@powerhousedao/reactor 6.0.0-dev.26 → 6.0.0-dev.27
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/dist/src/cache/document-meta-cache.js +3 -3
- package/dist/src/cache/document-meta-cache.js.map +1 -1
- package/dist/src/cache/kysely-operation-index.d.ts +2 -1
- package/dist/src/cache/kysely-operation-index.d.ts.map +1 -1
- package/dist/src/cache/kysely-operation-index.js +16 -4
- package/dist/src/cache/kysely-operation-index.js.map +1 -1
- package/dist/src/cache/kysely-write-cache.js +8 -8
- package/dist/src/cache/kysely-write-cache.js.map +1 -1
- package/dist/src/cache/operation-index-types.d.ts +2 -1
- package/dist/src/cache/operation-index-types.d.ts.map +1 -1
- package/dist/src/cache/operation-index-types.js.map +1 -1
- package/dist/src/client/reactor-client.d.ts +4 -6
- package/dist/src/client/reactor-client.d.ts.map +1 -1
- package/dist/src/client/reactor-client.js +20 -25
- package/dist/src/client/reactor-client.js.map +1 -1
- package/dist/src/client/types.d.ts +1 -4
- package/dist/src/client/types.d.ts.map +1 -1
- package/dist/src/core/reactor-builder.d.ts.map +1 -1
- package/dist/src/core/reactor-builder.js +2 -5
- package/dist/src/core/reactor-builder.js.map +1 -1
- package/dist/src/core/reactor-client-builder.d.ts +3 -2
- package/dist/src/core/reactor-client-builder.d.ts.map +1 -1
- package/dist/src/core/reactor-client-builder.js +13 -4
- package/dist/src/core/reactor-client-builder.js.map +1 -1
- package/dist/src/core/reactor.d.ts +8 -75
- package/dist/src/core/reactor.d.ts.map +1 -1
- package/dist/src/core/reactor.js +72 -552
- package/dist/src/core/reactor.js.map +1 -1
- package/dist/src/core/types.d.ts +28 -19
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/utils.d.ts +6 -1
- package/dist/src/core/utils.d.ts.map +1 -1
- package/dist/src/core/utils.js +22 -6
- package/dist/src/core/utils.js.map +1 -1
- package/dist/src/executor/simple-job-executor.js +5 -5
- package/dist/src/executor/simple-job-executor.js.map +1 -1
- package/dist/src/index.d.ts +3 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/read-models/base-read-model.js +4 -4
- package/dist/src/read-models/base-read-model.js.map +1 -1
- package/dist/src/read-models/document-view.d.ts +5 -2
- package/dist/src/read-models/document-view.d.ts.map +1 -1
- package/dist/src/read-models/document-view.js +128 -28
- package/dist/src/read-models/document-view.js.map +1 -1
- package/dist/src/shared/collect-all-pages.d.ts +7 -0
- package/dist/src/shared/collect-all-pages.d.ts.map +1 -0
- package/dist/src/shared/collect-all-pages.js +17 -0
- package/dist/src/shared/collect-all-pages.js.map +1 -0
- package/dist/src/signer/passthrough-signer.d.ts +1 -1
- package/dist/src/signer/passthrough-signer.d.ts.map +1 -1
- package/dist/src/signer/passthrough-signer.js +1 -3
- package/dist/src/signer/passthrough-signer.js.map +1 -1
- package/dist/src/storage/interfaces.d.ts +38 -94
- package/dist/src/storage/interfaces.d.ts.map +1 -1
- package/dist/src/storage/interfaces.js.map +1 -1
- package/dist/src/storage/kysely/document-indexer.d.ts +6 -6
- package/dist/src/storage/kysely/document-indexer.d.ts.map +1 -1
- package/dist/src/storage/kysely/document-indexer.js +123 -52
- package/dist/src/storage/kysely/document-indexer.js.map +1 -1
- package/dist/src/storage/kysely/store.d.ts +2 -1
- package/dist/src/storage/kysely/store.d.ts.map +1 -1
- package/dist/src/storage/kysely/store.js +33 -15
- package/dist/src/storage/kysely/store.js.map +1 -1
- package/dist/src/sync/channels/composite-channel-factory.d.ts.map +1 -1
- package/dist/src/sync/channels/composite-channel-factory.js +5 -2
- package/dist/src/sync/channels/composite-channel-factory.js.map +1 -1
- package/dist/src/sync/channels/gql-channel-factory.d.ts.map +1 -1
- package/dist/src/sync/channels/gql-channel-factory.js +5 -2
- package/dist/src/sync/channels/gql-channel-factory.js.map +1 -1
- package/dist/src/sync/channels/gql-channel.d.ts +4 -9
- package/dist/src/sync/channels/gql-channel.d.ts.map +1 -1
- package/dist/src/sync/channels/gql-channel.js +11 -31
- package/dist/src/sync/channels/gql-channel.js.map +1 -1
- package/dist/src/sync/channels/index.d.ts +2 -0
- package/dist/src/sync/channels/index.d.ts.map +1 -1
- package/dist/src/sync/channels/index.js +2 -0
- package/dist/src/sync/channels/index.js.map +1 -1
- package/dist/src/sync/channels/interval-poll-timer.d.ts +18 -0
- package/dist/src/sync/channels/interval-poll-timer.d.ts.map +1 -0
- package/dist/src/sync/channels/interval-poll-timer.js +43 -0
- package/dist/src/sync/channels/interval-poll-timer.js.map +1 -0
- package/dist/src/sync/channels/poll-timer.d.ts +14 -0
- package/dist/src/sync/channels/poll-timer.d.ts.map +1 -0
- package/dist/src/sync/channels/poll-timer.js +2 -0
- package/dist/src/sync/channels/poll-timer.js.map +1 -0
- package/dist/src/sync/index.d.ts +1 -1
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/index.js +1 -1
- package/dist/src/sync/index.js.map +1 -1
- package/dist/src/sync/sync-manager.js +2 -2
- package/dist/src/sync/sync-manager.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/storage/consistency-aware-legacy-storage.d.ts +0 -33
- package/dist/src/storage/consistency-aware-legacy-storage.d.ts.map +0 -1
- package/dist/src/storage/consistency-aware-legacy-storage.js +0 -65
- package/dist/src/storage/consistency-aware-legacy-storage.js.map +0 -1
package/dist/src/core/reactor.js
CHANGED
|
@@ -5,7 +5,7 @@ import { ReactorEventTypes } from "../events/types.js";
|
|
|
5
5
|
import { createMutableShutdownStatus } from "../shared/factories.js";
|
|
6
6
|
import { JobStatus } from "../shared/types.js";
|
|
7
7
|
import { matchesScope } from "../shared/utils.js";
|
|
8
|
-
import { filterByType,
|
|
8
|
+
import { filterByType, getSharedActionScope, getSharedOperationScope, signAction, signActions, toErrorInfo, topologicalSort, validateActionScopes, validateBatchRequest, } from "./utils.js";
|
|
9
9
|
/**
|
|
10
10
|
* This class implements the IReactor interface and serves as the main entry point
|
|
11
11
|
* for the new Reactor architecture.
|
|
@@ -13,7 +13,6 @@ import { filterByType, getSharedScope, signAction, signActions, toErrorInfo, top
|
|
|
13
13
|
export class Reactor {
|
|
14
14
|
logger;
|
|
15
15
|
documentModelRegistry;
|
|
16
|
-
documentStorage;
|
|
17
16
|
shutdownStatus;
|
|
18
17
|
setShutdown;
|
|
19
18
|
queue;
|
|
@@ -21,59 +20,44 @@ export class Reactor {
|
|
|
21
20
|
readModelCoordinator;
|
|
22
21
|
features;
|
|
23
22
|
documentView;
|
|
24
|
-
|
|
23
|
+
documentIndexer;
|
|
25
24
|
operationStore;
|
|
26
25
|
eventBus;
|
|
27
|
-
constructor(logger, documentModelRegistry,
|
|
26
|
+
constructor(logger, documentModelRegistry, queue, jobTracker, readModelCoordinator, features, documentView, documentIndexer, operationStore, eventBus) {
|
|
28
27
|
this.logger = logger;
|
|
29
28
|
this.documentModelRegistry = documentModelRegistry;
|
|
30
|
-
this.documentStorage = documentStorage;
|
|
31
29
|
this.queue = queue;
|
|
32
30
|
this.jobTracker = jobTracker;
|
|
33
31
|
this.readModelCoordinator = readModelCoordinator;
|
|
34
32
|
this.features = features;
|
|
35
33
|
this.documentView = documentView;
|
|
36
|
-
this.
|
|
34
|
+
this.documentIndexer = documentIndexer;
|
|
37
35
|
this.operationStore = operationStore;
|
|
38
36
|
this.eventBus = eventBus;
|
|
39
37
|
const [status, setter] = createMutableShutdownStatus(false);
|
|
40
38
|
this.shutdownStatus = status;
|
|
41
39
|
this.setShutdown = setter;
|
|
42
|
-
this.logger.verbose("Reactor({ legacyStorage: @legacy })", features.legacyStorageEnabled);
|
|
43
40
|
this.readModelCoordinator.start();
|
|
44
41
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Signals that the reactor should shutdown.
|
|
47
|
-
*/
|
|
48
42
|
kill() {
|
|
49
43
|
this.logger.verbose("kill()");
|
|
50
|
-
// Mark the reactor as shutdown
|
|
51
44
|
this.setShutdown(true);
|
|
52
|
-
// Stop the read model coordinator
|
|
53
45
|
this.readModelCoordinator.stop();
|
|
54
|
-
// Stop the job tracker
|
|
55
46
|
this.jobTracker.shutdown();
|
|
56
47
|
return this.shutdownStatus;
|
|
57
48
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Retrieves a list of document model specifications
|
|
60
|
-
*/
|
|
61
49
|
getDocumentModels(namespace, paging, signal) {
|
|
62
50
|
this.logger.verbose("getDocumentModels(@namespace, @paging)", namespace, paging);
|
|
63
|
-
|
|
51
|
+
if (signal?.aborted) {
|
|
52
|
+
throw new AbortError();
|
|
53
|
+
}
|
|
64
54
|
const modules = this.documentModelRegistry.getAllModules();
|
|
65
55
|
const filteredModels = modules.filter((module) => !namespace || module.documentModel.global.id.startsWith(namespace));
|
|
66
|
-
// Apply paging
|
|
67
56
|
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
68
57
|
const limit = paging?.limit || filteredModels.length;
|
|
69
58
|
const pagedModels = filteredModels.slice(startIndex, startIndex + limit);
|
|
70
|
-
// Create paged results
|
|
71
59
|
const hasMore = startIndex + limit < filteredModels.length;
|
|
72
60
|
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
73
|
-
// even thought this is currently synchronous, they could have passed in an already-aborted signal
|
|
74
|
-
if (signal?.aborted) {
|
|
75
|
-
throw new AbortError();
|
|
76
|
-
}
|
|
77
61
|
return Promise.resolve({
|
|
78
62
|
results: pagedModels,
|
|
79
63
|
options: paging || { cursor: "0", limit: filteredModels.length },
|
|
@@ -83,197 +67,70 @@ export class Reactor {
|
|
|
83
67
|
: undefined,
|
|
84
68
|
});
|
|
85
69
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Retrieves a specific PHDocument by id
|
|
88
|
-
*/
|
|
89
70
|
async get(id, view, consistencyToken, signal) {
|
|
90
71
|
this.logger.verbose("get(@id, @view)", id, view);
|
|
91
|
-
|
|
92
|
-
const document = await this.documentStorage.get(id, consistencyToken, signal);
|
|
93
|
-
if (signal?.aborted) {
|
|
94
|
-
throw new AbortError();
|
|
95
|
-
}
|
|
96
|
-
const childIds = await this.documentStorage.getChildren(id, consistencyToken, signal);
|
|
97
|
-
if (signal?.aborted) {
|
|
98
|
-
throw new AbortError();
|
|
99
|
-
}
|
|
100
|
-
for (const scope in document.state) {
|
|
101
|
-
if (!matchesScope(view, scope)) {
|
|
102
|
-
delete document.state[scope];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
document,
|
|
107
|
-
childIds,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
const document = await this.documentView.get(id, view, consistencyToken, signal);
|
|
112
|
-
if (signal?.aborted) {
|
|
113
|
-
throw new AbortError();
|
|
114
|
-
}
|
|
115
|
-
const relationships = await this._documentIndexer.getOutgoing(id, ["child"], consistencyToken, signal);
|
|
116
|
-
if (signal?.aborted) {
|
|
117
|
-
throw new AbortError();
|
|
118
|
-
}
|
|
119
|
-
const childIds = relationships.map((rel) => rel.targetId);
|
|
120
|
-
return {
|
|
121
|
-
document,
|
|
122
|
-
childIds,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
72
|
+
return await this.documentView.get(id, view, consistencyToken, signal);
|
|
125
73
|
}
|
|
126
|
-
/**
|
|
127
|
-
* Retrieves a specific PHDocument by slug
|
|
128
|
-
*/
|
|
129
74
|
async getBySlug(slug, view, consistencyToken, signal) {
|
|
130
75
|
this.logger.verbose("getBySlug(@slug, @view)", slug, view);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
ids = await this.documentStorage.resolveIds([slug], consistencyToken, signal);
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
if (error instanceof Error && error.message.includes("not found")) {
|
|
138
|
-
throw new Error(`Document not found with slug: ${slug}`);
|
|
139
|
-
}
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
if (ids.length === 0 || !ids[0]) {
|
|
143
|
-
throw new Error(`Document not found with slug: ${slug}`);
|
|
144
|
-
}
|
|
145
|
-
return await this.get(ids[0], view, consistencyToken, signal);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
const documentId = await this.documentView.resolveSlug(slug, view, consistencyToken, signal);
|
|
149
|
-
if (!documentId) {
|
|
150
|
-
throw new Error(`Document not found with slug: ${slug}`);
|
|
151
|
-
}
|
|
152
|
-
return await this.get(documentId, view, consistencyToken, signal);
|
|
76
|
+
const documentId = await this.documentView.resolveSlug(slug, view, consistencyToken, signal);
|
|
77
|
+
if (!documentId) {
|
|
78
|
+
throw new Error(`Document not found with slug: ${slug}`);
|
|
153
79
|
}
|
|
80
|
+
return await this.get(documentId, view, consistencyToken, signal);
|
|
154
81
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Retrieves a specific PHDocument by identifier (either id or slug)
|
|
157
|
-
*/
|
|
158
82
|
async getByIdOrSlug(identifier, view, consistencyToken, signal) {
|
|
159
83
|
this.logger.verbose("getByIdOrSlug(@identifier, @view)", identifier, view);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const ids = await this.documentStorage.resolveIds([identifier], consistencyToken, signal);
|
|
167
|
-
if (ids.length === 0 || !ids[0]) {
|
|
168
|
-
throw new Error(`Document not found: ${identifier}`);
|
|
169
|
-
}
|
|
170
|
-
return await this.get(ids[0], view, consistencyToken, signal);
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
throw new Error(`Document not found: ${identifier}`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
84
|
+
return await this.documentView.getByIdOrSlug(identifier, view, consistencyToken, signal);
|
|
85
|
+
}
|
|
86
|
+
async getChildren(documentId, consistencyToken, signal) {
|
|
87
|
+
const relationships = await this.documentIndexer.getOutgoing(documentId, ["child"], undefined, consistencyToken, signal);
|
|
88
|
+
if (signal?.aborted) {
|
|
89
|
+
throw new AbortError();
|
|
176
90
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (signal?.aborted) {
|
|
184
|
-
throw new AbortError();
|
|
185
|
-
}
|
|
186
|
-
const childIds = relationships.map((rel) => rel.targetId);
|
|
187
|
-
return {
|
|
188
|
-
document,
|
|
189
|
-
childIds,
|
|
190
|
-
};
|
|
91
|
+
return relationships.results.map((rel) => rel.targetId);
|
|
92
|
+
}
|
|
93
|
+
async getParents(childId, consistencyToken, signal) {
|
|
94
|
+
const relationships = await this.documentIndexer.getIncoming(childId, ["parent"], undefined, consistencyToken, signal);
|
|
95
|
+
if (signal?.aborted) {
|
|
96
|
+
throw new AbortError();
|
|
191
97
|
}
|
|
98
|
+
return relationships.results.map((rel) => rel.sourceId);
|
|
192
99
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Retrieves the operations for a document
|
|
195
|
-
*/
|
|
196
100
|
async getOperations(documentId, view, filter, paging, consistencyToken, signal) {
|
|
197
101
|
this.logger.verbose("getOperations(@documentId, @view, @filter, @paging)", documentId, view, filter, paging);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
const operations = document.operations;
|
|
204
|
-
const result = {};
|
|
205
|
-
for (const scope in operations) {
|
|
206
|
-
if (matchesScope(view, scope)) {
|
|
207
|
-
let scopeOperations = operations[scope];
|
|
208
|
-
if (filter) {
|
|
209
|
-
if (filter.actionTypes && filter.actionTypes.length > 0) {
|
|
210
|
-
scopeOperations = scopeOperations.filter((op) => filter.actionTypes.includes(op.action.type));
|
|
211
|
-
}
|
|
212
|
-
if (filter.sinceRevision !== undefined) {
|
|
213
|
-
scopeOperations = scopeOperations.filter((op) => op.index >= filter.sinceRevision);
|
|
214
|
-
}
|
|
215
|
-
if (filter.timestampFrom) {
|
|
216
|
-
const fromMs = new Date(filter.timestampFrom).getTime();
|
|
217
|
-
scopeOperations = scopeOperations.filter((op) => new Date(op.timestampUtcMs).getTime() >= fromMs);
|
|
218
|
-
}
|
|
219
|
-
if (filter.timestampTo) {
|
|
220
|
-
const toMs = new Date(filter.timestampTo).getTime();
|
|
221
|
-
scopeOperations = scopeOperations.filter((op) => new Date(op.timestampUtcMs).getTime() <= toMs);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
225
|
-
const limit = paging?.limit || scopeOperations.length;
|
|
226
|
-
const pagedOperations = scopeOperations.slice(startIndex, startIndex + limit);
|
|
227
|
-
result[scope] = {
|
|
228
|
-
results: pagedOperations,
|
|
229
|
-
options: { cursor: String(startIndex + limit), limit },
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return Promise.resolve(result);
|
|
102
|
+
const branch = view?.branch || "main";
|
|
103
|
+
const revisions = await this.operationStore.getRevisions(documentId, branch, signal);
|
|
104
|
+
if (signal?.aborted) {
|
|
105
|
+
throw new AbortError();
|
|
234
106
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
107
|
+
const allScopes = Object.keys(revisions.revision);
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const scope of allScopes) {
|
|
110
|
+
if (!matchesScope(view, scope)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
238
113
|
if (signal?.aborted) {
|
|
239
114
|
throw new AbortError();
|
|
240
115
|
}
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
cursor: scopeResult.nextCursor || String(currentCursor),
|
|
257
|
-
limit: currentLimit,
|
|
258
|
-
},
|
|
259
|
-
nextCursor: scopeResult.nextCursor,
|
|
260
|
-
next: scopeResult.hasMore
|
|
261
|
-
? async () => {
|
|
262
|
-
const nextPage = await this.getOperations(documentId, view, filter, {
|
|
263
|
-
cursor: scopeResult.nextCursor,
|
|
264
|
-
limit: currentLimit,
|
|
265
|
-
}, consistencyToken, signal);
|
|
266
|
-
return nextPage[scope];
|
|
267
|
-
}
|
|
268
|
-
: undefined,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
return result;
|
|
116
|
+
const scopeResult = await this.operationStore.getSince(documentId, scope, branch, -1, filter, paging, signal);
|
|
117
|
+
result[scope] = {
|
|
118
|
+
results: scopeResult.results,
|
|
119
|
+
options: scopeResult.options,
|
|
120
|
+
nextCursor: scopeResult.nextCursor,
|
|
121
|
+
next: scopeResult.next
|
|
122
|
+
? async () => {
|
|
123
|
+
const nextPage = await this.getOperations(documentId, view, filter, {
|
|
124
|
+
cursor: scopeResult.nextCursor,
|
|
125
|
+
limit: scopeResult.options.limit,
|
|
126
|
+
}, consistencyToken, signal);
|
|
127
|
+
return nextPage[scope];
|
|
128
|
+
}
|
|
129
|
+
: undefined,
|
|
130
|
+
};
|
|
272
131
|
}
|
|
132
|
+
return result;
|
|
273
133
|
}
|
|
274
|
-
/**
|
|
275
|
-
* Filters documents by criteria and returns a list of them
|
|
276
|
-
*/
|
|
277
134
|
async find(search, view, paging, consistencyToken, signal) {
|
|
278
135
|
this.logger.verbose("find(@search, @view, @paging)", search, view, paging);
|
|
279
136
|
let results;
|
|
@@ -293,7 +150,7 @@ export class Reactor {
|
|
|
293
150
|
}
|
|
294
151
|
}
|
|
295
152
|
else if (search.parentId) {
|
|
296
|
-
results = await this.findByParentId(search.parentId, view, paging, signal);
|
|
153
|
+
results = await this.findByParentId(search.parentId, view, paging, consistencyToken, signal);
|
|
297
154
|
if (search.type) {
|
|
298
155
|
results = filterByType(results, search.type);
|
|
299
156
|
}
|
|
@@ -309,9 +166,6 @@ export class Reactor {
|
|
|
309
166
|
}
|
|
310
167
|
return results;
|
|
311
168
|
}
|
|
312
|
-
/**
|
|
313
|
-
* Creates a document
|
|
314
|
-
*/
|
|
315
169
|
async create(document, signer, signal, meta) {
|
|
316
170
|
this.logger.verbose("create(@id, @type, @slug)", document.header.id, document.header.documentType, document.header.slug);
|
|
317
171
|
const createdAtUtcIso = new Date().toISOString();
|
|
@@ -345,12 +199,10 @@ export class Reactor {
|
|
|
345
199
|
toVersion: document.state.document.version,
|
|
346
200
|
initialState: document.state,
|
|
347
201
|
});
|
|
348
|
-
// Sign actions if signer is provided
|
|
349
202
|
let actions = [createAction, upgradeAction];
|
|
350
203
|
if (signer) {
|
|
351
204
|
actions = await signActions(actions, signer, signal);
|
|
352
205
|
}
|
|
353
|
-
// Create a single job with both CREATE_DOCUMENT and UPGRADE_DOCUMENT actions
|
|
354
206
|
const job = {
|
|
355
207
|
id: uuidv4(),
|
|
356
208
|
kind: "mutation",
|
|
@@ -365,7 +217,6 @@ export class Reactor {
|
|
|
365
217
|
errorHistory: [],
|
|
366
218
|
meta,
|
|
367
219
|
};
|
|
368
|
-
// Create job info and register with tracker
|
|
369
220
|
const jobInfo = {
|
|
370
221
|
id: job.id,
|
|
371
222
|
status: JobStatus.PENDING,
|
|
@@ -379,13 +230,9 @@ export class Reactor {
|
|
|
379
230
|
};
|
|
380
231
|
this.jobTracker.registerJob(jobInfo);
|
|
381
232
|
this.emitJobPending(jobInfo.id, meta);
|
|
382
|
-
// Enqueue the job
|
|
383
233
|
await this.queue.enqueue(job);
|
|
384
234
|
return jobInfo;
|
|
385
235
|
}
|
|
386
|
-
/**
|
|
387
|
-
* Deletes a document
|
|
388
|
-
*/
|
|
389
236
|
async deleteDocument(id, signer, signal, meta) {
|
|
390
237
|
this.logger.verbose("deleteDocument(@id)", id);
|
|
391
238
|
const createdAtUtcIso = new Date().toISOString();
|
|
@@ -393,7 +240,6 @@ export class Reactor {
|
|
|
393
240
|
throw new AbortError();
|
|
394
241
|
}
|
|
395
242
|
let action = deleteDocumentAction(id);
|
|
396
|
-
// Sign action if signer is provided
|
|
397
243
|
if (signer) {
|
|
398
244
|
action = await signAction(action, signer, signal);
|
|
399
245
|
}
|
|
@@ -427,18 +273,13 @@ export class Reactor {
|
|
|
427
273
|
await this.queue.enqueue(job);
|
|
428
274
|
return jobInfo;
|
|
429
275
|
}
|
|
430
|
-
/**
|
|
431
|
-
* Applies a list of actions to a document
|
|
432
|
-
*/
|
|
433
276
|
async execute(docId, branch, actions, signal, meta) {
|
|
434
277
|
this.logger.verbose("execute(@docId, @branch, @actions)", docId, branch, actions);
|
|
435
278
|
if (signal?.aborted) {
|
|
436
279
|
throw new AbortError();
|
|
437
280
|
}
|
|
438
281
|
const createdAtUtcIso = new Date().toISOString();
|
|
439
|
-
|
|
440
|
-
const scope = actions.length > 0 ? actions[0].scope || "global" : "global";
|
|
441
|
-
// Create a single job with all actions
|
|
282
|
+
const scope = getSharedActionScope(actions);
|
|
442
283
|
const job = {
|
|
443
284
|
id: uuidv4(),
|
|
444
285
|
kind: "mutation",
|
|
@@ -453,7 +294,6 @@ export class Reactor {
|
|
|
453
294
|
errorHistory: [],
|
|
454
295
|
meta,
|
|
455
296
|
};
|
|
456
|
-
// Create job info and register with tracker
|
|
457
297
|
const jobInfo = {
|
|
458
298
|
id: job.id,
|
|
459
299
|
status: JobStatus.PENDING,
|
|
@@ -467,18 +307,12 @@ export class Reactor {
|
|
|
467
307
|
};
|
|
468
308
|
this.jobTracker.registerJob(jobInfo);
|
|
469
309
|
this.emitJobPending(jobInfo.id, meta);
|
|
470
|
-
// Enqueue the job
|
|
471
310
|
await this.queue.enqueue(job);
|
|
472
311
|
if (signal?.aborted) {
|
|
473
312
|
throw new AbortError();
|
|
474
313
|
}
|
|
475
314
|
return jobInfo;
|
|
476
315
|
}
|
|
477
|
-
/**
|
|
478
|
-
* Imports pre-existing operations that were produced by another reactor.
|
|
479
|
-
* This function may cause a reshuffle, which will generate additional
|
|
480
|
-
* operations.
|
|
481
|
-
*/
|
|
482
316
|
async load(docId, branch, operations, signal, meta) {
|
|
483
317
|
this.logger.verbose("load(@docId, @branch, @count, @operations)", docId, branch, operations.length, operations);
|
|
484
318
|
if (signal?.aborted) {
|
|
@@ -487,13 +321,7 @@ export class Reactor {
|
|
|
487
321
|
if (operations.length === 0) {
|
|
488
322
|
throw new Error("load requires at least one operation");
|
|
489
323
|
}
|
|
490
|
-
|
|
491
|
-
const scope = getSharedScope(operations);
|
|
492
|
-
operations.forEach((operation, index) => {
|
|
493
|
-
if (!operation.timestampUtcMs) {
|
|
494
|
-
throw new Error(`Operation at position ${index} is missing timestampUtcMs`);
|
|
495
|
-
}
|
|
496
|
-
});
|
|
324
|
+
const scope = getSharedOperationScope(operations);
|
|
497
325
|
const createdAtUtcIso = new Date().toISOString();
|
|
498
326
|
const job = {
|
|
499
327
|
id: uuidv4(),
|
|
@@ -528,9 +356,6 @@ export class Reactor {
|
|
|
528
356
|
}
|
|
529
357
|
return jobInfo;
|
|
530
358
|
}
|
|
531
|
-
/**
|
|
532
|
-
* Applies multiple mutations across documents with dependency management
|
|
533
|
-
*/
|
|
534
359
|
async executeBatch(request, signal, meta) {
|
|
535
360
|
this.logger.verbose("executeBatch(@count jobs)", request.jobs.length);
|
|
536
361
|
if (signal?.aborted) {
|
|
@@ -611,39 +436,28 @@ export class Reactor {
|
|
|
611
436
|
};
|
|
612
437
|
return result;
|
|
613
438
|
}
|
|
614
|
-
/**
|
|
615
|
-
* Adds multiple documents as children to another
|
|
616
|
-
*/
|
|
617
439
|
async addChildren(parentId, documentIds, branch = "main", signer, signal) {
|
|
618
440
|
this.logger.verbose("addChildren(@parentId, @count children, @branch)", parentId, documentIds.length, branch);
|
|
619
441
|
if (signal?.aborted) {
|
|
620
442
|
throw new AbortError();
|
|
621
443
|
}
|
|
622
444
|
let actions = documentIds.map((childId) => addRelationshipAction(parentId, childId, "child"));
|
|
623
|
-
// Sign actions if signer is provided
|
|
624
445
|
if (signer) {
|
|
625
446
|
actions = await signActions(actions, signer, signal);
|
|
626
447
|
}
|
|
627
448
|
return await this.execute(parentId, branch, actions, signal);
|
|
628
449
|
}
|
|
629
|
-
/**
|
|
630
|
-
* Removes multiple documents as children from another
|
|
631
|
-
*/
|
|
632
450
|
async removeChildren(parentId, documentIds, branch = "main", signer, signal) {
|
|
633
451
|
this.logger.verbose("removeChildren(@parentId, @count children, @branch)", parentId, documentIds.length, branch);
|
|
634
452
|
if (signal?.aborted) {
|
|
635
453
|
throw new AbortError();
|
|
636
454
|
}
|
|
637
455
|
let actions = documentIds.map((childId) => removeRelationshipAction(parentId, childId, "child"));
|
|
638
|
-
// Sign actions if signer is provided
|
|
639
456
|
if (signer) {
|
|
640
457
|
actions = await signActions(actions, signer, signal);
|
|
641
458
|
}
|
|
642
459
|
return await this.execute(parentId, branch, actions, signal);
|
|
643
460
|
}
|
|
644
|
-
/**
|
|
645
|
-
* Retrieves the status of a job
|
|
646
|
-
*/
|
|
647
461
|
getJobStatus(jobId, signal) {
|
|
648
462
|
this.logger.verbose("getJobStatus(@jobId)", jobId);
|
|
649
463
|
if (signal?.aborted) {
|
|
@@ -651,7 +465,6 @@ export class Reactor {
|
|
|
651
465
|
}
|
|
652
466
|
const jobInfo = this.jobTracker.getJobStatus(jobId);
|
|
653
467
|
if (!jobInfo) {
|
|
654
|
-
// Job not found - return FAILED status with appropriate error
|
|
655
468
|
const now = new Date().toISOString();
|
|
656
469
|
return Promise.resolve({
|
|
657
470
|
id: jobId,
|
|
@@ -668,327 +481,34 @@ export class Reactor {
|
|
|
668
481
|
}
|
|
669
482
|
return Promise.resolve(jobInfo);
|
|
670
483
|
}
|
|
671
|
-
/**
|
|
672
|
-
* Finds documents by their IDs
|
|
673
|
-
*/
|
|
674
484
|
async findByIds(ids, view, paging, consistencyToken, signal) {
|
|
675
485
|
this.logger.verbose("findByIds(@count ids)", ids.length);
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
try {
|
|
688
|
-
document = await this.documentStorage.get(id, consistencyToken, signal);
|
|
689
|
-
}
|
|
690
|
-
catch {
|
|
691
|
-
// Skip documents that don't exist or can't be accessed
|
|
692
|
-
// This matches the behavior expected from a search operation
|
|
693
|
-
continue;
|
|
694
|
-
}
|
|
695
|
-
// Apply view filter - This will be removed when we pass the viewfilter along
|
|
696
|
-
// to the underlying store, but is here now for the interface.
|
|
697
|
-
for (const scope in document.state) {
|
|
698
|
-
if (!matchesScope(view, scope)) {
|
|
699
|
-
delete document.state[scope];
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
documents.push(document);
|
|
703
|
-
}
|
|
704
|
-
if (signal?.aborted) {
|
|
705
|
-
throw new AbortError();
|
|
706
|
-
}
|
|
707
|
-
// Apply paging
|
|
708
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
709
|
-
const limit = paging?.limit || documents.length;
|
|
710
|
-
const pagedDocuments = documents.slice(startIndex, startIndex + limit);
|
|
711
|
-
// Create paged results
|
|
712
|
-
const hasMore = startIndex + limit < documents.length;
|
|
713
|
-
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
714
|
-
return {
|
|
715
|
-
results: pagedDocuments,
|
|
716
|
-
options: paging || { cursor: "0", limit: documents.length },
|
|
717
|
-
nextCursor,
|
|
718
|
-
next: hasMore
|
|
719
|
-
? () => this.findByIds(ids, view, { cursor: nextCursor, limit }, consistencyToken, signal)
|
|
720
|
-
: undefined,
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
else {
|
|
724
|
-
const documents = [];
|
|
725
|
-
// Fetch each document by ID using documentView
|
|
726
|
-
for (const id of ids) {
|
|
727
|
-
if (signal?.aborted) {
|
|
728
|
-
throw new AbortError();
|
|
729
|
-
}
|
|
730
|
-
try {
|
|
731
|
-
const document = await this.documentView.get(id, view, undefined, signal);
|
|
732
|
-
documents.push(document);
|
|
733
|
-
}
|
|
734
|
-
catch {
|
|
735
|
-
// Skip documents that don't exist or can't be accessed
|
|
736
|
-
continue;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
if (signal?.aborted) {
|
|
740
|
-
throw new AbortError();
|
|
741
|
-
}
|
|
742
|
-
// Apply paging
|
|
743
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
744
|
-
const limit = paging?.limit || documents.length;
|
|
745
|
-
const pagedDocuments = documents.slice(startIndex, startIndex + limit);
|
|
746
|
-
// Create paged results
|
|
747
|
-
const hasMore = startIndex + limit < documents.length;
|
|
748
|
-
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
749
|
-
return {
|
|
750
|
-
results: pagedDocuments,
|
|
751
|
-
options: paging || { cursor: "0", limit: documents.length },
|
|
752
|
-
nextCursor,
|
|
753
|
-
next: hasMore
|
|
754
|
-
? () => this.findByIds(ids, view, { cursor: nextCursor, limit }, consistencyToken, signal)
|
|
755
|
-
: undefined,
|
|
756
|
-
};
|
|
757
|
-
}
|
|
486
|
+
const startIndex = paging?.cursor ? parseInt(paging.cursor) || 0 : 0;
|
|
487
|
+
const limit = paging?.limit || ids.length;
|
|
488
|
+
const pagedIds = ids.slice(startIndex, startIndex + limit);
|
|
489
|
+
const results = await this.documentView.getMany(pagedIds, view, consistencyToken, signal);
|
|
490
|
+
const hasMore = startIndex + limit < ids.length;
|
|
491
|
+
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
492
|
+
return {
|
|
493
|
+
results,
|
|
494
|
+
options: paging || { cursor: "0", limit: ids.length },
|
|
495
|
+
nextCursor,
|
|
496
|
+
};
|
|
758
497
|
}
|
|
759
|
-
/**
|
|
760
|
-
* Finds documents by their slugs
|
|
761
|
-
*/
|
|
762
498
|
async findBySlugs(slugs, view, paging, consistencyToken, signal) {
|
|
763
499
|
this.logger.verbose("findBySlugs(@count slugs)", slugs.length);
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
}
|
|
767
|
-
if (this.features.legacyStorageEnabled) {
|
|
768
|
-
const documents = [];
|
|
769
|
-
// Use storage to resolve slugs to IDs
|
|
770
|
-
let ids;
|
|
771
|
-
try {
|
|
772
|
-
ids = await this.documentStorage.resolveIds(slugs, consistencyToken, signal);
|
|
773
|
-
}
|
|
774
|
-
catch {
|
|
775
|
-
// If slug resolution fails, return empty results
|
|
776
|
-
// This matches the behavior expected from a search operation
|
|
777
|
-
ids = [];
|
|
778
|
-
}
|
|
779
|
-
// Fetch each document by resolved ID
|
|
780
|
-
for (const id of ids) {
|
|
781
|
-
if (signal?.aborted) {
|
|
782
|
-
throw new AbortError();
|
|
783
|
-
}
|
|
784
|
-
let document;
|
|
785
|
-
try {
|
|
786
|
-
document = await this.documentStorage.get(id, consistencyToken, signal);
|
|
787
|
-
}
|
|
788
|
-
catch {
|
|
789
|
-
// Skip documents that don't exist or can't be accessed
|
|
790
|
-
continue;
|
|
791
|
-
}
|
|
792
|
-
// Apply view filter - This will be removed when we pass the viewfilter along
|
|
793
|
-
// to the underlying store, but is here now for the interface.
|
|
794
|
-
for (const scope in document.state) {
|
|
795
|
-
if (!matchesScope(view, scope)) {
|
|
796
|
-
delete document.state[scope];
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
documents.push(document);
|
|
800
|
-
}
|
|
801
|
-
if (signal?.aborted) {
|
|
802
|
-
throw new AbortError();
|
|
803
|
-
}
|
|
804
|
-
// Apply paging - this will be removed when we pass the paging along
|
|
805
|
-
// to the underlying store, but is here now for the interface.
|
|
806
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
807
|
-
const limit = paging?.limit || documents.length;
|
|
808
|
-
const pagedDocuments = documents.slice(startIndex, startIndex + limit);
|
|
809
|
-
// Create paged results
|
|
810
|
-
const hasMore = startIndex + limit < documents.length;
|
|
811
|
-
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
812
|
-
return {
|
|
813
|
-
results: pagedDocuments,
|
|
814
|
-
options: paging || { cursor: "0", limit: documents.length },
|
|
815
|
-
nextCursor,
|
|
816
|
-
next: hasMore
|
|
817
|
-
? () => this.findBySlugs(slugs, view, { cursor: nextCursor, limit }, consistencyToken, signal)
|
|
818
|
-
: undefined,
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
const documents = [];
|
|
823
|
-
// Resolve each slug to a document ID
|
|
824
|
-
const documentIds = [];
|
|
825
|
-
for (const slug of slugs) {
|
|
826
|
-
if (signal?.aborted) {
|
|
827
|
-
throw new AbortError();
|
|
828
|
-
}
|
|
829
|
-
const documentId = await this.documentView.resolveSlug(slug, view, undefined, signal);
|
|
830
|
-
if (documentId) {
|
|
831
|
-
documentIds.push(documentId);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
// Fetch each document
|
|
835
|
-
for (const documentId of documentIds) {
|
|
836
|
-
if (signal?.aborted) {
|
|
837
|
-
throw new AbortError();
|
|
838
|
-
}
|
|
839
|
-
try {
|
|
840
|
-
const document = await this.documentView.get(documentId, view, undefined, signal);
|
|
841
|
-
documents.push(document);
|
|
842
|
-
}
|
|
843
|
-
catch {
|
|
844
|
-
// Skip documents that don't exist or can't be accessed
|
|
845
|
-
continue;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (signal?.aborted) {
|
|
849
|
-
throw new AbortError();
|
|
850
|
-
}
|
|
851
|
-
// Apply paging
|
|
852
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
853
|
-
const limit = paging?.limit || documents.length;
|
|
854
|
-
const pagedDocuments = documents.slice(startIndex, startIndex + limit);
|
|
855
|
-
// Create paged results
|
|
856
|
-
const hasMore = startIndex + limit < documents.length;
|
|
857
|
-
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
858
|
-
return {
|
|
859
|
-
results: pagedDocuments,
|
|
860
|
-
options: paging || { cursor: "0", limit: documents.length },
|
|
861
|
-
nextCursor,
|
|
862
|
-
next: hasMore
|
|
863
|
-
? () => this.findBySlugs(slugs, view, { cursor: nextCursor, limit }, consistencyToken, signal)
|
|
864
|
-
: undefined,
|
|
865
|
-
};
|
|
866
|
-
}
|
|
500
|
+
const ids = await this.documentView.resolveSlugs(slugs, view, consistencyToken, signal);
|
|
501
|
+
return await this.findByIds(ids, view, paging, consistencyToken, signal);
|
|
867
502
|
}
|
|
868
|
-
|
|
869
|
-
* Finds documents by parent ID
|
|
870
|
-
*/
|
|
871
|
-
async findByParentId(parentId, view, paging, signal) {
|
|
503
|
+
async findByParentId(parentId, view, paging, consistencyToken, signal) {
|
|
872
504
|
this.logger.verbose("findByParentId(@parentId)", parentId);
|
|
873
|
-
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
throw new AbortError();
|
|
877
|
-
}
|
|
878
|
-
const documents = [];
|
|
879
|
-
// Fetch each child document using the appropriate storage method
|
|
880
|
-
for (const relationship of relationships) {
|
|
881
|
-
if (signal?.aborted) {
|
|
882
|
-
throw new AbortError();
|
|
883
|
-
}
|
|
884
|
-
try {
|
|
885
|
-
let document;
|
|
886
|
-
if (this.features.legacyStorageEnabled) {
|
|
887
|
-
document = await this.documentStorage.get(relationship.targetId);
|
|
888
|
-
// Apply view filter for legacy storage
|
|
889
|
-
for (const scope in document.state) {
|
|
890
|
-
if (!matchesScope(view, scope)) {
|
|
891
|
-
delete document.state[scope];
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
else {
|
|
896
|
-
document = await this.documentView.get(relationship.targetId, view, undefined, signal);
|
|
897
|
-
}
|
|
898
|
-
documents.push(document);
|
|
899
|
-
}
|
|
900
|
-
catch {
|
|
901
|
-
// Skip documents that don't exist or can't be accessed
|
|
902
|
-
continue;
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
if (signal?.aborted) {
|
|
906
|
-
throw new AbortError();
|
|
907
|
-
}
|
|
908
|
-
// Apply paging
|
|
909
|
-
const startIndex = paging ? parseInt(paging.cursor) || 0 : 0;
|
|
910
|
-
const limit = paging?.limit || documents.length;
|
|
911
|
-
const pagedDocuments = documents.slice(startIndex, startIndex + limit);
|
|
912
|
-
// Create paged results
|
|
913
|
-
const hasMore = startIndex + limit < documents.length;
|
|
914
|
-
const nextCursor = hasMore ? String(startIndex + limit) : undefined;
|
|
915
|
-
return {
|
|
916
|
-
results: pagedDocuments,
|
|
917
|
-
options: paging || { cursor: "0", limit: documents.length },
|
|
918
|
-
nextCursor,
|
|
919
|
-
next: hasMore
|
|
920
|
-
? () => this.findByParentId(parentId, view, { cursor: nextCursor, limit }, signal)
|
|
921
|
-
: undefined,
|
|
922
|
-
};
|
|
505
|
+
const relationships = await this.documentIndexer.getOutgoing(parentId, ["child"], paging, consistencyToken, signal);
|
|
506
|
+
const ids = relationships.results.map((rel) => rel.targetId);
|
|
507
|
+
return await this.findByIds(ids, view, paging, undefined, signal);
|
|
923
508
|
}
|
|
924
|
-
/**
|
|
925
|
-
* Finds documents by type
|
|
926
|
-
*/
|
|
927
509
|
async findByType(type, view, paging, consistencyToken, signal) {
|
|
928
510
|
this.logger.verbose("findByType(@type)", type);
|
|
929
|
-
|
|
930
|
-
await this.documentView.waitForConsistency(consistencyToken, undefined, signal);
|
|
931
|
-
}
|
|
932
|
-
if (this.features.legacyStorageEnabled) {
|
|
933
|
-
const documents = [];
|
|
934
|
-
// Use storage's findByType method directly
|
|
935
|
-
const cursor = paging?.cursor;
|
|
936
|
-
const limit = paging?.limit || 100;
|
|
937
|
-
// Get document IDs of the specified type
|
|
938
|
-
const { documents: documentIds, nextCursor } = await this.documentStorage.findByType(type, limit, cursor, consistencyToken, signal);
|
|
939
|
-
if (signal?.aborted) {
|
|
940
|
-
throw new AbortError();
|
|
941
|
-
}
|
|
942
|
-
// Fetch each document by its ID
|
|
943
|
-
for (const documentId of documentIds) {
|
|
944
|
-
if (signal?.aborted) {
|
|
945
|
-
throw new AbortError();
|
|
946
|
-
}
|
|
947
|
-
let document;
|
|
948
|
-
try {
|
|
949
|
-
document = await this.documentStorage.get(documentId, consistencyToken, signal);
|
|
950
|
-
}
|
|
951
|
-
catch {
|
|
952
|
-
// Skip documents that can't be retrieved
|
|
953
|
-
continue;
|
|
954
|
-
}
|
|
955
|
-
// Apply view filter
|
|
956
|
-
for (const scope in document.state) {
|
|
957
|
-
if (!matchesScope(view, scope)) {
|
|
958
|
-
delete document.state[scope];
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
documents.push(document);
|
|
962
|
-
}
|
|
963
|
-
if (signal?.aborted) {
|
|
964
|
-
throw new AbortError();
|
|
965
|
-
}
|
|
966
|
-
// Results are already paged from the storage layer
|
|
967
|
-
return {
|
|
968
|
-
results: documents,
|
|
969
|
-
options: paging || { cursor: cursor || "0", limit },
|
|
970
|
-
nextCursor,
|
|
971
|
-
next: nextCursor
|
|
972
|
-
? async () => this.findByType(type, view, { cursor: nextCursor, limit }, consistencyToken, signal)
|
|
973
|
-
: undefined,
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
else {
|
|
977
|
-
const result = await this.documentView.findByType(type, view, paging, consistencyToken, signal);
|
|
978
|
-
if (signal?.aborted) {
|
|
979
|
-
throw new AbortError();
|
|
980
|
-
}
|
|
981
|
-
const cursor = paging?.cursor;
|
|
982
|
-
const limit = paging?.limit || 100;
|
|
983
|
-
return {
|
|
984
|
-
results: result.items,
|
|
985
|
-
options: paging || { cursor: cursor || "0", limit },
|
|
986
|
-
nextCursor: result.nextCursor,
|
|
987
|
-
next: result.nextCursor
|
|
988
|
-
? async () => this.findByType(type, view, { cursor: result.nextCursor, limit }, consistencyToken, signal)
|
|
989
|
-
: undefined,
|
|
990
|
-
};
|
|
991
|
-
}
|
|
511
|
+
return await this.documentView.findByType(type, view, paging, consistencyToken, signal);
|
|
992
512
|
}
|
|
993
513
|
emitJobPending(jobId, meta) {
|
|
994
514
|
const event = {
|