@powerhousedao/reactor 6.0.0-dev.6 → 6.0.0-dev.61
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/collection-membership-cache.d.ts +13 -0
- package/dist/src/cache/collection-membership-cache.d.ts.map +1 -0
- package/dist/src/cache/collection-membership-cache.js +33 -0
- package/dist/src/cache/collection-membership-cache.js.map +1 -0
- package/dist/src/cache/document-meta-cache.d.ts.map +1 -1
- package/dist/src/cache/document-meta-cache.js +6 -5
- package/dist/src/cache/document-meta-cache.js.map +1 -1
- package/dist/src/cache/kysely-operation-index.d.ts +6 -1
- package/dist/src/cache/kysely-operation-index.d.ts.map +1 -1
- package/dist/src/cache/kysely-operation-index.js +102 -7
- package/dist/src/cache/kysely-operation-index.js.map +1 -1
- package/dist/src/cache/kysely-write-cache.d.ts +9 -2
- package/dist/src/cache/kysely-write-cache.d.ts.map +1 -1
- package/dist/src/cache/kysely-write-cache.js +38 -15
- package/dist/src/cache/kysely-write-cache.js.map +1 -1
- package/dist/src/cache/operation-index-types.d.ts +16 -2
- 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/cache/write/interfaces.d.ts +7 -2
- package/dist/src/cache/write/interfaces.d.ts.map +1 -1
- package/dist/src/client/reactor-client.d.ts +13 -10
- package/dist/src/client/reactor-client.d.ts.map +1 -1
- package/dist/src/client/reactor-client.js +134 -43
- package/dist/src/client/reactor-client.js.map +1 -1
- package/dist/src/client/types.d.ts +25 -6
- package/dist/src/client/types.d.ts.map +1 -1
- package/dist/src/client/types.js.map +1 -1
- package/dist/src/core/reactor-builder.d.ts +23 -7
- package/dist/src/core/reactor-builder.d.ts.map +1 -1
- package/dist/src/core/reactor-builder.js +99 -24
- package/dist/src/core/reactor-builder.js.map +1 -1
- package/dist/src/core/reactor-client-builder.d.ts +5 -4
- package/dist/src/core/reactor-client-builder.d.ts.map +1 -1
- package/dist/src/core/reactor-client-builder.js +14 -5
- package/dist/src/core/reactor-client-builder.js.map +1 -1
- package/dist/src/core/reactor.d.ts +20 -80
- package/dist/src/core/reactor.d.ts.map +1 -1
- package/dist/src/core/reactor.js +235 -576
- package/dist/src/core/reactor.js.map +1 -1
- package/dist/src/core/types.d.ts +64 -28
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/utils.d.ts +39 -3
- package/dist/src/core/utils.d.ts.map +1 -1
- package/dist/src/core/utils.js +63 -9
- package/dist/src/core/utils.js.map +1 -1
- package/dist/src/events/types.d.ts +35 -10
- package/dist/src/events/types.d.ts.map +1 -1
- package/dist/src/events/types.js +7 -5
- package/dist/src/events/types.js.map +1 -1
- package/dist/src/executor/document-action-handler.d.ts +37 -0
- package/dist/src/executor/document-action-handler.d.ts.map +1 -0
- package/dist/src/executor/document-action-handler.js +356 -0
- package/dist/src/executor/document-action-handler.js.map +1 -0
- package/dist/src/executor/signature-verifier.d.ts +9 -0
- package/dist/src/executor/signature-verifier.d.ts.map +1 -0
- package/dist/src/executor/signature-verifier.js +70 -0
- package/dist/src/executor/signature-verifier.js.map +1 -0
- package/dist/src/executor/simple-job-executor-manager.d.ts +6 -1
- package/dist/src/executor/simple-job-executor-manager.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor-manager.js +125 -13
- package/dist/src/executor/simple-job-executor-manager.js.map +1 -1
- package/dist/src/executor/simple-job-executor.d.ts +6 -46
- package/dist/src/executor/simple-job-executor.d.ts.map +1 -1
- package/dist/src/executor/simple-job-executor.js +113 -588
- package/dist/src/executor/simple-job-executor.js.map +1 -1
- package/dist/src/executor/types.d.ts +1 -3
- package/dist/src/executor/types.d.ts.map +1 -1
- package/dist/src/executor/types.js.map +1 -1
- package/dist/src/executor/util.d.ts +12 -2
- package/dist/src/executor/util.d.ts.map +1 -1
- package/dist/src/executor/util.js +47 -1
- package/dist/src/executor/util.js.map +1 -1
- package/dist/src/index.d.ts +11 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/job-tracker/in-memory-job-tracker.d.ts +4 -3
- package/dist/src/job-tracker/in-memory-job-tracker.d.ts.map +1 -1
- package/dist/src/job-tracker/in-memory-job-tracker.js +20 -18
- package/dist/src/job-tracker/in-memory-job-tracker.js.map +1 -1
- package/dist/src/job-tracker/interfaces.d.ts +3 -1
- package/dist/src/job-tracker/interfaces.d.ts.map +1 -1
- package/dist/src/logging/console.d.ts +1 -22
- package/dist/src/logging/console.d.ts.map +1 -1
- package/dist/src/logging/console.js +1 -107
- package/dist/src/logging/console.js.map +1 -1
- package/dist/src/logging/types.d.ts +1 -11
- package/dist/src/logging/types.d.ts.map +1 -1
- package/dist/src/processors/index.d.ts +1 -1
- package/dist/src/processors/index.d.ts.map +1 -1
- package/dist/src/processors/index.js.map +1 -1
- package/dist/src/processors/processor-manager.d.ts +2 -2
- package/dist/src/processors/processor-manager.d.ts.map +1 -1
- package/dist/src/processors/processor-manager.js.map +1 -1
- package/dist/src/processors/relational/types.d.ts +2 -0
- package/dist/src/processors/relational/types.d.ts.map +1 -0
- package/dist/src/processors/relational/types.js +2 -0
- package/dist/src/processors/relational/types.js.map +1 -0
- package/dist/src/processors/relational/utils.d.ts +2 -0
- package/dist/src/processors/relational/utils.d.ts.map +1 -0
- package/dist/src/processors/relational/utils.js +2 -0
- package/dist/src/processors/relational/utils.js.map +1 -0
- package/dist/src/processors/utils.d.ts +2 -2
- package/dist/src/processors/utils.d.ts.map +1 -1
- package/dist/src/processors/utils.js +2 -1
- package/dist/src/processors/utils.js.map +1 -1
- package/dist/src/queue/job-execution-handle.d.ts +3 -0
- package/dist/src/queue/job-execution-handle.d.ts.map +1 -1
- package/dist/src/queue/job-execution-handle.js +9 -0
- package/dist/src/queue/job-execution-handle.js.map +1 -1
- package/dist/src/queue/queue.d.ts +30 -1
- package/dist/src/queue/queue.d.ts.map +1 -1
- package/dist/src/queue/queue.js +110 -1
- package/dist/src/queue/queue.js.map +1 -1
- package/dist/src/queue/types.d.ts +4 -3
- package/dist/src/queue/types.d.ts.map +1 -1
- package/dist/src/queue/types.js.map +1 -1
- package/dist/src/read-models/base-read-model.d.ts +1 -1
- package/dist/src/read-models/base-read-model.d.ts.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/coordinator.d.ts +2 -2
- package/dist/src/read-models/coordinator.d.ts.map +1 -1
- package/dist/src/read-models/coordinator.js +8 -8
- package/dist/src/read-models/coordinator.js.map +1 -1
- package/dist/src/read-models/document-view.d.ts +6 -3
- package/dist/src/read-models/document-view.d.ts.map +1 -1
- package/dist/src/read-models/document-view.js +130 -48
- package/dist/src/read-models/document-view.js.map +1 -1
- package/dist/src/read-models/interfaces.d.ts +1 -1
- package/dist/src/read-models/interfaces.d.ts.map +1 -1
- package/dist/src/registry/document-model-resolver.d.ts +29 -0
- package/dist/src/registry/document-model-resolver.d.ts.map +1 -0
- package/dist/src/registry/document-model-resolver.js +81 -0
- package/dist/src/registry/document-model-resolver.js.map +1 -0
- package/dist/src/registry/implementation.d.ts +4 -0
- package/dist/src/registry/implementation.d.ts.map +1 -1
- package/dist/src/registry/implementation.js +10 -0
- package/dist/src/registry/implementation.js.map +1 -1
- package/dist/src/registry/index.d.ts +3 -1
- package/dist/src/registry/index.d.ts.map +1 -1
- package/dist/src/registry/index.js +1 -0
- package/dist/src/registry/index.js.map +1 -1
- package/dist/src/registry/interfaces.d.ts +8 -0
- package/dist/src/registry/interfaces.d.ts.map +1 -1
- package/dist/src/shared/awaiter.d.ts +2 -2
- package/dist/src/shared/awaiter.d.ts.map +1 -1
- package/dist/src/shared/awaiter.js +11 -11
- package/dist/src/shared/awaiter.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/shared/drive-url.d.ts +15 -0
- package/dist/src/shared/drive-url.d.ts.map +1 -0
- package/dist/src/shared/drive-url.js +17 -0
- package/dist/src/shared/drive-url.js.map +1 -0
- package/dist/src/shared/errors.d.ts +9 -0
- package/dist/src/shared/errors.d.ts.map +1 -1
- package/dist/src/shared/errors.js +18 -0
- package/dist/src/shared/errors.js.map +1 -1
- package/dist/src/shared/factories.d.ts +6 -2
- package/dist/src/shared/factories.d.ts.map +1 -1
- package/dist/src/shared/factories.js +10 -2
- package/dist/src/shared/factories.js.map +1 -1
- package/dist/src/shared/types.d.ts +32 -6
- package/dist/src/shared/types.d.ts.map +1 -1
- package/dist/src/shared/types.js +4 -4
- package/dist/src/shared/types.js.map +1 -1
- 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 +238 -124
- package/dist/src/storage/interfaces.d.ts.map +1 -1
- package/dist/src/storage/interfaces.js +10 -0
- package/dist/src/storage/interfaces.js.map +1 -1
- package/dist/src/storage/kysely/document-indexer.d.ts +8 -7
- 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 +5 -4
- package/dist/src/storage/kysely/store.d.ts.map +1 -1
- package/dist/src/storage/kysely/store.js +52 -21
- package/dist/src/storage/kysely/store.js.map +1 -1
- package/dist/src/storage/kysely/sync-cursor-storage.d.ts +1 -1
- package/dist/src/storage/kysely/sync-cursor-storage.d.ts.map +1 -1
- package/dist/src/storage/kysely/sync-cursor-storage.js +6 -2
- package/dist/src/storage/kysely/sync-cursor-storage.js.map +1 -1
- package/dist/src/storage/kysely/sync-dead-letter-storage.d.ts +17 -0
- package/dist/src/storage/kysely/sync-dead-letter-storage.d.ts.map +1 -0
- package/dist/src/storage/kysely/sync-dead-letter-storage.js +110 -0
- package/dist/src/storage/kysely/sync-dead-letter-storage.js.map +1 -0
- package/dist/src/storage/kysely/sync-remote-storage.js +1 -1
- package/dist/src/storage/kysely/sync-remote-storage.js.map +1 -1
- package/dist/src/storage/kysely/types.d.ts +22 -0
- package/dist/src/storage/kysely/types.d.ts.map +1 -1
- package/dist/src/storage/migrations/011_add_cursor_type_column.d.ts +3 -0
- package/dist/src/storage/migrations/011_add_cursor_type_column.d.ts.map +1 -0
- package/dist/src/storage/migrations/011_add_cursor_type_column.js +29 -0
- package/dist/src/storage/migrations/011_add_cursor_type_column.js.map +1 -0
- package/dist/src/storage/migrations/012_add_source_remote_column.d.ts +3 -0
- package/dist/src/storage/migrations/012_add_source_remote_column.d.ts.map +1 -0
- package/dist/src/storage/migrations/012_add_source_remote_column.js +7 -0
- package/dist/src/storage/migrations/012_add_source_remote_column.js.map +1 -0
- package/dist/src/storage/migrations/013_create_sync_dead_letters_table.d.ts +3 -0
- package/dist/src/storage/migrations/013_create_sync_dead_letters_table.d.ts.map +1 -0
- package/dist/src/storage/migrations/013_create_sync_dead_letters_table.js +24 -0
- package/dist/src/storage/migrations/013_create_sync_dead_letters_table.js.map +1 -0
- package/dist/src/storage/migrations/migrator.d.ts.map +1 -1
- package/dist/src/storage/migrations/migrator.js +6 -0
- package/dist/src/storage/migrations/migrator.js.map +1 -1
- package/dist/src/subs/default-error-handler.d.ts.map +1 -1
- package/dist/src/subs/default-error-handler.js.map +1 -1
- package/dist/src/subs/subscription-notification-read-model.d.ts +3 -2
- package/dist/src/subs/subscription-notification-read-model.d.ts.map +1 -1
- package/dist/src/subs/subscription-notification-read-model.js +1 -1
- package/dist/src/subs/subscription-notification-read-model.js.map +1 -1
- package/dist/src/sync/batch-aggregator.d.ts +25 -0
- package/dist/src/sync/batch-aggregator.d.ts.map +1 -0
- package/dist/src/sync/batch-aggregator.js +94 -0
- package/dist/src/sync/batch-aggregator.js.map +1 -0
- package/dist/src/sync/buffered-mailbox.d.ts +36 -0
- package/dist/src/sync/buffered-mailbox.d.ts.map +1 -0
- package/dist/src/sync/buffered-mailbox.js +164 -0
- package/dist/src/sync/buffered-mailbox.js.map +1 -0
- package/dist/src/sync/channels/{gql-channel.d.ts → gql-req-channel.d.ts} +49 -42
- package/dist/src/sync/channels/gql-req-channel.d.ts.map +1 -0
- package/dist/src/sync/channels/gql-req-channel.js +548 -0
- package/dist/src/sync/channels/gql-req-channel.js.map +1 -0
- package/dist/src/sync/channels/gql-request-channel-factory.d.ts +32 -0
- package/dist/src/sync/channels/gql-request-channel-factory.d.ts.map +1 -0
- package/dist/src/sync/channels/gql-request-channel-factory.js +105 -0
- package/dist/src/sync/channels/gql-request-channel-factory.js.map +1 -0
- package/dist/src/sync/channels/gql-res-channel.d.ts +25 -0
- package/dist/src/sync/channels/gql-res-channel.d.ts.map +1 -0
- package/dist/src/sync/channels/gql-res-channel.js +79 -0
- package/dist/src/sync/channels/gql-res-channel.js.map +1 -0
- package/dist/src/sync/channels/gql-response-channel-factory.d.ts +13 -0
- package/dist/src/sync/channels/gql-response-channel-factory.d.ts.map +1 -0
- package/dist/src/sync/channels/gql-response-channel-factory.js +14 -0
- package/dist/src/sync/channels/gql-response-channel-factory.js.map +1 -0
- package/dist/src/sync/channels/index.d.ts +6 -4
- package/dist/src/sync/channels/index.d.ts.map +1 -1
- package/dist/src/sync/channels/index.js +6 -4
- package/dist/src/sync/channels/index.js.map +1 -1
- package/dist/src/sync/channels/interval-poll-timer.d.ts +40 -0
- package/dist/src/sync/channels/interval-poll-timer.d.ts.map +1 -0
- package/dist/src/sync/channels/interval-poll-timer.js +123 -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/channels/utils.d.ts +15 -1
- package/dist/src/sync/channels/utils.d.ts.map +1 -1
- package/dist/src/sync/channels/utils.js +67 -2
- package/dist/src/sync/channels/utils.js.map +1 -1
- package/dist/src/sync/index.d.ts +10 -6
- package/dist/src/sync/index.d.ts.map +1 -1
- package/dist/src/sync/index.js +7 -5
- package/dist/src/sync/index.js.map +1 -1
- package/dist/src/sync/interfaces.d.ts +34 -21
- package/dist/src/sync/interfaces.d.ts.map +1 -1
- package/dist/src/sync/mailbox.d.ts +51 -12
- package/dist/src/sync/mailbox.d.ts.map +1 -1
- package/dist/src/sync/mailbox.js +89 -6
- package/dist/src/sync/mailbox.js.map +1 -1
- package/dist/src/sync/sync-awaiter.d.ts +34 -0
- package/dist/src/sync/sync-awaiter.d.ts.map +1 -0
- package/dist/src/sync/sync-awaiter.js +124 -0
- package/dist/src/sync/sync-awaiter.js.map +1 -0
- package/dist/src/sync/sync-builder.d.ts +5 -1
- package/dist/src/sync/sync-builder.d.ts.map +1 -1
- package/dist/src/sync/sync-builder.js +14 -1
- package/dist/src/sync/sync-builder.js.map +1 -1
- package/dist/src/sync/sync-manager.d.ts +21 -8
- package/dist/src/sync/sync-manager.d.ts.map +1 -1
- package/dist/src/sync/sync-manager.js +274 -93
- package/dist/src/sync/sync-manager.js.map +1 -1
- package/dist/src/sync/sync-operation.d.ts +4 -2
- package/dist/src/sync/sync-operation.d.ts.map +1 -1
- package/dist/src/sync/sync-operation.js +8 -1
- package/dist/src/sync/sync-operation.js.map +1 -1
- package/dist/src/sync/sync-status-tracker.d.ts +31 -0
- package/dist/src/sync/sync-status-tracker.d.ts.map +1 -0
- package/dist/src/sync/sync-status-tracker.js +137 -0
- package/dist/src/sync/sync-status-tracker.js.map +1 -0
- package/dist/src/sync/types.d.ts +79 -2
- package/dist/src/sync/types.d.ts.map +1 -1
- package/dist/src/sync/types.js +15 -0
- package/dist/src/sync/types.js.map +1 -1
- package/dist/src/sync/utils.d.ts +37 -2
- package/dist/src/sync/utils.d.ts.map +1 -1
- package/dist/src/sync/utils.js +205 -0
- package/dist/src/sync/utils.js.map +1 -1
- package/dist/src/utils/reshuffle.d.ts +22 -5
- package/dist/src/utils/reshuffle.d.ts.map +1 -1
- package/dist/src/utils/reshuffle.js +50 -6
- package/dist/src/utils/reshuffle.js.map +1 -1
- package/package.json +12 -15
- package/dist/src/processors/types.d.ts +0 -63
- package/dist/src/processors/types.d.ts.map +0 -1
- package/dist/src/processors/types.js +0 -2
- package/dist/src/processors/types.js.map +0 -1
- 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/sync/channels/composite-channel-factory.d.ts +0 -30
- package/dist/src/sync/channels/composite-channel-factory.d.ts.map +0 -1
- package/dist/src/sync/channels/composite-channel-factory.js +0 -87
- package/dist/src/sync/channels/composite-channel-factory.js.map +0 -1
- package/dist/src/sync/channels/gql-channel-factory.d.ts +0 -25
- package/dist/src/sync/channels/gql-channel-factory.d.ts.map +0 -1
- package/dist/src/sync/channels/gql-channel-factory.js +0 -76
- package/dist/src/sync/channels/gql-channel-factory.js.map +0 -1
- package/dist/src/sync/channels/gql-channel.d.ts.map +0 -1
- package/dist/src/sync/channels/gql-channel.js +0 -423
- package/dist/src/sync/channels/gql-channel.js.map +0 -1
- package/dist/src/sync/channels/polling-channel.d.ts +0 -39
- package/dist/src/sync/channels/polling-channel.d.ts.map +0 -1
- package/dist/src/sync/channels/polling-channel.js +0 -72
- package/dist/src/sync/channels/polling-channel.js.map +0 -1
package/dist/src/sync/utils.js
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
import { driveCollectionId, } from "../cache/operation-index-types.js";
|
|
2
|
+
import { SyncOperation } from "./sync-operation.js";
|
|
3
|
+
import { SyncOperationStatus, } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Trims a mailbox using the jobIds from a batch.
|
|
6
|
+
*/
|
|
7
|
+
export function trimMailboxFromBatch(mailbox, batch) {
|
|
8
|
+
const toRemove = [];
|
|
9
|
+
// we want to guarantee:
|
|
10
|
+
//
|
|
11
|
+
// 1. sync ops are still in the inbox when marked as executed
|
|
12
|
+
// 2. we remove syncops as a batch after they have been executed
|
|
13
|
+
for (const syncOp of batch.entries) {
|
|
14
|
+
for (const item of mailbox.items) {
|
|
15
|
+
if (syncOp.event.jobId === item.jobId) {
|
|
16
|
+
toRemove.push(item);
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (toRemove.length > 0) {
|
|
22
|
+
for (const syncOp of toRemove) {
|
|
23
|
+
syncOp.executed();
|
|
24
|
+
}
|
|
25
|
+
mailbox.remove(...toRemove);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Trims a mailbox using the ack ordinal.
|
|
30
|
+
*/
|
|
31
|
+
export function trimMailboxFromAckOrdinal(mailbox, ackOrdinal) {
|
|
32
|
+
const toRemove = [];
|
|
33
|
+
// we want to guarantee:
|
|
34
|
+
//
|
|
35
|
+
// 1. sync ops are still in the mailbox when marked as applied
|
|
36
|
+
// 2. we remove syncops as a single batch
|
|
37
|
+
for (const syncOp of mailbox.items) {
|
|
38
|
+
let maxOrdinal = 0;
|
|
39
|
+
for (const op of syncOp.operations) {
|
|
40
|
+
maxOrdinal = Math.max(maxOrdinal, op.context.ordinal);
|
|
41
|
+
}
|
|
42
|
+
if (maxOrdinal <= ackOrdinal) {
|
|
43
|
+
toRemove.push(syncOp);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (toRemove.length > 0) {
|
|
47
|
+
for (const syncOp of toRemove) {
|
|
48
|
+
syncOp.executed();
|
|
49
|
+
}
|
|
50
|
+
mailbox.remove(...toRemove);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
1
53
|
/**
|
|
2
54
|
* Filters operations based on a remote's filter criteria.
|
|
3
55
|
*
|
|
@@ -43,6 +95,23 @@ export function createIdleHealth() {
|
|
|
43
95
|
* This ensures operations are grouped for efficient processing while maintaining
|
|
44
96
|
* causality across documents and scopes.
|
|
45
97
|
*/
|
|
98
|
+
/**
|
|
99
|
+
* Sorts envelopes by the timestamp of their first operation.
|
|
100
|
+
* Envelopes without operations are placed at the end.
|
|
101
|
+
*/
|
|
102
|
+
export function sortEnvelopesByFirstOperationTimestamp(envelopes) {
|
|
103
|
+
return envelopes.slice().sort((a, b) => {
|
|
104
|
+
const aTimestamp = a.operations?.[0]?.operation.timestampUtcMs;
|
|
105
|
+
const bTimestamp = b.operations?.[0]?.operation.timestampUtcMs;
|
|
106
|
+
if (!aTimestamp && !bTimestamp)
|
|
107
|
+
return 0;
|
|
108
|
+
if (!aTimestamp)
|
|
109
|
+
return 1;
|
|
110
|
+
if (!bTimestamp)
|
|
111
|
+
return -1;
|
|
112
|
+
return new Date(aTimestamp).getTime() - new Date(bTimestamp).getTime();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
46
115
|
export function batchOperationsByDocument(operations) {
|
|
47
116
|
const batches = [];
|
|
48
117
|
let currentDocId = null;
|
|
@@ -75,4 +144,140 @@ export function batchOperationsByDocument(operations) {
|
|
|
75
144
|
flushBatch();
|
|
76
145
|
return batches;
|
|
77
146
|
}
|
|
147
|
+
export function getMaxOrdinal(operations) {
|
|
148
|
+
return operations.reduce((maxOrdinal, operation) => Math.max(maxOrdinal, operation.context.ordinal), 0);
|
|
149
|
+
}
|
|
150
|
+
export function filterByCollectionMembership(operations, collectionId, collectionMemberships) {
|
|
151
|
+
if (!collectionMemberships) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
return operations.filter((op) => {
|
|
155
|
+
const documentId = op.context.documentId;
|
|
156
|
+
if (!(documentId in collectionMemberships)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return collectionMemberships[documentId].includes(collectionId);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
export function toOperationWithContext(entry) {
|
|
163
|
+
return {
|
|
164
|
+
operation: {
|
|
165
|
+
id: entry.id,
|
|
166
|
+
index: entry.index,
|
|
167
|
+
skip: entry.skip,
|
|
168
|
+
hash: entry.hash,
|
|
169
|
+
timestampUtcMs: entry.timestampUtcMs,
|
|
170
|
+
action: entry.action,
|
|
171
|
+
},
|
|
172
|
+
context: {
|
|
173
|
+
documentId: entry.documentId,
|
|
174
|
+
documentType: entry.documentType,
|
|
175
|
+
scope: entry.scope,
|
|
176
|
+
branch: entry.branch,
|
|
177
|
+
ordinal: entry.ordinal ?? 0,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Merges SyncOperations that share the same (documentId, scope, branch) into
|
|
183
|
+
* a single SyncOperation per group. Within each group, operations are sorted
|
|
184
|
+
* by context.ordinal. The merged SyncOperation keeps the first group member's
|
|
185
|
+
* jobId; all other jobIds are remapped so external dependencies still resolve.
|
|
186
|
+
*/
|
|
187
|
+
export function consolidateSyncOperations(syncOps) {
|
|
188
|
+
if (syncOps.length <= 1) {
|
|
189
|
+
return syncOps;
|
|
190
|
+
}
|
|
191
|
+
const groups = new Map();
|
|
192
|
+
const jobIdRemap = new Map();
|
|
193
|
+
const insertionOrder = [];
|
|
194
|
+
for (const syncOp of syncOps) {
|
|
195
|
+
const key = `${syncOp.documentId}|${syncOp.scopes.slice().sort().join(",")}|${syncOp.branch}`;
|
|
196
|
+
const existing = groups.get(key);
|
|
197
|
+
if (existing) {
|
|
198
|
+
existing.ops.push(syncOp);
|
|
199
|
+
if (syncOp.jobId && syncOp.jobId !== existing.canonicalJobId) {
|
|
200
|
+
jobIdRemap.set(syncOp.jobId, existing.canonicalJobId);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
groups.set(key, { ops: [syncOp], canonicalJobId: syncOp.jobId });
|
|
205
|
+
insertionOrder.push(key);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const result = [];
|
|
209
|
+
for (const key of insertionOrder) {
|
|
210
|
+
const group = groups.get(key);
|
|
211
|
+
const allOperations = group.ops
|
|
212
|
+
.flatMap((op) => op.operations)
|
|
213
|
+
.sort((a, b) => a.context.ordinal - b.context.ordinal);
|
|
214
|
+
const allDeps = new Set();
|
|
215
|
+
for (const op of group.ops) {
|
|
216
|
+
for (const dep of op.jobDependencies) {
|
|
217
|
+
allDeps.add(dep);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
allDeps.delete(group.canonicalJobId);
|
|
221
|
+
for (const op of group.ops) {
|
|
222
|
+
allDeps.delete(op.jobId);
|
|
223
|
+
}
|
|
224
|
+
const remappedDeps = [];
|
|
225
|
+
for (const dep of allDeps) {
|
|
226
|
+
const mapped = jobIdRemap.get(dep) ?? dep;
|
|
227
|
+
if (!remappedDeps.includes(mapped) && mapped !== group.canonicalJobId) {
|
|
228
|
+
remappedDeps.push(mapped);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const first = group.ops[0];
|
|
232
|
+
const merged = new SyncOperation(first.id, first.jobId, remappedDeps, first.remoteName, first.documentId, first.scopes, first.branch, allOperations);
|
|
233
|
+
if (first.status > SyncOperationStatus.TransportPending) {
|
|
234
|
+
if (first.status >= SyncOperationStatus.Error) {
|
|
235
|
+
merged.executed();
|
|
236
|
+
}
|
|
237
|
+
else if (first.status >= SyncOperationStatus.Applied) {
|
|
238
|
+
merged.transported();
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
merged.started();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
result.push(merged);
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
export function mergeCollectionMemberships(events) {
|
|
249
|
+
const mergedMemberships = {};
|
|
250
|
+
for (const event of events) {
|
|
251
|
+
if (event.collectionMemberships) {
|
|
252
|
+
for (const [docId, collections] of Object.entries(event.collectionMemberships)) {
|
|
253
|
+
if (!(docId in mergedMemberships)) {
|
|
254
|
+
mergedMemberships[docId] = [];
|
|
255
|
+
}
|
|
256
|
+
for (const c of collections) {
|
|
257
|
+
if (!mergedMemberships[docId].includes(c)) {
|
|
258
|
+
mergedMemberships[docId].push(c);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const op of event.operations) {
|
|
264
|
+
const action = op.operation.action;
|
|
265
|
+
if (action.type !== "ADD_RELATIONSHIP") {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const input = action.input;
|
|
269
|
+
if (!input?.sourceId || !input.targetId) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const collectionId = driveCollectionId(op.context.branch, input.sourceId);
|
|
273
|
+
if (!(input.targetId in mergedMemberships)) {
|
|
274
|
+
mergedMemberships[input.targetId] = [];
|
|
275
|
+
}
|
|
276
|
+
if (!mergedMemberships[input.targetId].includes(collectionId)) {
|
|
277
|
+
mergedMemberships[input.targetId].push(collectionId);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return mergedMemberships;
|
|
282
|
+
}
|
|
78
283
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/sync/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/sync/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
type OperationIndex = {
|
|
2
2
|
index: number;
|
|
3
3
|
skip: number;
|
|
4
|
-
id
|
|
5
|
-
timestampUtcMs
|
|
4
|
+
id: string;
|
|
5
|
+
timestampUtcMs: string;
|
|
6
|
+
action?: {
|
|
7
|
+
id?: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
};
|
|
6
10
|
};
|
|
7
11
|
/**
|
|
8
12
|
* Sorts operations by index and skip number.
|
|
@@ -10,9 +14,16 @@ type OperationIndex = {
|
|
|
10
14
|
*/
|
|
11
15
|
export declare function sortOperations<TOpIndex extends OperationIndex>(operations: TOpIndex[]): TOpIndex[];
|
|
12
16
|
/**
|
|
13
|
-
* Reshuffles operations by timestamp
|
|
17
|
+
* Reshuffles operations by timestamp, then applies deterministic tie-breaking.
|
|
14
18
|
* Used for merging concurrent operations from different branches.
|
|
15
19
|
*
|
|
20
|
+
* For strict document-structure actions (e.g., CREATE_DOCUMENT/UPGRADE_DOCUMENT),
|
|
21
|
+
* logical index (index - skip) is prioritized to preserve causal replay order.
|
|
22
|
+
*
|
|
23
|
+
* For other actions, action ID is prioritized to ensure a canonical cross-reactor order
|
|
24
|
+
* for concurrent operations that may have diverged local indices due to prior reshuffles.
|
|
25
|
+
* Logical index and operation ID are then used as deterministic tie-breakers.
|
|
26
|
+
*
|
|
16
27
|
* Example:
|
|
17
28
|
* [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, 2:0, B3:0, B4:2, B5:0]
|
|
18
29
|
* GC => [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, B4:2, B5:0]
|
|
@@ -20,11 +31,17 @@ export declare function sortOperations<TOpIndex extends OperationIndex>(operatio
|
|
|
20
31
|
* Reshuffle(6:4) => [6:4, 7:0, 8:0, 9:0, 10:0, 11:0]
|
|
21
32
|
* merge => [0:0, 1:0, 6:4, 7:0, 8:0, 9:0, 10:0, 11:0]
|
|
22
33
|
*/
|
|
23
|
-
export declare function reshuffleByTimestamp<TOp extends OperationIndex>(startIndex:
|
|
34
|
+
export declare function reshuffleByTimestamp<TOp extends OperationIndex>(startIndex: {
|
|
35
|
+
index: number;
|
|
36
|
+
skip: number;
|
|
37
|
+
}, opsA: TOp[], opsB: TOp[]): TOp[];
|
|
24
38
|
/**
|
|
25
39
|
* Reshuffles operations by timestamp first, then by original index value.
|
|
26
40
|
* Used for merging concurrent operations while preserving index ordering for operations with same timestamp.
|
|
27
41
|
*/
|
|
28
|
-
export declare function reshuffleByTimestampAndIndex<TOp extends OperationIndex>(startIndex:
|
|
42
|
+
export declare function reshuffleByTimestampAndIndex<TOp extends OperationIndex>(startIndex: {
|
|
43
|
+
index: number;
|
|
44
|
+
skip: number;
|
|
45
|
+
}, opsA: TOp[], opsB: TOp[]): TOp[];
|
|
29
46
|
export {};
|
|
30
47
|
//# sourceMappingURL=reshuffle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reshuffle.d.ts","sourceRoot":"","sources":["../../../src/utils/reshuffle.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"reshuffle.d.ts","sourceRoot":"","sources":["../../../src/utils/reshuffle.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE;QACP,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH,CAAC;AAUF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,cAAc,EAC5D,UAAU,EAAE,QAAQ,EAAE,GACrB,QAAQ,EAAE,CAKZ;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,cAAc,EAC7D,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC3C,IAAI,EAAE,GAAG,EAAE,EACX,IAAI,EAAE,GAAG,EAAE,GACV,GAAG,EAAE,CAuCP;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,SAAS,cAAc,EACrE,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC3C,IAAI,EAAE,GAAG,EAAE,EACX,IAAI,EAAE,GAAG,EAAE,GACV,GAAG,EAAE,CAoBP"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
const STRICT_ORDER_ACTION_TYPES = new Set([
|
|
2
|
+
"CREATE_DOCUMENT",
|
|
3
|
+
"DELETE_DOCUMENT",
|
|
4
|
+
"UPGRADE_DOCUMENT",
|
|
5
|
+
"ADD_RELATIONSHIP",
|
|
6
|
+
"REMOVE_RELATIONSHIP",
|
|
7
|
+
]);
|
|
1
8
|
/**
|
|
2
9
|
* Sorts operations by index and skip number.
|
|
3
10
|
* [0:0 2:0 1:0 3:3 3:1] => [0:0 1:0 2:0 3:1 3:3]
|
|
@@ -9,9 +16,16 @@ export function sortOperations(operations) {
|
|
|
9
16
|
.sort((a, b) => a.index - b.index);
|
|
10
17
|
}
|
|
11
18
|
/**
|
|
12
|
-
* Reshuffles operations by timestamp
|
|
19
|
+
* Reshuffles operations by timestamp, then applies deterministic tie-breaking.
|
|
13
20
|
* Used for merging concurrent operations from different branches.
|
|
14
21
|
*
|
|
22
|
+
* For strict document-structure actions (e.g., CREATE_DOCUMENT/UPGRADE_DOCUMENT),
|
|
23
|
+
* logical index (index - skip) is prioritized to preserve causal replay order.
|
|
24
|
+
*
|
|
25
|
+
* For other actions, action ID is prioritized to ensure a canonical cross-reactor order
|
|
26
|
+
* for concurrent operations that may have diverged local indices due to prior reshuffles.
|
|
27
|
+
* Logical index and operation ID are then used as deterministic tie-breakers.
|
|
28
|
+
*
|
|
15
29
|
* Example:
|
|
16
30
|
* [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, 2:0, B3:0, B4:2, B5:0]
|
|
17
31
|
* GC => [0:0, 1:0, 2:0, A3:0, A4:0, A5:0] + [0:0, 1:0, B4:2, B5:0]
|
|
@@ -21,8 +35,29 @@ export function sortOperations(operations) {
|
|
|
21
35
|
*/
|
|
22
36
|
export function reshuffleByTimestamp(startIndex, opsA, opsB) {
|
|
23
37
|
return [...opsA, ...opsB]
|
|
24
|
-
.sort((a, b) =>
|
|
25
|
-
new Date(
|
|
38
|
+
.sort((a, b) => {
|
|
39
|
+
const timestampDiff = new Date(a.timestampUtcMs).getTime() -
|
|
40
|
+
new Date(b.timestampUtcMs).getTime();
|
|
41
|
+
if (timestampDiff !== 0) {
|
|
42
|
+
return timestampDiff;
|
|
43
|
+
}
|
|
44
|
+
const shouldPrioritizeLogicalIndex = STRICT_ORDER_ACTION_TYPES.has(a.action?.type ?? "") ||
|
|
45
|
+
STRICT_ORDER_ACTION_TYPES.has(b.action?.type ?? "");
|
|
46
|
+
const logicalIndexDiff = a.index - a.skip - (b.index - b.skip);
|
|
47
|
+
if (shouldPrioritizeLogicalIndex) {
|
|
48
|
+
if (logicalIndexDiff !== 0) {
|
|
49
|
+
return logicalIndexDiff;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const actionIdDiff = (a.action?.id ?? "").localeCompare(b.action?.id ?? "");
|
|
53
|
+
if (actionIdDiff !== 0) {
|
|
54
|
+
return actionIdDiff;
|
|
55
|
+
}
|
|
56
|
+
if (!shouldPrioritizeLogicalIndex && logicalIndexDiff !== 0) {
|
|
57
|
+
return logicalIndexDiff;
|
|
58
|
+
}
|
|
59
|
+
return a.id.localeCompare(b.id);
|
|
60
|
+
})
|
|
26
61
|
.map((op, i) => ({
|
|
27
62
|
...op,
|
|
28
63
|
index: startIndex.index + i,
|
|
@@ -35,9 +70,18 @@ export function reshuffleByTimestamp(startIndex, opsA, opsB) {
|
|
|
35
70
|
*/
|
|
36
71
|
export function reshuffleByTimestampAndIndex(startIndex, opsA, opsB) {
|
|
37
72
|
return [...opsA, ...opsB]
|
|
38
|
-
.sort((a, b) =>
|
|
39
|
-
|
|
40
|
-
|
|
73
|
+
.sort((a, b) => {
|
|
74
|
+
const indexDiff = a.index - b.index;
|
|
75
|
+
if (indexDiff !== 0) {
|
|
76
|
+
return indexDiff;
|
|
77
|
+
}
|
|
78
|
+
const timestampDiff = new Date(a.timestampUtcMs).getTime() -
|
|
79
|
+
new Date(b.timestampUtcMs).getTime();
|
|
80
|
+
if (timestampDiff !== 0) {
|
|
81
|
+
return timestampDiff;
|
|
82
|
+
}
|
|
83
|
+
return a.id.localeCompare(b.id);
|
|
84
|
+
})
|
|
41
85
|
.map((op, i) => ({
|
|
42
86
|
...op,
|
|
43
87
|
index: startIndex.index + i,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reshuffle.js","sourceRoot":"","sources":["../../../src/utils/reshuffle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reshuffle.js","sourceRoot":"","sources":["../../../src/utils/reshuffle.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/reactor",
|
|
3
|
-
"version": "6.0.0-dev.
|
|
3
|
+
"version": "6.0.0-dev.61",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/powerhouse-inc/powerhouse",
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./dist/src/index.js"
|
|
13
13
|
},
|
|
14
|
-
"imports": {
|
|
15
|
-
"#*": "./dist/src/*"
|
|
16
|
-
},
|
|
17
14
|
"files": [
|
|
18
15
|
"./dist/src"
|
|
19
16
|
],
|
|
@@ -24,24 +21,24 @@
|
|
|
24
21
|
"author": "",
|
|
25
22
|
"license": "AGPL-3.0-only",
|
|
26
23
|
"dependencies": {
|
|
27
|
-
"@electric-sql/pglite": "0.
|
|
28
|
-
"kysely": "
|
|
29
|
-
"kysely-pglite-dialect": "
|
|
24
|
+
"@electric-sql/pglite": "0.3.15",
|
|
25
|
+
"kysely": "0.28.11",
|
|
26
|
+
"kysely-pglite-dialect": "1.2.0",
|
|
30
27
|
"uuid": "^11.0.5",
|
|
31
|
-
"
|
|
32
|
-
"document-
|
|
28
|
+
"@powerhousedao/shared": "6.0.0-dev.61",
|
|
29
|
+
"document-model": "6.0.0-dev.61",
|
|
30
|
+
"document-drive": "6.0.0-dev.61"
|
|
33
31
|
},
|
|
34
32
|
"devDependencies": {
|
|
35
33
|
"@vitest/coverage-v8": "^3.2.4",
|
|
34
|
+
"prettier": "3.8.1",
|
|
36
35
|
"tinybench": "^2.9.0",
|
|
37
|
-
"tsx": "
|
|
38
|
-
"
|
|
39
|
-
"vitest": "^3.2.4"
|
|
36
|
+
"tsx": "4.21.0",
|
|
37
|
+
"vitest": "3.2.4"
|
|
40
38
|
},
|
|
41
39
|
"scripts": {
|
|
42
|
-
"build": "pnpm run build:tsc",
|
|
43
|
-
"build:tsc": "tsc --build",
|
|
44
40
|
"prebuild": "pnpm run clean",
|
|
41
|
+
"build": "tsc",
|
|
45
42
|
"test": "vitest run --coverage --printConsoleTrace=true --silent=false",
|
|
46
43
|
"test:watch": "vitest --coverage",
|
|
47
44
|
"lint": "eslint",
|
|
@@ -49,7 +46,7 @@
|
|
|
49
46
|
"bench:sync": "node --import tsx bench/two-reactor-sync.bench.ts",
|
|
50
47
|
"clean": "rimraf dist",
|
|
51
48
|
"clean:node_modules": "rimraf node_modules",
|
|
52
|
-
"claude": "pnpm build && pnpm test &&
|
|
49
|
+
"claude": "pnpm build && pnpm test && pnpm exec prettier --write \"**/*.ts\" && pnpm lint",
|
|
53
50
|
"migrate": "tsx src/storage/migrations/run-migrations.ts",
|
|
54
51
|
"migrate:status": "tsx src/storage/migrations/run-migrations.ts status"
|
|
55
52
|
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { PHDocumentHeader } from "document-model";
|
|
2
|
-
import type { OperationWithContext } from "../storage/interfaces.js";
|
|
3
|
-
/**
|
|
4
|
-
* Filter for matching operations to processors.
|
|
5
|
-
* All fields are optional arrays - when provided, operations must match at least one value in each specified field.
|
|
6
|
-
* When a field is undefined or empty, it matches all values for that field.
|
|
7
|
-
*/
|
|
8
|
-
export type ProcessorFilter = {
|
|
9
|
-
documentType?: string[];
|
|
10
|
-
scope?: string[];
|
|
11
|
-
branch?: string[];
|
|
12
|
-
documentId?: string[];
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* Describes an object that can process operations.
|
|
16
|
-
*/
|
|
17
|
-
export interface IProcessor {
|
|
18
|
-
/**
|
|
19
|
-
* Processes a list of operations with context.
|
|
20
|
-
* Called when operations match this processor's filter.
|
|
21
|
-
*/
|
|
22
|
-
onOperations(operations: OperationWithContext[]): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Called when the processor is disconnected.
|
|
25
|
-
* Used to clean up any resources allocated during processor creation.
|
|
26
|
-
*/
|
|
27
|
-
onDisconnect(): Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Relates a processor to its filter configuration.
|
|
31
|
-
*/
|
|
32
|
-
export type ProcessorRecord = {
|
|
33
|
-
processor: IProcessor;
|
|
34
|
-
filter: ProcessorFilter;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* A factory function that creates processor records for a given drive.
|
|
38
|
-
* Called once per drive when the drive is first detected or when the factory is registered.
|
|
39
|
-
*/
|
|
40
|
-
export type ProcessorFactory = (driveHeader: PHDocumentHeader) => ProcessorRecord[] | Promise<ProcessorRecord[]>;
|
|
41
|
-
/**
|
|
42
|
-
* Manages processor creation and destruction based on drive operations.
|
|
43
|
-
*/
|
|
44
|
-
export interface IProcessorManager {
|
|
45
|
-
/**
|
|
46
|
-
* Registers a processor factory.
|
|
47
|
-
* Immediately creates processors for all existing drives.
|
|
48
|
-
*/
|
|
49
|
-
registerFactory(identifier: string, factory: ProcessorFactory): Promise<void>;
|
|
50
|
-
/**
|
|
51
|
-
* Unregisters a processor factory and disconnects all processors it created.
|
|
52
|
-
*/
|
|
53
|
-
unregisterFactory(identifier: string): Promise<void>;
|
|
54
|
-
/**
|
|
55
|
-
* Gets all registered factory identifiers.
|
|
56
|
-
*/
|
|
57
|
-
getFactoryIdentifiers(): string[];
|
|
58
|
-
/**
|
|
59
|
-
* Gets all processor records for a specific drive.
|
|
60
|
-
*/
|
|
61
|
-
getProcessorsForDrive(driveId: string): ProcessorRecord[];
|
|
62
|
-
}
|
|
63
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/processors/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,YAAY,CAAC,UAAU,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE;;;OAGG;IACH,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,UAAU,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,WAAW,EAAE,gBAAgB,KAC1B,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9E;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErD;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE,CAAC;IAElC;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,EAAE,CAAC;CAC3D"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/processors/types.ts"],"names":[],"mappings":""}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { IDocumentStorage } from "document-drive";
|
|
2
|
-
import type { PHDocument } from "document-model";
|
|
3
|
-
import type { IEventBus } from "../events/interfaces.js";
|
|
4
|
-
import type { IConsistencyTracker } from "../shared/consistency-tracker.js";
|
|
5
|
-
import type { ConsistencyToken } from "../shared/types.js";
|
|
6
|
-
import type { IConsistencyAwareStorage } from "./interfaces.js";
|
|
7
|
-
/**
|
|
8
|
-
* A wrapper around IDocumentStorage that provides read-after-write consistency
|
|
9
|
-
* by waiting for the consistency tracker to be updated before delegating reads
|
|
10
|
-
* to the inner storage.
|
|
11
|
-
*
|
|
12
|
-
* This is used when legacy storage mode is enabled with async persistence
|
|
13
|
-
* (e.g., BrowserStorage with IndexedDB) to ensure documents are available
|
|
14
|
-
* for reading after being written.
|
|
15
|
-
*/
|
|
16
|
-
export declare class ConsistencyAwareLegacyStorage implements IConsistencyAwareStorage {
|
|
17
|
-
private inner;
|
|
18
|
-
private consistencyTracker;
|
|
19
|
-
constructor(inner: IDocumentStorage, consistencyTracker: IConsistencyTracker, eventBus: IEventBus);
|
|
20
|
-
private waitForConsistency;
|
|
21
|
-
get<TDocument extends PHDocument>(id: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
22
|
-
getBySlug<TDocument extends PHDocument>(slug: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<TDocument>;
|
|
23
|
-
exists(id: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<boolean>;
|
|
24
|
-
findByType(type: string, limit?: number, cursor?: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<{
|
|
25
|
-
documents: string[];
|
|
26
|
-
nextCursor: string | undefined;
|
|
27
|
-
}>;
|
|
28
|
-
getChildren(id: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
29
|
-
resolveIds(slugs: string[], consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
30
|
-
resolveSlugs(ids: string[], consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
31
|
-
getParents(childId: string, consistencyToken?: ConsistencyToken, signal?: AbortSignal): Promise<string[]>;
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=consistency-aware-legacy-storage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"consistency-aware-legacy-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/consistency-aware-legacy-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;;;;;;;GAQG;AACH,qBAAa,6BAA8B,YAAW,wBAAwB;IAE1E,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,kBAAkB;gBADlB,KAAK,EAAE,gBAAgB,EACvB,kBAAkB,EAAE,mBAAmB,EAC/C,QAAQ,EAAE,SAAS;YAgBP,kBAAkB;IAa1B,GAAG,CAAC,SAAS,SAAS,UAAU,EACpC,EAAE,EAAE,MAAM,EACV,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,SAAS,CAAC;IAKf,SAAS,CAAC,SAAS,SAAS,UAAU,EAC1C,IAAI,EAAE,MAAM,EACZ,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,SAAS,CAAC;IAKf,MAAM,CACV,EAAE,EAAE,MAAM,EACV,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC;IAKb,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAK7D,WAAW,CACf,EAAE,EAAE,MAAM,EACV,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAKd,UAAU,CACd,KAAK,EAAE,MAAM,EAAE,EACf,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAKd,YAAY,CAChB,GAAG,EAAE,MAAM,EAAE,EACb,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;IAKd,UAAU,CACd,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC;CAIrB"}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { OperationEventTypes } from "../events/types.js";
|
|
2
|
-
/**
|
|
3
|
-
* A wrapper around IDocumentStorage that provides read-after-write consistency
|
|
4
|
-
* by waiting for the consistency tracker to be updated before delegating reads
|
|
5
|
-
* to the inner storage.
|
|
6
|
-
*
|
|
7
|
-
* This is used when legacy storage mode is enabled with async persistence
|
|
8
|
-
* (e.g., BrowserStorage with IndexedDB) to ensure documents are available
|
|
9
|
-
* for reading after being written.
|
|
10
|
-
*/
|
|
11
|
-
export class ConsistencyAwareLegacyStorage {
|
|
12
|
-
inner;
|
|
13
|
-
consistencyTracker;
|
|
14
|
-
constructor(inner, consistencyTracker, eventBus) {
|
|
15
|
-
this.inner = inner;
|
|
16
|
-
this.consistencyTracker = consistencyTracker;
|
|
17
|
-
eventBus.subscribe(OperationEventTypes.OPERATION_WRITTEN, (_type, event) => {
|
|
18
|
-
const coordinates = event.operations.map((op) => ({
|
|
19
|
-
documentId: op.context.documentId,
|
|
20
|
-
scope: op.context.scope,
|
|
21
|
-
branch: op.context.branch,
|
|
22
|
-
operationIndex: op.operation.index,
|
|
23
|
-
}));
|
|
24
|
-
this.consistencyTracker.update(coordinates);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
async waitForConsistency(consistencyToken, signal) {
|
|
28
|
-
if (consistencyToken && consistencyToken.coordinates.length > 0) {
|
|
29
|
-
await this.consistencyTracker.waitFor(consistencyToken.coordinates, undefined, signal);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
async get(id, consistencyToken, signal) {
|
|
33
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
34
|
-
return this.inner.get(id);
|
|
35
|
-
}
|
|
36
|
-
async getBySlug(slug, consistencyToken, signal) {
|
|
37
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
38
|
-
return this.inner.getBySlug(slug);
|
|
39
|
-
}
|
|
40
|
-
async exists(id, consistencyToken, signal) {
|
|
41
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
42
|
-
return this.inner.exists(id);
|
|
43
|
-
}
|
|
44
|
-
async findByType(type, limit, cursor, consistencyToken, signal) {
|
|
45
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
46
|
-
return this.inner.findByType(type, limit, cursor);
|
|
47
|
-
}
|
|
48
|
-
async getChildren(id, consistencyToken, signal) {
|
|
49
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
50
|
-
return this.inner.getChildren(id);
|
|
51
|
-
}
|
|
52
|
-
async resolveIds(slugs, consistencyToken, signal) {
|
|
53
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
54
|
-
return this.inner.resolveIds(slugs, signal);
|
|
55
|
-
}
|
|
56
|
-
async resolveSlugs(ids, consistencyToken, signal) {
|
|
57
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
58
|
-
return this.inner.resolveSlugs(ids, signal);
|
|
59
|
-
}
|
|
60
|
-
async getParents(childId, consistencyToken, signal) {
|
|
61
|
-
await this.waitForConsistency(consistencyToken, signal);
|
|
62
|
-
return this.inner.getParents(childId);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=consistency-aware-legacy-storage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"consistency-aware-legacy-storage.js","sourceRoot":"","sources":["../../../src/storage/consistency-aware-legacy-storage.ts"],"names":[],"mappings":"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"}
|