document-drive 1.17.2 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/package.json +11 -9
- package/src/server/index.ts +341 -232
- package/src/server/listener/manager.ts +265 -144
- package/src/server/listener/transmitter/pull-responder.ts +64 -11
- package/src/server/listener/transmitter/switchboard-push.ts +56 -13
- package/src/server/types.ts +114 -144
package/src/server/index.ts
CHANGED
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
OperationError,
|
|
69
69
|
SynchronizationUnitNotFoundError,
|
|
70
70
|
} from "./error";
|
|
71
|
-
import { ListenerManager } from "./listener
|
|
71
|
+
import { ListenerManager } from "./listener";
|
|
72
72
|
import {
|
|
73
73
|
CancelPullLoop,
|
|
74
74
|
InternalTransmitter,
|
|
@@ -76,9 +76,9 @@ import {
|
|
|
76
76
|
ITransmitter,
|
|
77
77
|
PullResponderTransmitter,
|
|
78
78
|
StrandUpdateSource,
|
|
79
|
+
SwitchboardPushTransmitter,
|
|
79
80
|
} from "./listener/transmitter";
|
|
80
81
|
import {
|
|
81
|
-
AbstractDocumentDriveServer,
|
|
82
82
|
AddOperationOptions,
|
|
83
83
|
DefaultListenerManagerOptions,
|
|
84
84
|
DocumentDriveServerOptions,
|
|
@@ -86,7 +86,9 @@ import {
|
|
|
86
86
|
GetDocumentOptions,
|
|
87
87
|
GetStrandsOptions,
|
|
88
88
|
IBaseDocumentDriveServer,
|
|
89
|
+
IListenerManager,
|
|
89
90
|
IOperationResult,
|
|
91
|
+
Listener,
|
|
90
92
|
ListenerState,
|
|
91
93
|
RemoteDriveAccessLevel,
|
|
92
94
|
RemoteDriveOptions,
|
|
@@ -109,15 +111,47 @@ export * from "../read-mode";
|
|
|
109
111
|
|
|
110
112
|
export const PULL_DRIVE_INTERVAL = 5000;
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
interface ITransmitterFactory {
|
|
115
|
+
instance(
|
|
116
|
+
transmitterType: string,
|
|
117
|
+
listener: Listener,
|
|
118
|
+
driveServer: IBaseDocumentDriveServer,
|
|
119
|
+
): ITransmitter;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export class TransmitterFactory implements ITransmitterFactory {
|
|
123
|
+
private readonly listenerManager: IListenerManager;
|
|
124
|
+
|
|
125
|
+
constructor(listenerManager: IListenerManager) {
|
|
126
|
+
this.listenerManager = listenerManager;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
instance(
|
|
130
|
+
transmitterType: string,
|
|
131
|
+
listener: Listener,
|
|
132
|
+
driveServer: IBaseDocumentDriveServer,
|
|
133
|
+
): ITransmitter {
|
|
134
|
+
switch (transmitterType) {
|
|
135
|
+
case "SwitchboardPush": {
|
|
136
|
+
return new SwitchboardPushTransmitter(listener.callInfo!.data!);
|
|
137
|
+
}
|
|
138
|
+
case "Internal": {
|
|
139
|
+
return new InternalTransmitter(listener, driveServer);
|
|
140
|
+
}
|
|
141
|
+
default: {
|
|
142
|
+
return new PullResponderTransmitter(listener, this.listenerManager);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class BaseDocumentDriveServer implements IBaseDocumentDriveServer {
|
|
116
149
|
private emitter = createNanoEvents<DriveEvents>();
|
|
117
150
|
private cache: ICache;
|
|
118
151
|
private documentModels: DocumentModel[];
|
|
119
152
|
private storage: IDriveStorage;
|
|
120
|
-
private
|
|
153
|
+
private transmitterFactory: ITransmitterFactory;
|
|
154
|
+
private listenerManager: IListenerManager;
|
|
121
155
|
private triggerMap = new Map<
|
|
122
156
|
DocumentDriveState["id"],
|
|
123
157
|
Map<Trigger["id"], CancelPullLoop>
|
|
@@ -138,7 +172,6 @@ export class BaseDocumentDriveServer
|
|
|
138
172
|
queueManager: IQueueManager = new BaseQueueManager(),
|
|
139
173
|
options?: DocumentDriveServerOptions,
|
|
140
174
|
) {
|
|
141
|
-
super();
|
|
142
175
|
this.options = {
|
|
143
176
|
...options,
|
|
144
177
|
defaultDrives: {
|
|
@@ -154,11 +187,16 @@ export class BaseDocumentDriveServer
|
|
|
154
187
|
: options.taskQueueMethod,
|
|
155
188
|
};
|
|
156
189
|
|
|
157
|
-
this
|
|
190
|
+
// todo: pull this into the constructor -- there is a circular dependency right now
|
|
191
|
+
this.listenerManager = new ListenerManager(
|
|
158
192
|
this,
|
|
159
193
|
undefined,
|
|
160
|
-
options
|
|
194
|
+
this.options.listenerManager,
|
|
161
195
|
);
|
|
196
|
+
|
|
197
|
+
// todo: pull this into the constructor, depends on listenerManager
|
|
198
|
+
this.transmitterFactory = new TransmitterFactory(this.listenerManager);
|
|
199
|
+
|
|
162
200
|
this.documentModels = documentModels;
|
|
163
201
|
this.storage = storage;
|
|
164
202
|
this.cache = cache;
|
|
@@ -491,7 +529,7 @@ export class BaseDocumentDriveServer
|
|
|
491
529
|
this.getSynchronizationUnitsRevision(driveId, syncUnits)
|
|
492
530
|
.then((syncUnitRevisions) => {
|
|
493
531
|
for (const revision of syncUnitRevisions) {
|
|
494
|
-
this.
|
|
532
|
+
this.listenerManager
|
|
495
533
|
.updateListenerRevision(
|
|
496
534
|
pushListener.listenerId,
|
|
497
535
|
driveId,
|
|
@@ -584,6 +622,8 @@ export class BaseDocumentDriveServer
|
|
|
584
622
|
}
|
|
585
623
|
|
|
586
624
|
private async _initialize() {
|
|
625
|
+
await this.listenerManager.initialize(this.handleListenerError);
|
|
626
|
+
|
|
587
627
|
await this.queueManager.init(this.queueDelegate, (error) => {
|
|
588
628
|
logger.error(`Error initializing queue manager`, error);
|
|
589
629
|
errors.push(error);
|
|
@@ -608,22 +648,6 @@ export class BaseDocumentDriveServer
|
|
|
608
648
|
await this.defaultDrivesManager.initializeDefaultRemoteDrives();
|
|
609
649
|
}
|
|
610
650
|
|
|
611
|
-
// if network connect comes back online
|
|
612
|
-
// then triggers the listeners update
|
|
613
|
-
if (typeof window !== "undefined") {
|
|
614
|
-
window.addEventListener("online", () => {
|
|
615
|
-
this.listenerStateManager
|
|
616
|
-
.triggerUpdate(
|
|
617
|
-
false,
|
|
618
|
-
{ type: "local" },
|
|
619
|
-
this.handleListenerError.bind(this),
|
|
620
|
-
)
|
|
621
|
-
.catch((error) => {
|
|
622
|
-
logger.error("Non handled error updating listeners", error);
|
|
623
|
-
});
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
|
|
627
651
|
return errors.length === 0 ? null : errors;
|
|
628
652
|
}
|
|
629
653
|
|
|
@@ -635,7 +659,36 @@ export class BaseDocumentDriveServer
|
|
|
635
659
|
await this.startSyncRemoteDrive(driveId);
|
|
636
660
|
}
|
|
637
661
|
|
|
638
|
-
|
|
662
|
+
for (const zodListener of drive.state.local.listeners) {
|
|
663
|
+
const transmitter = this.transmitterFactory.instance(
|
|
664
|
+
zodListener.callInfo?.transmitterType ?? "",
|
|
665
|
+
{
|
|
666
|
+
driveId,
|
|
667
|
+
listenerId: zodListener.listenerId,
|
|
668
|
+
block: zodListener.block,
|
|
669
|
+
filter: zodListener.filter,
|
|
670
|
+
system: zodListener.system,
|
|
671
|
+
label: zodListener.label || undefined,
|
|
672
|
+
callInfo: zodListener.callInfo || undefined,
|
|
673
|
+
},
|
|
674
|
+
this,
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
await this.listenerManager.setListener(driveId, {
|
|
678
|
+
block: zodListener.block,
|
|
679
|
+
driveId: drive.state.global.id,
|
|
680
|
+
filter: {
|
|
681
|
+
branch: zodListener.filter.branch ?? [],
|
|
682
|
+
documentId: zodListener.filter.documentId ?? [],
|
|
683
|
+
documentType: zodListener.filter.documentType,
|
|
684
|
+
scope: zodListener.filter.scope ?? [],
|
|
685
|
+
},
|
|
686
|
+
listenerId: zodListener.listenerId,
|
|
687
|
+
system: zodListener.system,
|
|
688
|
+
label: zodListener.label ?? "",
|
|
689
|
+
transmitter,
|
|
690
|
+
});
|
|
691
|
+
}
|
|
639
692
|
}
|
|
640
693
|
|
|
641
694
|
public async getSynchronizationUnits(
|
|
@@ -899,8 +952,8 @@ export class BaseDocumentDriveServer
|
|
|
899
952
|
return [...this.documentModels];
|
|
900
953
|
}
|
|
901
954
|
|
|
902
|
-
async addDrive(
|
|
903
|
-
const id =
|
|
955
|
+
async addDrive(input: DriveInput): Promise<DocumentDriveDocument> {
|
|
956
|
+
const id = input.global.id || generateUUID();
|
|
904
957
|
if (!id) {
|
|
905
958
|
throw new Error("Invalid Drive Id");
|
|
906
959
|
}
|
|
@@ -911,13 +964,13 @@ export class BaseDocumentDriveServer
|
|
|
911
964
|
}
|
|
912
965
|
|
|
913
966
|
const document = utils.createDocument({
|
|
914
|
-
state:
|
|
967
|
+
state: input,
|
|
915
968
|
});
|
|
916
969
|
|
|
917
970
|
await this.storage.createDrive(id, document);
|
|
918
971
|
|
|
919
|
-
if (
|
|
920
|
-
await this.cache.deleteDocument("drives-slug",
|
|
972
|
+
if (input.global.slug) {
|
|
973
|
+
await this.cache.deleteDocument("drives-slug", input.global.slug);
|
|
921
974
|
}
|
|
922
975
|
|
|
923
976
|
await this._initializeDrive(id);
|
|
@@ -966,13 +1019,13 @@ export class BaseDocumentDriveServer
|
|
|
966
1019
|
}
|
|
967
1020
|
|
|
968
1021
|
public async registerPullResponderTrigger(
|
|
969
|
-
|
|
1022
|
+
driveId: string,
|
|
970
1023
|
url: string,
|
|
971
1024
|
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval">,
|
|
972
1025
|
) {
|
|
973
1026
|
const pullTrigger =
|
|
974
1027
|
await PullResponderTransmitter.createPullResponderTrigger(
|
|
975
|
-
|
|
1028
|
+
driveId,
|
|
976
1029
|
url,
|
|
977
1030
|
options,
|
|
978
1031
|
);
|
|
@@ -980,12 +1033,12 @@ export class BaseDocumentDriveServer
|
|
|
980
1033
|
return pullTrigger;
|
|
981
1034
|
}
|
|
982
1035
|
|
|
983
|
-
async deleteDrive(
|
|
1036
|
+
async deleteDrive(driveId: string) {
|
|
984
1037
|
const result = await Promise.allSettled([
|
|
985
|
-
this.stopSyncRemoteDrive(
|
|
986
|
-
this.
|
|
987
|
-
this.cache.deleteDocument("drives",
|
|
988
|
-
this.storage.deleteDrive(
|
|
1038
|
+
this.stopSyncRemoteDrive(driveId),
|
|
1039
|
+
this.listenerManager.removeDrive(driveId),
|
|
1040
|
+
this.cache.deleteDocument("drives", driveId),
|
|
1041
|
+
this.storage.deleteDrive(driveId),
|
|
989
1042
|
]);
|
|
990
1043
|
|
|
991
1044
|
result.forEach((r) => {
|
|
@@ -999,10 +1052,10 @@ export class BaseDocumentDriveServer
|
|
|
999
1052
|
return this.storage.getDrives();
|
|
1000
1053
|
}
|
|
1001
1054
|
|
|
1002
|
-
async getDrive(
|
|
1055
|
+
async getDrive(driveId: string, options?: GetDocumentOptions) {
|
|
1003
1056
|
let document: DocumentDriveDocument | undefined;
|
|
1004
1057
|
try {
|
|
1005
|
-
const cachedDocument = await this.cache.getDocument("drives",
|
|
1058
|
+
const cachedDocument = await this.cache.getDocument("drives", driveId); // TODO support GetDocumentOptions
|
|
1006
1059
|
if (cachedDocument && isDocumentDrive(cachedDocument)) {
|
|
1007
1060
|
document = cachedDocument;
|
|
1008
1061
|
if (isAtRevision(document, options?.revisions)) {
|
|
@@ -1012,13 +1065,13 @@ export class BaseDocumentDriveServer
|
|
|
1012
1065
|
} catch (e) {
|
|
1013
1066
|
logger.error("Error getting drive from cache", e);
|
|
1014
1067
|
}
|
|
1015
|
-
const driveStorage = document ?? (await this.storage.getDrive(
|
|
1068
|
+
const driveStorage = document ?? (await this.storage.getDrive(driveId));
|
|
1016
1069
|
const result = this._buildDocument(driveStorage, options);
|
|
1017
1070
|
if (!isDocumentDrive(result)) {
|
|
1018
|
-
throw new Error(`Document with id ${
|
|
1071
|
+
throw new Error(`Document with id ${driveId} is not a Document Drive`);
|
|
1019
1072
|
} else {
|
|
1020
1073
|
if (!options?.revisions) {
|
|
1021
|
-
this.cache.setDocument("drives",
|
|
1074
|
+
this.cache.setDocument("drives", driveId, result).catch(logger.error);
|
|
1022
1075
|
}
|
|
1023
1076
|
return result;
|
|
1024
1077
|
}
|
|
@@ -1044,10 +1097,14 @@ export class BaseDocumentDriveServer
|
|
|
1044
1097
|
}
|
|
1045
1098
|
}
|
|
1046
1099
|
|
|
1047
|
-
async getDocument(
|
|
1100
|
+
async getDocument(
|
|
1101
|
+
driveId: string,
|
|
1102
|
+
documentId: string,
|
|
1103
|
+
options?: GetDocumentOptions,
|
|
1104
|
+
) {
|
|
1048
1105
|
let cachedDocument: Document | undefined;
|
|
1049
1106
|
try {
|
|
1050
|
-
cachedDocument = await this.cache.getDocument(
|
|
1107
|
+
cachedDocument = await this.cache.getDocument(driveId, documentId); // TODO support GetDocumentOptions
|
|
1051
1108
|
if (cachedDocument && isAtRevision(cachedDocument, options?.revisions)) {
|
|
1052
1109
|
return cachedDocument;
|
|
1053
1110
|
}
|
|
@@ -1055,17 +1112,17 @@ export class BaseDocumentDriveServer
|
|
|
1055
1112
|
logger.error("Error getting document from cache", e);
|
|
1056
1113
|
}
|
|
1057
1114
|
const documentStorage =
|
|
1058
|
-
cachedDocument ?? (await this.storage.getDocument(
|
|
1115
|
+
cachedDocument ?? (await this.storage.getDocument(driveId, documentId));
|
|
1059
1116
|
const document = this._buildDocument(documentStorage, options);
|
|
1060
1117
|
|
|
1061
1118
|
if (!options?.revisions) {
|
|
1062
|
-
this.cache.setDocument(
|
|
1119
|
+
this.cache.setDocument(driveId, documentId, document).catch(logger.error);
|
|
1063
1120
|
}
|
|
1064
1121
|
return document;
|
|
1065
1122
|
}
|
|
1066
1123
|
|
|
1067
|
-
getDocuments(
|
|
1068
|
-
return this.storage.getDocuments(
|
|
1124
|
+
getDocuments(driveId: string) {
|
|
1125
|
+
return this.storage.getDocuments(driveId);
|
|
1069
1126
|
}
|
|
1070
1127
|
|
|
1071
1128
|
protected async createDocument(driveId: string, input: CreateDocumentInput) {
|
|
@@ -1102,7 +1159,7 @@ export class BaseDocumentDriveServer
|
|
|
1102
1159
|
for (const syncUnit of input.synchronizationUnits) {
|
|
1103
1160
|
this.initSyncStatus(syncUnit.syncId, {
|
|
1104
1161
|
pull: this.triggerMap.get(driveId) ? "INITIAL_SYNC" : undefined,
|
|
1105
|
-
push: this.
|
|
1162
|
+
push: this.listenerManager.driveHasListeners(driveId)
|
|
1106
1163
|
? "SUCCESS"
|
|
1107
1164
|
: undefined,
|
|
1108
1165
|
});
|
|
@@ -1131,24 +1188,26 @@ export class BaseDocumentDriveServer
|
|
|
1131
1188
|
return document;
|
|
1132
1189
|
}
|
|
1133
1190
|
|
|
1134
|
-
async deleteDocument(driveId: string,
|
|
1191
|
+
async deleteDocument(driveId: string, documentId: string) {
|
|
1135
1192
|
try {
|
|
1136
|
-
const syncUnits = await this.getSynchronizationUnitsIds(driveId, [
|
|
1193
|
+
const syncUnits = await this.getSynchronizationUnitsIds(driveId, [
|
|
1194
|
+
documentId,
|
|
1195
|
+
]);
|
|
1137
1196
|
|
|
1138
1197
|
// remove document sync units status when a document is deleted
|
|
1139
1198
|
for (const syncUnit of syncUnits) {
|
|
1140
1199
|
this.updateSyncUnitStatus(syncUnit.syncId, null);
|
|
1141
1200
|
}
|
|
1142
|
-
await this.
|
|
1201
|
+
await this.listenerManager.removeSyncUnits(driveId, syncUnits);
|
|
1143
1202
|
} catch (error) {
|
|
1144
1203
|
logger.warn("Error deleting document", error);
|
|
1145
1204
|
}
|
|
1146
|
-
await this.cache.deleteDocument(driveId,
|
|
1147
|
-
return this.storage.deleteDocument(driveId,
|
|
1205
|
+
await this.cache.deleteDocument(driveId, documentId);
|
|
1206
|
+
return this.storage.deleteDocument(driveId, documentId);
|
|
1148
1207
|
}
|
|
1149
1208
|
|
|
1150
1209
|
async _processOperations<T extends Document, A extends Action>(
|
|
1151
|
-
|
|
1210
|
+
driveId: string,
|
|
1152
1211
|
documentId: string | undefined,
|
|
1153
1212
|
documentStorage: DocumentStorage<T>,
|
|
1154
1213
|
operations: Operation<A | BaseAction>[],
|
|
@@ -1158,7 +1217,7 @@ export class BaseDocumentDriveServer
|
|
|
1158
1217
|
|
|
1159
1218
|
const documentStorageWithState = await this._addDocumentResultingStage(
|
|
1160
1219
|
documentStorage,
|
|
1161
|
-
|
|
1220
|
+
driveId,
|
|
1162
1221
|
documentId,
|
|
1163
1222
|
);
|
|
1164
1223
|
|
|
@@ -1215,7 +1274,7 @@ export class BaseDocumentDriveServer
|
|
|
1215
1274
|
const taskQueueMethod = this.options.taskQueueMethod;
|
|
1216
1275
|
const task = () =>
|
|
1217
1276
|
this._performOperation(
|
|
1218
|
-
|
|
1277
|
+
driveId,
|
|
1219
1278
|
documentId,
|
|
1220
1279
|
document,
|
|
1221
1280
|
nextOperation,
|
|
@@ -1256,7 +1315,7 @@ export class BaseDocumentDriveServer
|
|
|
1256
1315
|
|
|
1257
1316
|
private async _addDocumentResultingStage<T extends Document>(
|
|
1258
1317
|
document: DocumentStorage<T>,
|
|
1259
|
-
|
|
1318
|
+
driveId: string,
|
|
1260
1319
|
documentId?: string,
|
|
1261
1320
|
options?: GetDocumentOptions,
|
|
1262
1321
|
): Promise<DocumentStorage<T>> {
|
|
@@ -1278,14 +1337,14 @@ export class BaseDocumentDriveServer
|
|
|
1278
1337
|
if (lastRemainingOperation && !lastRemainingOperation.resultingState) {
|
|
1279
1338
|
lastRemainingOperation.resultingState = await (documentId
|
|
1280
1339
|
? this.storage.getOperationResultingState?.(
|
|
1281
|
-
|
|
1340
|
+
driveId,
|
|
1282
1341
|
documentId,
|
|
1283
1342
|
lastRemainingOperation.index,
|
|
1284
1343
|
lastRemainingOperation.scope,
|
|
1285
1344
|
"main",
|
|
1286
1345
|
)
|
|
1287
1346
|
: this.storage.getDriveOperationResultingState?.(
|
|
1288
|
-
|
|
1347
|
+
driveId,
|
|
1289
1348
|
lastRemainingOperation.index,
|
|
1290
1349
|
lastRemainingOperation.scope,
|
|
1291
1350
|
"main",
|
|
@@ -1341,8 +1400,8 @@ export class BaseDocumentDriveServer
|
|
|
1341
1400
|
}
|
|
1342
1401
|
|
|
1343
1402
|
private async _performOperation<T extends Document>(
|
|
1344
|
-
|
|
1345
|
-
|
|
1403
|
+
driveId: string,
|
|
1404
|
+
documentId: string | undefined,
|
|
1346
1405
|
document: T,
|
|
1347
1406
|
operation: Operation,
|
|
1348
1407
|
skipHashValidation = false,
|
|
@@ -1366,16 +1425,16 @@ export class BaseDocumentDriveServer
|
|
|
1366
1425
|
// if the latest operation doesn't have a resulting state then tries
|
|
1367
1426
|
// to retrieve it from the db to avoid rerunning all the operations
|
|
1368
1427
|
if (lastRemainingOperation && !lastRemainingOperation.resultingState) {
|
|
1369
|
-
lastRemainingOperation.resultingState = await (
|
|
1428
|
+
lastRemainingOperation.resultingState = await (documentId
|
|
1370
1429
|
? this.storage.getOperationResultingState?.(
|
|
1371
|
-
|
|
1372
|
-
|
|
1430
|
+
driveId,
|
|
1431
|
+
documentId,
|
|
1373
1432
|
lastRemainingOperation.index,
|
|
1374
1433
|
lastRemainingOperation.scope,
|
|
1375
1434
|
"main",
|
|
1376
1435
|
)
|
|
1377
1436
|
: this.storage.getDriveOperationResultingState?.(
|
|
1378
|
-
|
|
1437
|
+
driveId,
|
|
1379
1438
|
lastRemainingOperation.index,
|
|
1380
1439
|
lastRemainingOperation.scope,
|
|
1381
1440
|
"main",
|
|
@@ -1390,20 +1449,21 @@ export class BaseDocumentDriveServer
|
|
|
1390
1449
|
let handler: (() => Promise<unknown>) | undefined = undefined;
|
|
1391
1450
|
switch (signal.type) {
|
|
1392
1451
|
case "CREATE_CHILD_DOCUMENT":
|
|
1393
|
-
handler = () => this.createDocument(
|
|
1452
|
+
handler = () => this.createDocument(driveId, signal.input);
|
|
1394
1453
|
break;
|
|
1395
1454
|
case "DELETE_CHILD_DOCUMENT":
|
|
1396
|
-
handler = () => this.deleteDocument(
|
|
1455
|
+
handler = () => this.deleteDocument(driveId, signal.input.id);
|
|
1397
1456
|
break;
|
|
1398
1457
|
case "COPY_CHILD_DOCUMENT":
|
|
1399
1458
|
handler = () =>
|
|
1400
|
-
this.getDocument(
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1459
|
+
this.getDocument(driveId, signal.input.id).then(
|
|
1460
|
+
(documentToCopy) =>
|
|
1461
|
+
this.createDocument(driveId, {
|
|
1462
|
+
id: signal.input.newId,
|
|
1463
|
+
documentType: documentToCopy.documentType,
|
|
1464
|
+
document: documentToCopy,
|
|
1465
|
+
synchronizationUnits: signal.input.synchronizationUnits,
|
|
1466
|
+
}),
|
|
1407
1467
|
);
|
|
1408
1468
|
break;
|
|
1409
1469
|
}
|
|
@@ -1449,50 +1509,53 @@ export class BaseDocumentDriveServer
|
|
|
1449
1509
|
}
|
|
1450
1510
|
|
|
1451
1511
|
addOperation(
|
|
1452
|
-
|
|
1453
|
-
|
|
1512
|
+
driveId: string,
|
|
1513
|
+
documentId: string,
|
|
1454
1514
|
operation: Operation,
|
|
1455
1515
|
options?: AddOperationOptions,
|
|
1456
1516
|
): Promise<IOperationResult> {
|
|
1457
|
-
return this.addOperations(
|
|
1517
|
+
return this.addOperations(driveId, documentId, [operation], options);
|
|
1458
1518
|
}
|
|
1459
1519
|
|
|
1460
1520
|
private async _addOperations(
|
|
1461
|
-
|
|
1462
|
-
|
|
1521
|
+
driveId: string,
|
|
1522
|
+
documentId: string,
|
|
1463
1523
|
callback: (document: DocumentStorage) => Promise<{
|
|
1464
1524
|
operations: Operation[];
|
|
1465
1525
|
header: DocumentHeader;
|
|
1466
1526
|
}>,
|
|
1467
1527
|
) {
|
|
1468
1528
|
if (!this.storage.addDocumentOperationsWithTransaction) {
|
|
1469
|
-
const documentStorage = await this.storage.getDocument(
|
|
1529
|
+
const documentStorage = await this.storage.getDocument(
|
|
1530
|
+
driveId,
|
|
1531
|
+
documentId,
|
|
1532
|
+
);
|
|
1470
1533
|
const result = await callback(documentStorage);
|
|
1471
1534
|
// saves the applied operations to storage
|
|
1472
1535
|
if (result.operations.length > 0) {
|
|
1473
1536
|
await this.storage.addDocumentOperations(
|
|
1474
|
-
|
|
1475
|
-
|
|
1537
|
+
driveId,
|
|
1538
|
+
documentId,
|
|
1476
1539
|
result.operations,
|
|
1477
1540
|
result.header,
|
|
1478
1541
|
);
|
|
1479
1542
|
}
|
|
1480
1543
|
} else {
|
|
1481
1544
|
await this.storage.addDocumentOperationsWithTransaction(
|
|
1482
|
-
|
|
1483
|
-
|
|
1545
|
+
driveId,
|
|
1546
|
+
documentId,
|
|
1484
1547
|
callback,
|
|
1485
1548
|
);
|
|
1486
1549
|
}
|
|
1487
1550
|
}
|
|
1488
1551
|
|
|
1489
1552
|
queueOperation(
|
|
1490
|
-
|
|
1491
|
-
|
|
1553
|
+
driveId: string,
|
|
1554
|
+
documentId: string,
|
|
1492
1555
|
operation: Operation,
|
|
1493
1556
|
options?: AddOperationOptions,
|
|
1494
1557
|
): Promise<IOperationResult> {
|
|
1495
|
-
return this.queueOperations(
|
|
1558
|
+
return this.queueOperations(driveId, documentId, [operation], options);
|
|
1496
1559
|
}
|
|
1497
1560
|
|
|
1498
1561
|
private async resultIfExistingOperations(
|
|
@@ -1534,20 +1597,24 @@ export class BaseDocumentDriveServer
|
|
|
1534
1597
|
}
|
|
1535
1598
|
|
|
1536
1599
|
async queueOperations(
|
|
1537
|
-
|
|
1538
|
-
|
|
1600
|
+
driveId: string,
|
|
1601
|
+
documentId: string,
|
|
1539
1602
|
operations: Operation[],
|
|
1540
1603
|
options?: AddOperationOptions,
|
|
1541
1604
|
) {
|
|
1542
1605
|
// if operations are already stored then returns cached document
|
|
1543
|
-
const result = await this.resultIfExistingOperations(
|
|
1606
|
+
const result = await this.resultIfExistingOperations(
|
|
1607
|
+
driveId,
|
|
1608
|
+
documentId,
|
|
1609
|
+
operations,
|
|
1610
|
+
);
|
|
1544
1611
|
if (result) {
|
|
1545
1612
|
return result;
|
|
1546
1613
|
}
|
|
1547
1614
|
try {
|
|
1548
1615
|
const jobId = await this.queueManager.addJob({
|
|
1549
|
-
driveId:
|
|
1550
|
-
documentId:
|
|
1616
|
+
driveId: driveId,
|
|
1617
|
+
documentId: documentId,
|
|
1551
1618
|
operations,
|
|
1552
1619
|
options,
|
|
1553
1620
|
});
|
|
@@ -1581,24 +1648,24 @@ export class BaseDocumentDriveServer
|
|
|
1581
1648
|
}
|
|
1582
1649
|
|
|
1583
1650
|
async queueAction(
|
|
1584
|
-
|
|
1585
|
-
|
|
1651
|
+
driveId: string,
|
|
1652
|
+
documentId: string,
|
|
1586
1653
|
action: Action,
|
|
1587
1654
|
options?: AddOperationOptions,
|
|
1588
1655
|
): Promise<IOperationResult> {
|
|
1589
|
-
return this.queueActions(
|
|
1656
|
+
return this.queueActions(driveId, documentId, [action], options);
|
|
1590
1657
|
}
|
|
1591
1658
|
|
|
1592
1659
|
async queueActions(
|
|
1593
|
-
|
|
1594
|
-
|
|
1660
|
+
driveId: string,
|
|
1661
|
+
documentId: string,
|
|
1595
1662
|
actions: Action[],
|
|
1596
1663
|
options?: AddOperationOptions,
|
|
1597
1664
|
): Promise<IOperationResult> {
|
|
1598
1665
|
try {
|
|
1599
1666
|
const jobId = await this.queueManager.addJob({
|
|
1600
|
-
driveId:
|
|
1601
|
-
documentId:
|
|
1667
|
+
driveId: driveId,
|
|
1668
|
+
documentId: documentId,
|
|
1602
1669
|
actions,
|
|
1603
1670
|
options,
|
|
1604
1671
|
});
|
|
@@ -1632,21 +1699,21 @@ export class BaseDocumentDriveServer
|
|
|
1632
1699
|
}
|
|
1633
1700
|
|
|
1634
1701
|
async queueDriveAction(
|
|
1635
|
-
|
|
1702
|
+
driveId: string,
|
|
1636
1703
|
action: DocumentDriveAction | BaseAction,
|
|
1637
1704
|
options?: AddOperationOptions,
|
|
1638
1705
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1639
|
-
return this.queueDriveActions(
|
|
1706
|
+
return this.queueDriveActions(driveId, [action], options);
|
|
1640
1707
|
}
|
|
1641
1708
|
|
|
1642
1709
|
async queueDriveActions(
|
|
1643
|
-
|
|
1710
|
+
driveId: string,
|
|
1644
1711
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
1645
1712
|
options?: AddOperationOptions,
|
|
1646
1713
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1647
1714
|
try {
|
|
1648
1715
|
const jobId = await this.queueManager.addJob({
|
|
1649
|
-
driveId:
|
|
1716
|
+
driveId: driveId,
|
|
1650
1717
|
actions,
|
|
1651
1718
|
options,
|
|
1652
1719
|
});
|
|
@@ -1681,13 +1748,17 @@ export class BaseDocumentDriveServer
|
|
|
1681
1748
|
}
|
|
1682
1749
|
|
|
1683
1750
|
async addOperations(
|
|
1684
|
-
|
|
1685
|
-
|
|
1751
|
+
driveId: string,
|
|
1752
|
+
documentId: string,
|
|
1686
1753
|
operations: Operation[],
|
|
1687
1754
|
options?: AddOperationOptions,
|
|
1688
1755
|
) {
|
|
1689
1756
|
// if operations are already stored then returns the result
|
|
1690
|
-
const result = await this.resultIfExistingOperations(
|
|
1757
|
+
const result = await this.resultIfExistingOperations(
|
|
1758
|
+
driveId,
|
|
1759
|
+
documentId,
|
|
1760
|
+
operations,
|
|
1761
|
+
);
|
|
1691
1762
|
if (result) {
|
|
1692
1763
|
return result;
|
|
1693
1764
|
}
|
|
@@ -1697,33 +1768,39 @@ export class BaseDocumentDriveServer
|
|
|
1697
1768
|
let error: Error | undefined;
|
|
1698
1769
|
|
|
1699
1770
|
try {
|
|
1700
|
-
await this._addOperations(
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1771
|
+
await this._addOperations(
|
|
1772
|
+
driveId,
|
|
1773
|
+
documentId,
|
|
1774
|
+
async (documentStorage) => {
|
|
1775
|
+
const result = await this._processOperations(
|
|
1776
|
+
driveId,
|
|
1777
|
+
documentId,
|
|
1778
|
+
documentStorage,
|
|
1779
|
+
operations,
|
|
1780
|
+
);
|
|
1707
1781
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1782
|
+
if (!result.document) {
|
|
1783
|
+
logger.error("Invalid document");
|
|
1784
|
+
throw result.error ?? new Error("Invalid document");
|
|
1785
|
+
}
|
|
1712
1786
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1787
|
+
document = result.document;
|
|
1788
|
+
error = result.error;
|
|
1789
|
+
signals.push(...result.signals);
|
|
1790
|
+
operationsApplied.push(...result.operationsApplied);
|
|
1717
1791
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1792
|
+
return {
|
|
1793
|
+
operations: result.operationsApplied,
|
|
1794
|
+
header: result.document,
|
|
1795
|
+
newState: document.state,
|
|
1796
|
+
};
|
|
1797
|
+
},
|
|
1798
|
+
);
|
|
1724
1799
|
|
|
1725
1800
|
if (document) {
|
|
1726
|
-
this.cache
|
|
1801
|
+
this.cache
|
|
1802
|
+
.setDocument(driveId, documentId, document)
|
|
1803
|
+
.catch(logger.error);
|
|
1727
1804
|
}
|
|
1728
1805
|
|
|
1729
1806
|
// gets all the different scopes and branches combinations from the operations
|
|
@@ -1738,8 +1815,8 @@ export class BaseDocumentDriveServer
|
|
|
1738
1815
|
);
|
|
1739
1816
|
|
|
1740
1817
|
const syncUnits = await this.getSynchronizationUnits(
|
|
1741
|
-
|
|
1742
|
-
[
|
|
1818
|
+
driveId,
|
|
1819
|
+
[documentId],
|
|
1743
1820
|
scopes,
|
|
1744
1821
|
branches,
|
|
1745
1822
|
);
|
|
@@ -1767,13 +1844,13 @@ export class BaseDocumentDriveServer
|
|
|
1767
1844
|
|
|
1768
1845
|
const operationSource = this.getOperationSource(source);
|
|
1769
1846
|
|
|
1770
|
-
this.
|
|
1847
|
+
this.listenerManager
|
|
1771
1848
|
.updateSynchronizationRevisions(
|
|
1772
|
-
|
|
1849
|
+
driveId,
|
|
1773
1850
|
syncUnits,
|
|
1774
1851
|
source,
|
|
1775
1852
|
() => {
|
|
1776
|
-
this.updateSyncUnitStatus(
|
|
1853
|
+
this.updateSyncUnitStatus(driveId, {
|
|
1777
1854
|
[operationSource]: "SYNCING",
|
|
1778
1855
|
});
|
|
1779
1856
|
|
|
@@ -1788,7 +1865,7 @@ export class BaseDocumentDriveServer
|
|
|
1788
1865
|
)
|
|
1789
1866
|
.then((updates) => {
|
|
1790
1867
|
if (updates.length) {
|
|
1791
|
-
this.updateSyncUnitStatus(
|
|
1868
|
+
this.updateSyncUnitStatus(driveId, {
|
|
1792
1869
|
[operationSource]: "SUCCESS",
|
|
1793
1870
|
});
|
|
1794
1871
|
}
|
|
@@ -1802,7 +1879,7 @@ export class BaseDocumentDriveServer
|
|
|
1802
1879
|
.catch((error) => {
|
|
1803
1880
|
logger.error("Non handled error updating sync revision", error);
|
|
1804
1881
|
this.updateSyncUnitStatus(
|
|
1805
|
-
|
|
1882
|
+
driveId,
|
|
1806
1883
|
{
|
|
1807
1884
|
[operationSource]: "ERROR",
|
|
1808
1885
|
},
|
|
@@ -1854,11 +1931,11 @@ export class BaseDocumentDriveServer
|
|
|
1854
1931
|
}
|
|
1855
1932
|
|
|
1856
1933
|
addDriveOperation(
|
|
1857
|
-
|
|
1934
|
+
driveId: string,
|
|
1858
1935
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1859
1936
|
options?: AddOperationOptions,
|
|
1860
1937
|
) {
|
|
1861
|
-
return this.addDriveOperations(
|
|
1938
|
+
return this.addDriveOperations(driveId, [operation], options);
|
|
1862
1939
|
}
|
|
1863
1940
|
|
|
1864
1941
|
async clearStorage() {
|
|
@@ -1870,35 +1947,35 @@ export class BaseDocumentDriveServer
|
|
|
1870
1947
|
}
|
|
1871
1948
|
|
|
1872
1949
|
private async _addDriveOperations(
|
|
1873
|
-
|
|
1950
|
+
driveId: string,
|
|
1874
1951
|
callback: (document: DocumentDriveStorage) => Promise<{
|
|
1875
1952
|
operations: Operation<DocumentDriveAction | BaseAction>[];
|
|
1876
1953
|
header: DocumentHeader;
|
|
1877
1954
|
}>,
|
|
1878
1955
|
) {
|
|
1879
1956
|
if (!this.storage.addDriveOperationsWithTransaction) {
|
|
1880
|
-
const documentStorage = await this.storage.getDrive(
|
|
1957
|
+
const documentStorage = await this.storage.getDrive(driveId);
|
|
1881
1958
|
const result = await callback(documentStorage);
|
|
1882
1959
|
// saves the applied operations to storage
|
|
1883
1960
|
if (result.operations.length > 0) {
|
|
1884
1961
|
await this.storage.addDriveOperations(
|
|
1885
|
-
|
|
1962
|
+
driveId,
|
|
1886
1963
|
result.operations,
|
|
1887
1964
|
result.header,
|
|
1888
1965
|
);
|
|
1889
1966
|
}
|
|
1890
1967
|
return result;
|
|
1891
1968
|
} else {
|
|
1892
|
-
return this.storage.addDriveOperationsWithTransaction(
|
|
1969
|
+
return this.storage.addDriveOperationsWithTransaction(driveId, callback);
|
|
1893
1970
|
}
|
|
1894
1971
|
}
|
|
1895
1972
|
|
|
1896
1973
|
queueDriveOperation(
|
|
1897
|
-
|
|
1974
|
+
driveId: string,
|
|
1898
1975
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1899
1976
|
options?: AddOperationOptions,
|
|
1900
1977
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1901
|
-
return this.queueDriveOperations(
|
|
1978
|
+
return this.queueDriveOperations(driveId, [operation], options);
|
|
1902
1979
|
}
|
|
1903
1980
|
|
|
1904
1981
|
private async resultIfExistingDriveOperations(
|
|
@@ -1935,13 +2012,13 @@ export class BaseDocumentDriveServer
|
|
|
1935
2012
|
}
|
|
1936
2013
|
|
|
1937
2014
|
async queueDriveOperations(
|
|
1938
|
-
|
|
2015
|
+
driveId: string,
|
|
1939
2016
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1940
2017
|
options?: AddOperationOptions,
|
|
1941
2018
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1942
2019
|
// if operations are already stored then returns cached document
|
|
1943
2020
|
const result = await this.resultIfExistingDriveOperations(
|
|
1944
|
-
|
|
2021
|
+
driveId,
|
|
1945
2022
|
operations,
|
|
1946
2023
|
);
|
|
1947
2024
|
if (result) {
|
|
@@ -1949,7 +2026,7 @@ export class BaseDocumentDriveServer
|
|
|
1949
2026
|
}
|
|
1950
2027
|
try {
|
|
1951
2028
|
const jobId = await this.queueManager.addJob({
|
|
1952
|
-
driveId:
|
|
2029
|
+
driveId: driveId,
|
|
1953
2030
|
operations,
|
|
1954
2031
|
options,
|
|
1955
2032
|
});
|
|
@@ -1984,7 +2061,7 @@ export class BaseDocumentDriveServer
|
|
|
1984
2061
|
}
|
|
1985
2062
|
|
|
1986
2063
|
async addDriveOperations(
|
|
1987
|
-
|
|
2064
|
+
driveId: string,
|
|
1988
2065
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1989
2066
|
options?: AddOperationOptions,
|
|
1990
2067
|
) {
|
|
@@ -1995,7 +2072,7 @@ export class BaseDocumentDriveServer
|
|
|
1995
2072
|
|
|
1996
2073
|
// if operations are already stored then returns cached drive
|
|
1997
2074
|
const result = await this.resultIfExistingDriveOperations(
|
|
1998
|
-
|
|
2075
|
+
driveId,
|
|
1999
2076
|
operations,
|
|
2000
2077
|
);
|
|
2001
2078
|
if (result) {
|
|
@@ -2003,11 +2080,11 @@ export class BaseDocumentDriveServer
|
|
|
2003
2080
|
}
|
|
2004
2081
|
|
|
2005
2082
|
try {
|
|
2006
|
-
await this._addDriveOperations(
|
|
2083
|
+
await this._addDriveOperations(driveId, async (documentStorage) => {
|
|
2007
2084
|
const result = await this._processOperations<
|
|
2008
2085
|
DocumentDriveDocument,
|
|
2009
2086
|
DocumentDriveAction
|
|
2010
|
-
>(
|
|
2087
|
+
>(driveId, undefined, documentStorage, operations.slice());
|
|
2011
2088
|
document = result.document;
|
|
2012
2089
|
operationsApplied.push(...result.operationsApplied);
|
|
2013
2090
|
signals.push(...result.signals);
|
|
@@ -2023,16 +2100,54 @@ export class BaseDocumentDriveServer
|
|
|
2023
2100
|
throw error ?? new Error("Invalid Document Drive document");
|
|
2024
2101
|
}
|
|
2025
2102
|
|
|
2026
|
-
this.cache.setDocument("drives",
|
|
2103
|
+
this.cache.setDocument("drives", driveId, document).catch(logger.error);
|
|
2027
2104
|
|
|
2028
2105
|
for (const operation of operationsApplied) {
|
|
2029
2106
|
switch (operation.type) {
|
|
2030
2107
|
case "ADD_LISTENER": {
|
|
2031
|
-
|
|
2108
|
+
const zodListener = operation.input.listener;
|
|
2109
|
+
|
|
2110
|
+
// create the transmitter
|
|
2111
|
+
const transmitter = this.transmitterFactory.instance(
|
|
2112
|
+
zodListener.callInfo?.transmitterType ?? "",
|
|
2113
|
+
{
|
|
2114
|
+
driveId,
|
|
2115
|
+
listenerId: zodListener.listenerId,
|
|
2116
|
+
block: zodListener.block,
|
|
2117
|
+
filter: zodListener.filter,
|
|
2118
|
+
system: zodListener.system,
|
|
2119
|
+
label: zodListener.label || undefined,
|
|
2120
|
+
callInfo: zodListener.callInfo || undefined,
|
|
2121
|
+
},
|
|
2122
|
+
this,
|
|
2123
|
+
);
|
|
2124
|
+
|
|
2125
|
+
// create the listener
|
|
2126
|
+
const listener = {
|
|
2127
|
+
...zodListener,
|
|
2128
|
+
driveId: driveId,
|
|
2129
|
+
label: zodListener.label ?? "",
|
|
2130
|
+
system: zodListener.system ?? false,
|
|
2131
|
+
filter: {
|
|
2132
|
+
branch: zodListener.filter.branch ?? [],
|
|
2133
|
+
documentId: zodListener.filter.documentId ?? [],
|
|
2134
|
+
documentType: zodListener.filter.documentType ?? [],
|
|
2135
|
+
scope: zodListener.filter.scope ?? [],
|
|
2136
|
+
},
|
|
2137
|
+
callInfo: {
|
|
2138
|
+
data: zodListener.callInfo?.data ?? "",
|
|
2139
|
+
name: zodListener.callInfo?.name ?? "PullResponder",
|
|
2140
|
+
transmitterType:
|
|
2141
|
+
zodListener.callInfo?.transmitterType ?? "PullResponder",
|
|
2142
|
+
},
|
|
2143
|
+
transmitter,
|
|
2144
|
+
};
|
|
2145
|
+
|
|
2146
|
+
await this.addListener(driveId, listener);
|
|
2032
2147
|
break;
|
|
2033
2148
|
}
|
|
2034
2149
|
case "REMOVE_LISTENER": {
|
|
2035
|
-
await this.removeListener(
|
|
2150
|
+
await this.removeListener(driveId, operation);
|
|
2036
2151
|
break;
|
|
2037
2152
|
}
|
|
2038
2153
|
}
|
|
@@ -2066,13 +2181,13 @@ export class BaseDocumentDriveServer
|
|
|
2066
2181
|
|
|
2067
2182
|
const operationSource = this.getOperationSource(source);
|
|
2068
2183
|
|
|
2069
|
-
this.
|
|
2184
|
+
this.listenerManager
|
|
2070
2185
|
.updateSynchronizationRevisions(
|
|
2071
|
-
|
|
2186
|
+
driveId,
|
|
2072
2187
|
[
|
|
2073
2188
|
{
|
|
2074
2189
|
syncId: "0",
|
|
2075
|
-
driveId:
|
|
2190
|
+
driveId: driveId,
|
|
2076
2191
|
documentId: "",
|
|
2077
2192
|
scope: "global",
|
|
2078
2193
|
branch: "main",
|
|
@@ -2083,7 +2198,7 @@ export class BaseDocumentDriveServer
|
|
|
2083
2198
|
],
|
|
2084
2199
|
source,
|
|
2085
2200
|
() => {
|
|
2086
|
-
this.updateSyncUnitStatus(
|
|
2201
|
+
this.updateSyncUnitStatus(driveId, {
|
|
2087
2202
|
[operationSource]: "SYNCING",
|
|
2088
2203
|
});
|
|
2089
2204
|
},
|
|
@@ -2092,7 +2207,7 @@ export class BaseDocumentDriveServer
|
|
|
2092
2207
|
)
|
|
2093
2208
|
.then((updates) => {
|
|
2094
2209
|
if (updates.length) {
|
|
2095
|
-
this.updateSyncUnitStatus(
|
|
2210
|
+
this.updateSyncUnitStatus(driveId, {
|
|
2096
2211
|
[operationSource]: "SUCCESS",
|
|
2097
2212
|
});
|
|
2098
2213
|
}
|
|
@@ -2100,7 +2215,7 @@ export class BaseDocumentDriveServer
|
|
|
2100
2215
|
.catch((error) => {
|
|
2101
2216
|
logger.error("Non handled error updating sync revision", error);
|
|
2102
2217
|
this.updateSyncUnitStatus(
|
|
2103
|
-
|
|
2218
|
+
driveId,
|
|
2104
2219
|
{ [operationSource]: "ERROR" },
|
|
2105
2220
|
error as Error,
|
|
2106
2221
|
);
|
|
@@ -2147,14 +2262,14 @@ export class BaseDocumentDriveServer
|
|
|
2147
2262
|
}
|
|
2148
2263
|
|
|
2149
2264
|
private _buildOperations<T extends Action>(
|
|
2150
|
-
|
|
2265
|
+
documentId: Document,
|
|
2151
2266
|
actions: (T | BaseAction)[],
|
|
2152
2267
|
): Operation<T | BaseAction>[] {
|
|
2153
2268
|
const operations: Operation<T | BaseAction>[] = [];
|
|
2154
|
-
const { reducer } = this.getDocumentModel(
|
|
2269
|
+
const { reducer } = this.getDocumentModel(documentId.documentType);
|
|
2155
2270
|
for (const action of actions) {
|
|
2156
|
-
|
|
2157
|
-
const operation =
|
|
2271
|
+
documentId = reducer(documentId, action);
|
|
2272
|
+
const operation = documentId.operations[action.scope].slice().pop();
|
|
2158
2273
|
if (!operation) {
|
|
2159
2274
|
throw new Error("Error creating operations");
|
|
2160
2275
|
}
|
|
@@ -2164,44 +2279,73 @@ export class BaseDocumentDriveServer
|
|
|
2164
2279
|
}
|
|
2165
2280
|
|
|
2166
2281
|
async addAction(
|
|
2167
|
-
|
|
2168
|
-
|
|
2282
|
+
driveId: string,
|
|
2283
|
+
documentId: string,
|
|
2169
2284
|
action: Action,
|
|
2170
2285
|
options?: AddOperationOptions,
|
|
2171
2286
|
): Promise<IOperationResult> {
|
|
2172
|
-
return this.addActions(
|
|
2287
|
+
return this.addActions(driveId, documentId, [action], options);
|
|
2173
2288
|
}
|
|
2174
2289
|
|
|
2175
2290
|
async addActions(
|
|
2176
|
-
|
|
2177
|
-
|
|
2291
|
+
driveId: string,
|
|
2292
|
+
documentId: string,
|
|
2178
2293
|
actions: Action[],
|
|
2179
2294
|
options?: AddOperationOptions,
|
|
2180
2295
|
): Promise<IOperationResult> {
|
|
2181
|
-
const document = await this.getDocument(
|
|
2296
|
+
const document = await this.getDocument(driveId, documentId);
|
|
2182
2297
|
const operations = this._buildOperations(document, actions);
|
|
2183
|
-
return this.addOperations(
|
|
2298
|
+
return this.addOperations(driveId, documentId, operations, options);
|
|
2184
2299
|
}
|
|
2185
2300
|
|
|
2186
2301
|
async addDriveAction(
|
|
2187
|
-
|
|
2302
|
+
driveId: string,
|
|
2188
2303
|
action: DocumentDriveAction | BaseAction,
|
|
2189
2304
|
options?: AddOperationOptions,
|
|
2190
2305
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2191
|
-
return this.addDriveActions(
|
|
2306
|
+
return this.addDriveActions(driveId, [action], options);
|
|
2192
2307
|
}
|
|
2193
2308
|
|
|
2194
2309
|
async addDriveActions(
|
|
2195
|
-
|
|
2310
|
+
driveId: string,
|
|
2196
2311
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
2197
2312
|
options?: AddOperationOptions,
|
|
2198
2313
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2199
|
-
const document = await this.getDrive(
|
|
2314
|
+
const document = await this.getDrive(driveId);
|
|
2200
2315
|
const operations = this._buildOperations(document, actions);
|
|
2201
|
-
const result = await this.addDriveOperations(
|
|
2316
|
+
const result = await this.addDriveOperations(driveId, operations, options);
|
|
2202
2317
|
return result;
|
|
2203
2318
|
}
|
|
2204
2319
|
|
|
2320
|
+
async detachDrive(driveId: string) {
|
|
2321
|
+
const documentDrive = await this.getDrive(driveId);
|
|
2322
|
+
const listeners = documentDrive.state.local.listeners || [];
|
|
2323
|
+
const triggers = documentDrive.state.local.triggers || [];
|
|
2324
|
+
|
|
2325
|
+
for (const listener of listeners) {
|
|
2326
|
+
await this.addDriveAction(
|
|
2327
|
+
driveId,
|
|
2328
|
+
actions.removeListener({ listenerId: listener.listenerId }),
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
for (const trigger of triggers) {
|
|
2333
|
+
await this.addDriveAction(
|
|
2334
|
+
driveId,
|
|
2335
|
+
actions.removeTrigger({ triggerId: trigger.id }),
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
await this.addDriveAction(
|
|
2340
|
+
driveId,
|
|
2341
|
+
actions.setSharingType({ type: "LOCAL" }),
|
|
2342
|
+
);
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
async addListener(driveId: string, listener: Listener) {
|
|
2346
|
+
await this.listenerManager.setListener(driveId, listener);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2205
2349
|
async addInternalListener(
|
|
2206
2350
|
driveId: string,
|
|
2207
2351
|
receiver: IReceiver,
|
|
@@ -2236,75 +2380,40 @@ export class BaseDocumentDriveServer
|
|
|
2236
2380
|
return transmitter;
|
|
2237
2381
|
}
|
|
2238
2382
|
|
|
2239
|
-
async detachDrive(driveId: string) {
|
|
2240
|
-
const documentDrive = await this.getDrive(driveId);
|
|
2241
|
-
const listeners = documentDrive.state.local.listeners || [];
|
|
2242
|
-
const triggers = documentDrive.state.local.triggers || [];
|
|
2243
|
-
|
|
2244
|
-
for (const listener of listeners) {
|
|
2245
|
-
await this.addDriveAction(
|
|
2246
|
-
driveId,
|
|
2247
|
-
actions.removeListener({ listenerId: listener.listenerId }),
|
|
2248
|
-
);
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
for (const trigger of triggers) {
|
|
2252
|
-
await this.addDriveAction(
|
|
2253
|
-
driveId,
|
|
2254
|
-
actions.removeTrigger({ triggerId: trigger.id }),
|
|
2255
|
-
);
|
|
2256
|
-
}
|
|
2257
|
-
|
|
2258
|
-
await this.addDriveAction(
|
|
2259
|
-
driveId,
|
|
2260
|
-
actions.setSharingType({ type: "LOCAL" }),
|
|
2261
|
-
);
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
private async addListener(
|
|
2265
|
-
driveId: string,
|
|
2266
|
-
operation: Operation<Action<"ADD_LISTENER", AddListenerInput>>,
|
|
2267
|
-
) {
|
|
2268
|
-
const { listener } = operation.input;
|
|
2269
|
-
await this.listenerStateManager.addListener({
|
|
2270
|
-
...listener,
|
|
2271
|
-
driveId,
|
|
2272
|
-
label: listener.label ?? "",
|
|
2273
|
-
system: listener.system ?? false,
|
|
2274
|
-
filter: {
|
|
2275
|
-
branch: listener.filter.branch ?? [],
|
|
2276
|
-
documentId: listener.filter.documentId ?? [],
|
|
2277
|
-
documentType: listener.filter.documentType ?? [],
|
|
2278
|
-
scope: listener.filter.scope ?? [],
|
|
2279
|
-
},
|
|
2280
|
-
callInfo: {
|
|
2281
|
-
data: listener.callInfo?.data ?? "",
|
|
2282
|
-
name: listener.callInfo?.name ?? "PullResponder",
|
|
2283
|
-
transmitterType: listener.callInfo?.transmitterType ?? "PullResponder",
|
|
2284
|
-
},
|
|
2285
|
-
});
|
|
2286
|
-
}
|
|
2287
|
-
|
|
2288
2383
|
private async removeListener(
|
|
2289
2384
|
driveId: string,
|
|
2290
2385
|
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput>>,
|
|
2291
2386
|
) {
|
|
2292
2387
|
const { listenerId } = operation.input;
|
|
2293
|
-
await this.
|
|
2388
|
+
await this.listenerManager.removeListener(driveId, listenerId);
|
|
2294
2389
|
}
|
|
2295
2390
|
|
|
2296
|
-
getTransmitter(
|
|
2391
|
+
async getTransmitter(
|
|
2297
2392
|
driveId: string,
|
|
2298
2393
|
listenerId: string,
|
|
2299
2394
|
): Promise<ITransmitter | undefined> {
|
|
2300
|
-
|
|
2395
|
+
const listener = await this.listenerManager.getListenerState(
|
|
2396
|
+
driveId,
|
|
2397
|
+
listenerId,
|
|
2398
|
+
);
|
|
2399
|
+
return listener?.listener.transmitter;
|
|
2301
2400
|
}
|
|
2302
2401
|
|
|
2303
2402
|
getListener(
|
|
2304
2403
|
driveId: string,
|
|
2305
2404
|
listenerId: string,
|
|
2306
2405
|
): Promise<ListenerState | undefined> {
|
|
2307
|
-
|
|
2406
|
+
let listenerState;
|
|
2407
|
+
try {
|
|
2408
|
+
listenerState = this.listenerManager.getListenerState(
|
|
2409
|
+
driveId,
|
|
2410
|
+
listenerId,
|
|
2411
|
+
);
|
|
2412
|
+
} catch {
|
|
2413
|
+
return Promise.resolve(undefined);
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
return Promise.resolve(listenerState);
|
|
2308
2417
|
}
|
|
2309
2418
|
|
|
2310
2419
|
getSyncStatus(
|