Skip to content

Commit

Permalink
datastore: concat transactional mutations (#1341)
Browse files Browse the repository at this point in the history
* datastore: concat transactional mutations

* extract the array flattening bit

* fix method ordering & system test
  • Loading branch information
stephenplusplus authored and callmehiphop committed May 26, 2016
1 parent d0553b8 commit ec5a8f6
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 52 deletions.
16 changes: 9 additions & 7 deletions lib/datastore/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
'use strict';

var arrify = require('arrify');
var extend = require('extend');
var flatten = require('lodash.flatten');
var nodeutil = require('util');
var prop = require('propprop');

/**
* @type {module:datastore/request}
Expand Down Expand Up @@ -375,9 +376,11 @@ Transaction.prototype.commit_ = function(callback) {
}
})

// Group entities together by action (delete or save).
// Group entities together by method: `save` mutations, then `delete`. Note:
// `save` mutations being first is required to maintain order when assigning
// IDs to incomplete keys.
.sort(function(a, b) {
return a.method > b.method ? 1 : a.method < b.method ? -1 : 0;
return a.method < b.method ? 1 : a.method > b.method ? -1 : 0;
})

// Group arguments together so that we only make one call to each method.
Expand Down Expand Up @@ -418,10 +421,9 @@ Transaction.prototype.commit_ = function(callback) {

// Take the `req` array built previously, and merge them into one request to
// send as the final transactional commit.
var reqOpts = this.requests_.reduce(function(acc, req) {
return extend(true, acc, req);
}, {});

var reqOpts = {
mutations: flatten(this.requests_.map(prop('mutations')))
};

this.request_(protoOpts, reqOpts, function(err, resp) {
if (err) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"grpc": "^0.14.1",
"hash-stream-validation": "^0.1.0",
"is": "^3.0.1",
"lodash.flatten": "^4.2.0",
"methmeth": "^1.0.0",
"mime-types": "^2.0.8",
"modelo": "^4.2.0",
Expand Down
78 changes: 41 additions & 37 deletions system-test/datastore.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,48 +690,52 @@ describe('Datastore', function() {
var key = datastore.key(['Company', 'Google']);
var incompleteKey = datastore.key('Company');

datastore.runInTransaction(function(t, tDone) {
t.delete(deleteKey);

t.save([
{
key: key,
data: { rating: 10 }
},
{
key: incompleteKey,
data: { rating: 100 }
}
]);

tDone();
datastore.save({
key: deleteKey,
data: {}
}, function(err) {
assert.ifError(err);

// Incomplete key should have been given an ID.
assert.strictEqual(incompleteKey.path.length, 2);

async.parallel([
// The key queued for deletion should have been deleted.
function(done) {
datastore.get(deleteKey, function(err, entity) {
assert.ifError(err);
assert.strictEqual(typeof entity, 'undefined');
done();
});
},
datastore.runInTransaction(function(t, tDone) {
t.delete(deleteKey);

t.save([
{
key: key,
data: { rating: 10 }
},
{
key: incompleteKey,
data: { rating: 100 }
}
]);

// Data should have been updated on the key.
function(done) {
datastore.get(key, function(err, entity) {
assert.ifError(err);
assert.strictEqual(entity.data.rating, 10);
done();
});
}
], function(err) {
tDone();
}, function(err) {
assert.ifError(err);
datastore.delete([key, incompleteKey], done);

// Incomplete key should have been given an ID.
assert.strictEqual(incompleteKey.path.length, 2);

async.parallel([
// The key queued for deletion should have been deleted.
function(callback) {
datastore.get(deleteKey, function(err, entity) {
assert.ifError(err);
assert.strictEqual(typeof entity, 'undefined');
callback();
});
},

// Data should have been updated on the key.
function(callback) {
datastore.get(key, function(err, entity) {
assert.ifError(err);
assert.strictEqual(entity.data.rating, 10);
callback();
});
}
], done);
});
});
});
Expand Down
32 changes: 24 additions & 8 deletions test/datastore/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
var arrify = require('arrify');
var assert = require('assert');
var entity = require('../../lib/datastore/entity.js');
var extend = require('extend');
var mockery = require('mockery-next');
var util = require('../../lib/common/util.js');

Expand Down Expand Up @@ -334,9 +333,11 @@ describe('Transaction', function() {
assert.equal(saveCalled, 1);

assert.equal(args.length, 2);

// Save arguments must come first.
assert.deepEqual(args, [
[deleteArg1, deleteArg2],
[saveArg1, saveArg2]
[saveArg1, saveArg2],
[deleteArg1, deleteArg2]
]);
});

Expand Down Expand Up @@ -364,14 +365,29 @@ describe('Transaction', function() {

it('should send the built request object', function(done) {
transaction.requests_ = [
{ a: 'b', c: 'd' },
{ e: 'f', g: 'h' }
{
mutations: [
{ a: 'b' },
{ c: 'd' }
]
},
{
mutations: [
{ e: 'f' },
{ g: 'h' }
]
}
];

transaction.request_ = function(protoOpts, reqOpts) {
var req1 = transaction.requests_[0];
var req2 = transaction.requests_[1];
assert.deepEqual(reqOpts, extend(req1, req2));
assert.deepEqual(reqOpts, {
mutations: [
{ a: 'b' },
{ c: 'd' },
{ e: 'f' },
{ g: 'h' }
]
});
done();
};

Expand Down

0 comments on commit ec5a8f6

Please sign in to comment.