aboutsummaryrefslogtreecommitdiff
path: root/src/server/websocket.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/websocket.ts')
-rw-r--r--src/server/websocket.ts120
1 files changed, 98 insertions, 22 deletions
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index b33e76c0b..7d111f359 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -201,15 +201,18 @@ export namespace WebSocket {
function setField(socket: Socket, newValue: Transferable) {
Database.Instance.update(newValue.id, newValue, () =>
- socket.broadcast.emit(MessageStore.SetField.Message, newValue));
+ socket.broadcast.emit(MessageStore.SetField.Message, newValue)); // broadcast set value to all other clients
if (newValue.type === Types.Text) { // if the newValue has sring type, then it's suitable for searching -- pass it to SOLR
Search.updateDocument({ id: newValue.id, data: { set: (newValue as any).data } });
}
}
+ function GetRefFieldLocal([id, callback]: [string, (result?: Transferable) => void]) {
+ return Database.Instance.getDocument(id, callback);
+ }
function GetRefField([id, callback]: [string, (result?: Transferable) => void]) {
process.stdout.write(`.`);
- Database.Instance.getDocument(id, callback);
+ GetRefFieldLocal([id, callback]);
}
function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) {
@@ -271,33 +274,106 @@ export namespace WebSocket {
return typeof value === "string" ? value : value[0];
}
+ function addToListField(socket: Socket, diff: Diff, curListItems?: Transferable): void {
+ diff.diff.$set = diff.diff.$addToSet; delete diff.diff.$addToSet;// convert add to set to a query of the current fields, and then a set of the composition of the new fields with the old ones
+ const updatefield = Array.from(Object.keys(diff.diff.$set))[0];
+ const newListItems = diff.diff.$set[updatefield].fields;
+ const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields.filter((item: any) => item !== undefined) || [];
+ diff.diff.$set[updatefield].fields = [...curList, ...newListItems.filter((newItem: any) => newItem && !curList.some((curItem: any) => curItem.fieldId ? curItem.fieldId === newItem.fieldId : curItem.heading ? curItem.heading === newItem.heading : curItem === newItem))];
+ const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length;
+ delete diff.diff.length;
+ Database.Instance.update(diff.id, diff.diff,
+ () => {
+ if (sendBack) {
+ console.log("RET BACK");
+ const id = socket.id;
+ socket.id = "";
+ socket.broadcast.emit(MessageStore.UpdateField.Message, diff);
+ socket.id = id;
+ } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff);
+ dispatchNextOp(diff.id);
+ }, false);
+ }
+
+ function remFromListField(socket: Socket, diff: Diff, curListItems?: Transferable): void {
+ diff.diff.$set = diff.diff.$remFromSet; delete diff.diff.$remFromSet;
+ const updatefield = Array.from(Object.keys(diff.diff.$set))[0];
+ const remListItems = diff.diff.$set[updatefield].fields;
+ const curList = (curListItems as any)?.fields?.[updatefield.replace("fields.", "")]?.fields || [];
+ diff.diff.$set[updatefield].fields = curList?.filter((curItem: any) => !remListItems.some((remItem: any) => remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem));
+ const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length;
+ delete diff.diff.length;
+ Database.Instance.update(diff.id, diff.diff,
+ () => {
+ if (sendBack) {
+ console.log("SEND BACK");
+ const id = socket.id;
+ socket.id = "";
+ socket.broadcast.emit(MessageStore.UpdateField.Message, diff);
+ socket.id = id;
+ } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff);
+ dispatchNextOp(diff.id);
+ }, false);
+ }
+
+ const pendingOps = new Map<string, { diff: Diff, socket: Socket }[]>();
+
+ function dispatchNextOp(id: string) {
+ const next = pendingOps.get(id)!.shift();
+ if (next) {
+ const { diff, socket } = next;
+ if (diff.diff.$addToSet) {
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own
+ }
+ if (diff.diff.$remFromSet) {
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own
+ }
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => SetField(socket, diff, result)]);
+ }
+ if (!pendingOps.get(id)!.length) pendingOps.delete(id);
+ }
+
function UpdateField(socket: Socket, diff: Diff) {
+ if (pendingOps.has(diff.id)) {
+ pendingOps.get(diff.id)!.push({ diff, socket });
+ return true;
+ }
+ pendingOps.set(diff.id, [{ diff, socket }]);
+ if (diff.diff.$addToSet) {
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own
+ }
+ if (diff.diff.$remFromSet) {
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own
+ }
+ return GetRefFieldLocal([diff.id, (result?: Transferable) => SetField(socket, diff, result)]);
+ }
+ function SetField(socket: Socket, diff: Diff, curListItems?: Transferable) {
Database.Instance.update(diff.id, diff.diff,
() => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false);
const docfield = diff.diff.$set || diff.diff.$unset;
- if (!docfield) {
- return;
- }
- const update: any = { id: diff.id };
- let dynfield = false;
- for (let key in docfield) {
- if (!key.startsWith("fields.")) continue;
- dynfield = true;
- const val = docfield[key];
- key = key.substring(7);
- Object.values(suffixMap).forEach(suf => { update[key + getSuffix(suf)] = { set: null }; });
- const term = ToSearchTerm(val);
- if (term !== undefined) {
- const { suffix, value } = term;
- update[key + suffix] = { set: value };
- if (key.endsWith('lastModified')) {
- update["lastModified" + suffix] = value;
+ if (docfield) {
+ const update: any = { id: diff.id };
+ let dynfield = false;
+ for (let key in docfield) {
+ if (!key.startsWith("fields.")) continue;
+ dynfield = true;
+ const val = docfield[key];
+ key = key.substring(7);
+ Object.values(suffixMap).forEach(suf => { update[key + getSuffix(suf)] = { set: null }; });
+ const term = ToSearchTerm(val);
+ if (term !== undefined) {
+ const { suffix, value } = term;
+ update[key + suffix] = { set: value };
+ if (key.endsWith('lastModified')) {
+ update["lastModified" + suffix] = value;
+ }
}
}
+ if (dynfield) {
+ Search.updateDocument(update);
+ }
}
- if (dynfield) {
- Search.updateDocument(update);
- }
+ dispatchNextOp(diff.id);
}
function DeleteField(socket: Socket, id: string) {