Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alecgibson committed May 29, 2024
1 parent 7abe650 commit ff43a8d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
14 changes: 13 additions & 1 deletion lib/submit-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var ot = require('./ot');
var projections = require('./projections');
var ShareDBError = require('./error');
var types = require('./types');
var akg = require('../test/akg-debug');

var ERROR_CODE = ShareDBError.CODES;

Expand Down Expand Up @@ -91,17 +92,21 @@ SubmitRequest.prototype.submit = function(callback) {
// Send a special projection so that getSnapshot knows to return all fields.
// With a null projection, it strips document metadata
var fields = {$submit: true};
akg.debug('submit', collection, id, op);

var snapshotOptions = {};
snapshotOptions.agentCustom = request.agent.custom;
backend.db.getSnapshot(collection, id, fields, snapshotOptions, function(err, snapshot) {
if (err) return callback(err);
akg.debug('get snapshot', collection, id, snapshot);

request.snapshot = snapshot;
request._addSnapshotMeta();

if (op.v == null) {
akg.debug('null version');
if (op.create && snapshot.type && op.src) {
akg.debug('check create collision');
// If the document was already created by another op, we will return a
// 'Document already exists' error in response and fail to submit this
// op. However, this could also happen in the case that the op was
Expand All @@ -110,7 +115,8 @@ SubmitRequest.prototype.submit = function(callback) {
// must get the past ops and check their src and seq values to
// differentiate.
request._fetchCreateOpVersion(function(error, version) {
if (err) return callback(err);
akg.debug('fetch create op version returned', error, version);
if (error) return callback(error);
if (version == null) {
callback(request.alreadyCreatedError());
} else {
Expand All @@ -131,6 +137,7 @@ SubmitRequest.prototype.submit = function(callback) {
if (op.v === snapshot.v) {
// The snapshot hasn't changed since the op's base version. Apply
// without transforming the op
akg.debug('op and snapshot version same');
return request.apply(callback);
}

Expand All @@ -143,6 +150,7 @@ SubmitRequest.prototype.submit = function(callback) {
// Transform the op up to the current snapshot version, then apply
var from = op.v;
backend.db.getOpsToSnapshot(collection, id, from, snapshot, {metadata: true}, function(err, ops) {
akg.debug('getOpsToSnapshot', from, snapshot, ops);
if (err) return callback(err);

if (ops.length !== snapshot.v - from) {
Expand Down Expand Up @@ -212,6 +220,7 @@ SubmitRequest.prototype.commit = function(callback) {
request.snapshot,
request.options,
function(err, succeeded) {
akg.debug('commit result', request.collection, request.id, request.op, request.snapshot, err, succeeded);
if (err) return callback(err);
if (!succeeded) {
// Between our fetch and our call to commit, another client committed an
Expand All @@ -237,6 +246,7 @@ SubmitRequest.prototype.commit = function(callback) {
};

SubmitRequest.prototype.retry = function(callback) {
akg.debug('retry');
this.retries++;
if (this.maxRetries != null && this.retries > this.maxRetries) {
return callback(this.maxRetriesError());
Expand Down Expand Up @@ -301,6 +311,7 @@ SubmitRequest.prototype._shouldSaveMilestoneSnapshot = function(snapshot) {

SubmitRequest.prototype._fetchCreateOpVersion = function(callback) {
var create = this.snapshot.m._create;
akg.debug('got create meta', create);
if (create) {
var version = (create.src === this.op.src && create.seq === this.op.seq) ? create.v : null;
return callback(null, version);
Expand All @@ -310,6 +321,7 @@ SubmitRequest.prototype._fetchCreateOpVersion = function(callback) {
// This can happen if a client tries to re-create or resubmit a create op to
// a "legacy" snapshot that existed before we started adding the meta (should
// be uncommon) or when using a driver that doesn't support metadata (eg Postgres).
akg.debug('get committed op version...');
this.backend.db.getCommittedOpVersion(this.collection, this.id, this.snapshot, this.op, null, callback);
};

Expand Down
9 changes: 9 additions & 0 deletions test/akg-debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function debug() {
if (!module.exports.enabled) return;
console.log.apply(console, arguments);
}

module.exports = {
enabled: false,
debug: debug
};
33 changes: 28 additions & 5 deletions test/client/submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ var deserializedType = require('./deserialized-type');
var numberType = require('./number-type');
var errorHandler = require('../util').errorHandler;
var richText = require('rich-text');
var MemoryDB = require('../../lib/db/memory');
types.register(deserializedType.type);
types.register(deserializedType.type2);
types.register(numberType.type);
types.register(richText.type);
var akg = require('../akg-debug');

module.exports = function() {
describe('client submit', function() {
Expand Down Expand Up @@ -210,13 +210,17 @@ module.exports = function() {

describe('create', function() {
describe('metadata enabled', function() {
afterEach(function() {
akg.enabled = false;
});

runCreateTests();
});

describe('no snapshot metadata available', function() {
beforeEach(function() {
var getSnapshot = MemoryDB.prototype.getSnapshot;
sinon.stub(MemoryDB.prototype, 'getSnapshot')
var getSnapshot = this.backend.db.getSnapshot;
sinon.stub(this.backend.db, 'getSnapshot')
.callsFake(function() {
var args = Array.from(arguments);
var callback = args.pop();
Expand All @@ -229,6 +233,7 @@ module.exports = function() {
});

afterEach(function() {
akg.enabled = false;
sinon.restore();
});

Expand Down Expand Up @@ -297,27 +302,45 @@ module.exports = function() {
});

it('does not fail when resubmitting a create op on a doc that was deleted', function(done) {
akg.enabled = true;
console.log('> START TEST');
var backend = this.backend;
var connection1 = backend.connect();
var connection2 = backend.connect();
var doc1 = connection1.get('dogs', 'fido');
var doc2 = connection2.get('dogs', 'fido');

async.series([
doc1.create.bind(doc1, {age: 3}),
doc1.del.bind(doc1),
function(next) {
console.log('doc1 create...');
doc1.create({age: 123}, function(error) {
console.log('doc1 created', error);
next(error);
});
},
function(next) {
console.log('doc1 del...');
doc1.del(function(error) {
console.log('doc1 deleted', error);
next(error);
});
},
function(next) {
var submitted = false;
backend.use('submit', function(request, next) {
if (!submitted) {
submitted = true;
console.log('reconnecting connection2');
connection2.close();
backend.connect(connection2);
}
next();
});

console.log('doc2 create...');
doc2.create({name: 'Fido'}, function(error) {
console.log('doc2 created', error);
console.log('doc2 version', doc2.version);
expect(doc2.version).to.equal(3);
next(error);
});
Expand Down

0 comments on commit ff43a8d

Please sign in to comment.