Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimistic locking #588

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
97e794c
Optimistic locking
Nov 2, 2016
4811ef8
Versioning support with configurable column
Mar 1, 2017
7a1a0ff
Fix indentation
Mar 1, 2017
f6b1ee2
Fix indentation
Mar 1, 2017
e12a304
Fix broken tests
Mar 1, 2017
9fc71cd
Merge branch 'master' of git://github.com/neumino/thinky
Sep 20, 2017
4bf7a2c
Updated version number and ignore
Sep 20, 2017
1d7c5b5
Updated project name
Sep 20, 2017
7bf573b
Reverted project name
Sep 20, 2017
3aac42d
Debug statements
Sep 24, 2017
749b55b
Debug statements
Sep 24, 2017
7d6096d
Disabling optimistic locking temporarily
Sep 24, 2017
c13fc9a
Re-enabling optimistic locking with logging in case it fails again
Sep 24, 2017
dd2b4c1
On Model insert also pre-calculate versions
Sep 25, 2017
22e41c8
Test for batch insertions and versioning
Sep 25, 2017
984cd22
Fixed test with the right error description
Sep 25, 2017
1b2bc50
On Model insert also pre-calculate versions
Sep 20, 2017
b17bc46
Test for batch insertions and versioning
Sep 25, 2017
f67b809
Fixed test with the right error description
Sep 25, 2017
10c8d98
Merge branch 'master' of github.com:cur3n4/thinky
Sep 25, 2017
b795ffb
Better error message on versioning exception
Oct 4, 2017
0f32b1c
Adding option to disable validate invocations immediately after save
Jan 15, 2018
2670ec3
Adding option to disable validate invocations except for on save
Jan 15, 2018
22edb02
Adding option to save multiple documents in the model, running the va…
Jan 15, 2018
b7a8704
Adding option to validate multiple documents in the model
Jan 16, 2018
919e8ea
Add ability to access the parent element from a virtual
Sep 28, 2019
c34f094
Merge remote-tracking branch 'upstream/master'
Nov 20, 2019
c4b8684
Access the parent document when having a virtual inside an array
Nov 21, 2019
ed3f752
Fix thinky virtuals and arrays
Nov 21, 2019
ac8f078
Upgrade mocha
May 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
_site/
.*.swp
test.js
.idea/modules.xml
.idea/thinky.iml
.idea/vcs.xml
.idea/workspace.xml
3 changes: 2 additions & 1 deletion config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
exports.host = process.env['WERCKER_RETHINKDB_HOST'] || 'localhost';
exports.port = process.env['WERCKER_RETHINKDB_PORT'] || 28015;
exports.db = 'thinky_test';
exports.authKey = '';
exports.user = 'admin';
exports.password = 'admin';
66 changes: 56 additions & 10 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function Document(model, options) {
this._options = {};
this._options.timeFormat = (options.timeFormat != null) ? options.timeFormat : model.getOptions().timeFormat;
this._options.validate = (options.validate != null) ? options.validate : model.getOptions().validate;
this._options.version = (options.version != null) ? options.version : model.getOptions().version;

this._saved = options.saved || false; // Whether the document is saved or not

Expand Down Expand Up @@ -723,6 +724,25 @@ Document.prototype._onSavedBelongsTo = function(
self._saveSelf(copy, docToSave, belongsToKeysSaved, saveAll, savedModel, resolve, reject)
}

Document.prototype._calculateVersion = function () {
var self = this;
var model = self._getModel();
var r = self._getModel()._thinky.r;

var versionType = self._getModel()._schema._schema[model._version];
if (versionType === undefined) {
throw new Error("A version field with name: " + model._version + " cannot be found in the schema definition");
}
if (type.isDate(versionType)) {
return new Date();
}
else if (type.isNumber(versionType)) {
return self[model._version] === undefined ? 0 : self[model._version] + 1;
}
else {
throw new Error("Version columns can only be Date or Number");
}
}

/**
* Save the document on which `save` was called.
Expand Down Expand Up @@ -760,15 +780,36 @@ Document.prototype._saveSelf = function(
// may throw an error (for example if a Date has not a valid time).
var buildQuery = function () {
if (self.__proto__._saved === false) {
if (model._version) {
copy[model._version] = self._calculateVersion();
}
return querySaveSelf = r.table(constructor.getTableName())
.insert(copy, {returnChanges: 'always'})
.insert(copy, {returnChanges: 'always'});
}
else {
if (copy[model._pk] === undefined) {
throw new Error("The document was previously saved, but its primary key is undefined.");
}
return querySaveSelf = r.table(constructor.getTableName())
.get(copy[model._pk]).replace(copy, {returnChanges: 'always'})
else if (model._version) {
var versionType = self._getModel()._schema._schema[model._version];
if (versionType === undefined) {
throw new Error("A version field with name: " + model._version + " cannot be found in the schema definition");
}
var newVersion = self._calculateVersion();
return querySaveSelf = r.table(constructor.getTableName())
.get(copy[model._pk]).replace(function (row) {
const existingVersion = copy[model._version];
console.log('Replacing ' + constructor.getTableName() + ' version from', existingVersion, 'to', newVersion);
copy[model._version] = newVersion;
return r.branch(row(model._version).eq(existingVersion), copy, r.error("Versioning failed - there is a different version for " + constructor.getTableName() + " (with pk: " + copy[model._pk] + ") in the database from: " + existingVersion));
}, {returnChanges: 'always'});

}
else {
return querySaveSelf = r.table(constructor.getTableName())
.get(copy[model._pk]).replace(copy, {returnChanges: 'always'})
}

}
}

Expand Down Expand Up @@ -824,15 +865,20 @@ Document.prototype._onSaved = function(result, docToSave, saveAll, savedModel, r
self.setSaved();
self.emit('saved', self);

var promise = self.validate();
if (promise instanceof Promise) {
promise.then(function() {
if (!self._getModel().getOptions().validate === 'onlyOnSave') {
var promise = self.validate();
if (promise instanceof Promise) {
promise.then(function() {
self._saveMany(docToSave, saveAll, savedModel, resolve, reject)
}).error(reject);
}
else {
self._saveMany(docToSave, saveAll, savedModel, resolve, reject)
}
} else {
self._saveMany(docToSave, saveAll, savedModel, resolve, reject)
}).error(reject);
}
else {
self._saveMany(docToSave, saveAll, savedModel, resolve, reject)
}

}, reject);
}

Expand Down
Loading