Skip to content

Commit

Permalink
Merge pull request #35 from holidayextras/deadlocks
Browse files Browse the repository at this point in the history
Prevent ghost rows in the database
  • Loading branch information
theninj4 authored Jul 11, 2016
2 parents 5c57c9d + 1d6dc7a commit 5a9dfca
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- 2016-07-11 - v1.2.5
- 2016-07-11 - Fixing bug when concurrently updating the same resource id
- 2016-07-04 - v1.2.4
- 2016-07-04 - Use stricter MySQL transaction isolation READ_COMMITTED
- 2016-07-01 - v1.2.3
Expand Down
38 changes: 25 additions & 13 deletions lib/sqlHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ SqlStore.prototype.populate = function(callback) {
self.baseModel.sync().asCallback(cb);
},
function(cb) {
async.each(self.relationArray, function(model, ecb) {
async.eachSeries(self.relationArray, function(model, ecb) {
model.sync().asCallback(ecb);
}, cb);
},
function(cb) {
async.each(self.resourceConfig.examples, function(exampleJson, ecb) {
async.eachSeries(self.resourceConfig.examples, function(exampleJson, ecb) {
var validation = Joi.validate(exampleJson, self.resourceConfig.attributes);
if (validation.error) return ecb(validation.error);
self.create({ request: { type: self.resourceConfig.resource } }, validation.value, ecb);
Expand Down Expand Up @@ -225,6 +225,15 @@ SqlStore.prototype._fixObject = function(json) {

SqlStore.prototype._errorHandler = function(e, callback) {
// console.log(e, e.stack);
if (e.message.match(/^ER_LOCK_DEADLOCK/)) {
return callback({
status: "500",
code: "EMODIFIED",
title: "Resource Just Changed",
detail: "The resource you tried to mutate was modified by another request. Your request has been aborted."
});
}

return callback({
status: "500",
code: "EUNKNOWN",
Expand Down Expand Up @@ -321,7 +330,7 @@ SqlStore.prototype._dealWithTransaction = function(done, callback) {
});
};
var rollback = function(e) {
debug("Err", e);
debug("Err", transaction.name, e);
var a = function() {
if (e instanceof Error) return self._errorHandler(e, done);
return done(e);
Expand All @@ -338,9 +347,12 @@ SqlStore.prototype._dealWithTransaction = function(done, callback) {
};

SqlStore.prototype._clearAndSetMany = function(relationModel, prop, theResource, keyName, ucKeyName, t, taskCallback) {
async.map(theResource[keyName] || [], function(deadRow, acallback) {
deadRow.destroy(t).asCallback(acallback);
}, function(deleteError) {
var whereClause = { };
whereClause[theResource.type + "Id"] = theResource.id;
relationModel.destroy({
where: whereClause,
transaction: t.transaction
}).asCallback(function(deleteError) {
if (deleteError) return taskCallback(deleteError);

async.map(prop, function(item, acallback) {
Expand All @@ -354,7 +366,12 @@ SqlStore.prototype._clearAndSetMany = function(relationModel, prop, theResource,
};

SqlStore.prototype._clearAndSetOne = function(relationModel, prop, theResource, keyName, ucKeyName, t, taskCallback) {
var next = function(deleteError) {
var whereClause = { };
whereClause[theResource.type + "Id"] = theResource.id;
relationModel.destroy({
where: whereClause,
transaction: t.transaction
}).asCallback(function(deleteError) {
if (deleteError) return taskCallback(deleteError);
if (!prop) {
theResource["set" + ucKeyName](null, t).asCallback(taskCallback);
Expand All @@ -365,12 +382,7 @@ SqlStore.prototype._clearAndSetOne = function(relationModel, prop, theResource,
theResource["set" + ucKeyName](newRelationModel, t).asCallback(taskCallback);
});
}
}
if (theResource[keyName]) {
theResource[keyName].destroy(t).asCallback(next);
} else {
next();
}
});
};

SqlStore.prototype._clearAndSetRelationTables = function(theResource, partialResource, t, callback) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonapi-store-relationaldb",
"version": "1.2.4",
"version": "1.2.5",
"description": "Relational data store for jsonapi-server.",
"keywords": [
"json:api",
Expand Down Expand Up @@ -35,7 +35,7 @@
"blanket": "1.1.9",
"coveralls": "^2.11.9",
"eslint": "^2.11.0",
"jsonapi-server": "^1.15.0",
"jsonapi-server": "^1.15.4",
"mocha": "^2.5.3",
"mocha-lcov-reporter": "^1.2.0",
"mocha-performance": "^0.1.1",
Expand Down

0 comments on commit 5a9dfca

Please sign in to comment.