Skip to content
This repository has been archived by the owner on Sep 13, 2019. It is now read-only.

Fix Bug 918952 - Add makeid to Goggles project model #28

Merged
merged 1 commit into from Sep 23, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -2,3 +2,16 @@ X-ray goggles on Node.js
========================

This is a reboot of the xray goggles, so that it is served as a node app.

Migration
---------

Various scripts are present that will assist in migrating old data sets along with Node.js scripts to update old records.

* `migrations/09052013-add-makeid-column.sql`
* Used to add the `makeid` to the `ThimbleProject` data model. Using the script will depend on your SQL managing environment, but here's an example of using it in a commandline prompt:
* `mysql < migrations/09052013-add-makeid-column.sql` - Assumes you have already done `use <DB_NAME>`

* `migrations/ThimbleProjectMigration.js`
* Used to retrieve the `makeid` for any `ThimbleProject` that has already been published to the **MakeAPI**. This only needs to be run once.
* `node migrations/ThimbleProjectMakeIDMigration.js` will execute this script, assuming proper `.env` variables have already been setup (instructions above).
5 changes: 5 additions & 0 deletions lib/database.js
Expand Up @@ -48,6 +48,11 @@ module.exports = function databaseHandleConstructor(modelName, options, legacyOp
* db function object that we return
*/
var databaseAPI = {
/**
* Accessor to the ThimbleProjects model.
*/
model: model,

/**
* if there is an originalURL, and that url is already
* "ours", AND this is an edit operation, then this is
Expand Down
70 changes: 47 additions & 23 deletions lib/middleware.js
Expand Up @@ -182,8 +182,12 @@ module.exports = function middlewareConstructor(env) {
userid: req.session.email,
url: req.publishedUrl
};
db.updateUrl(options, function(err) {
next(err);
db.updateUrl(options, function(err, project) {
if (err) {
return next(err);
}
req.project = project;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

project is not defined in this scope

next();
});
};
},
Expand Down Expand Up @@ -343,6 +347,7 @@ module.exports = function middlewareConstructor(env) {
publishMake: function(make) {
return function(req, res, next) {
var metaData = req.body.metaData,
project = req.project,
options = {
thumbnail: metaData.thumbnail,
contentType: "application/x-x-ray-goggles",
Expand All @@ -362,31 +367,50 @@ module.exports = function middlewareConstructor(env) {
function finalizePublishMake(err, result) {
if (err) {
metrics.increment('makeapi.publish.error');
next(err);
} else {
metrics.increment('makeapi.publish.success');
next();
return next(err);
}

metrics.increment('makeapi.publish.success');
next();
}

// Publish the make to the makeapi.
// If it exists and we own it, update it.
// Otherwise create a new one.
make.search({
email: req.session.email,
url: req.oldUrl || req.publishedUrl
}, function(err, results) {
if (err) {
return finalizePublishMake(err);
}
if (project.makeid) {
make.update(project.makeid, options, finalizePublishMake);
} else {

var result = results[0];
if (result) {
make.update(result.id, options, finalizePublishMake);
} else {
make.create(options, finalizePublishMake);
}
});
make.search({
email: req.session.email,
url: req.oldUrl || req.publishedUrl
}, function(err, results) {
if (err) {
return finalizePublishMake(err);
}

var result = results[0];

if (result) {
project.updateAttributes({ makeid: result.id })
.error(function(err) {
return next(err);
})
.success(function(updatedProject) {
req.project = updatedProject;
make.update(updatedProject.makeid, options, finalizePublishMake);
});
} else {
make.create(options, function( err, make ) {
project.updateAttributes({ makeid: make.id })
.error(function(err) {
return next(err);
})
.success(function(updatedProject) {
req.project = updatedProject;
finalizePublishMake( err, make );
});
});
}
});
}
};
},

Expand Down
5 changes: 5 additions & 0 deletions lib/models/thimbleproject.js
Expand Up @@ -32,6 +32,11 @@ module.exports = function(sequelize, DataTypes) {
// the <title> of the HTML data
title: {
type: DataTypes.STRING
},
// The id of this project's corresponding make
makeid: {
type: "CHAR(40)",
unique: true
}
},{
// let Sequelize handle timestamping
Expand Down
3 changes: 3 additions & 0 deletions migrations/09202013-add-makeid-column.sql
@@ -0,0 +1,3 @@
# Add the makeid column to the butter database
ALTER TABLE ThimbleProjects ADD COLUMN makeid CHAR(40);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add DEFAULT NULL after the datatype.

Add a second line to the migration script:
ALTER TABLE ThimbleProjects ADD UNIQUE KEY(makeid);

This will make sure we don't have two projects pointing at the same makeid. This will not conflict with the default value of NULL because NULL != NULL, oddly enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? Sounds like mongo is wrong then if with SQL NULL != NULL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in javascript null == null and null === null but SQL has NULL != NULL: http://dev.mysql.com/doc/refman/5.6/en/problems-with-null.html paragraph 4

ALTER TABLE ThimbleProjects ADD UNIQUE KEY(makeid);
90 changes: 90 additions & 0 deletions migrations/ThimbleProjectMakeIDMigration.js
@@ -0,0 +1,90 @@
/**
* This Script is designed to upgrade existing thimble projects
* that are already in the MakeAPI. It will grab each makes id
* and find it's corresponding Thimble project and update it
* with that makes id.
**/

var async = require( "async" ),
habitat = require( "habitat" ),
env;

habitat.load();
env = new habitat();

// Database information
var dbConfig = env.get( "DB" ),
db = require( "../lib/database" ),
dbAPI = db( "ThimbleProject", dbConfig ),
makeEnv = env.get( "make" ),
makeapi,
utils = require( "../lib/utils" ),
page = 1,
LIMIT = 1000,
completed,
q;

makeapi = require( "makeapi-client" )({
apiURL: makeEnv.endpoint,
hawk: {
key: makeEnv.privatekey,
id: makeEnv.publickey,
algorithm: "sha256"
}
});

function processGogglesMake( make, asyncCallback ) {
dbAPI.model.find({ where: {
title: utils.slugify( make.title ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I was thinking here; if we have the url, do we need to search by title?

url: make.url,
makeid: null
}})
.error( asyncCallback )
.success(function( project ) {
if ( project && !project.makeid ) {
project.updateAttributes({
makeid: make.id
})
.error( asyncCallback )
.success(function( updatedProject ) {
asyncCallback( null, updatedProject );
});
} else {
asyncCallback( null, project );
}
});
}

function getMakes( page ) {
makeapi
.contentType( "application/x-x-ray-goggles" )
.page( page )
.limit( LIMIT )
.then(function( err, results, count ) {
if ( err ) {
console.log( "Something went horribly wrong: " + err.toString() );
return process.exit( 1 );
}

completed += results.length;
q.push( results, function( error ) {
if ( error ) {
console.log( "Something went horribly wrong: " + error.toString() );
return process.exit( 1 );
}

if ( completed < count ) {
page++;
getMakes( page );
}
});
});
}

q = async.queue( processGogglesMake, 5 );

q.drain = function() {
console.log( "Hooray! All of the goggles makes have been updated" );
};

getMakes( page );
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -7,6 +7,7 @@
"postinstall": "bower install"
},
"dependencies": {
"async": "0.2.9",
"bower": "1.2.3",
"express": "3.2.0",
"glob": "3.2.3",
Expand Down