Lock collection navigation tree changes

This commit is contained in:
Jori Lallo
2017-12-09 15:04:55 -08:00
parent 7af2ff20a8
commit c5e2bb2432
2 changed files with 22 additions and 1 deletions

View File

@ -2,6 +2,7 @@
import slug from 'slug'; import slug from 'slug';
import randomstring from 'randomstring'; import randomstring from 'randomstring';
import { DataTypes, sequelize } from '../sequelize'; import { DataTypes, sequelize } from '../sequelize';
import { asyncLock } from '../redis';
import Document from './Document'; import Document from './Document';
import Event from './Event'; import Event from './Event';
import _ from 'lodash'; import _ from 'lodash';
@ -111,6 +112,9 @@ Collection.prototype.addDocumentToStructure = async function(
index, index,
}; };
// documentStructure can only be updated by one request at the time
const unlock = await asyncLock(`collection-${this.id}`);
// If moving existing document with children, use existing structure to // If moving existing document with children, use existing structure to
// keep everything in shape and not loose documents // keep everything in shape and not loose documents
const documentJson = { const documentJson = {
@ -158,6 +162,8 @@ Collection.prototype.addDocumentToStructure = async function(
teamId: this.teamId, teamId: this.teamId,
}); });
unlock();
return this; return this;
}; };
@ -166,6 +172,10 @@ Collection.prototype.addDocumentToStructure = async function(
*/ */
Collection.prototype.updateDocument = async function(updatedDocument) { Collection.prototype.updateDocument = async function(updatedDocument) {
if (!this.documentStructure) return; if (!this.documentStructure) return;
// documentStructure can only be updated by one request at the time
const unlock = await asyncLock(`collection-${this.id}`);
const { id } = updatedDocument; const { id } = updatedDocument;
const updateChildren = documents => { const updateChildren = documents => {
@ -184,6 +194,7 @@ Collection.prototype.updateDocument = async function(updatedDocument) {
this.documentStructure = updateChildren(this.documentStructure); this.documentStructure = updateChildren(this.documentStructure);
await this.save(); await this.save();
unlock();
return this; return this;
}; };
@ -216,7 +227,12 @@ Collection.prototype.removeDocument = async function(
options: DeleteDocumentOptions = { deleteDocument: true } options: DeleteDocumentOptions = { deleteDocument: true }
) { ) {
if (!this.documentStructure) return; if (!this.documentStructure) return;
let returnValue; let returnValue;
// documentStructure can only be updated by one request at the time
const unlock = await asyncLock('testLock');
const existingData = { const existingData = {
old: this.documentStructure, old: this.documentStructure,
documentId: document, documentId: document,
@ -280,6 +296,8 @@ Collection.prototype.removeDocument = async function(
teamId: this.teamId, teamId: this.teamId,
}); });
await unlock();
return returnValue; return returnValue;
}; };

View File

@ -5,4 +5,7 @@ import redisLock from 'redis-lock';
const client = redis.createClient(process.env.REDIS_URL); const client = redis.createClient(process.env.REDIS_URL);
const lock = redisLock(client); const lock = redisLock(client);
export { client, lock }; const asyncLock = (lockName: string) =>
new Promise(resolve => lock(lockName, unlock => resolve(unlock)));
export { client, asyncLock };