@claudexor/daemon 3.24.0 → 4.0.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/dist/account-resets.d.ts +39 -0
- package/dist/account-resets.d.ts.map +1 -0
- package/dist/account-resets.js +174 -0
- package/dist/account-resets.js.map +1 -0
- package/dist/client.d.ts +25 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +55 -51
- package/dist/client.js.map +1 -1
- package/dist/command-authority.d.ts +11 -8
- package/dist/command-authority.d.ts.map +1 -1
- package/dist/command-authority.js +5 -6
- package/dist/command-authority.js.map +1 -1
- package/dist/command-list-projection.d.ts +0 -1
- package/dist/command-list-projection.d.ts.map +1 -1
- package/dist/command-list-projection.js +0 -6
- package/dist/command-list-projection.js.map +1 -1
- package/dist/command-list-select.d.ts +0 -4
- package/dist/command-list-select.d.ts.map +1 -1
- package/dist/command-list-select.js +1 -115
- package/dist/command-list-select.js.map +1 -1
- package/dist/command-retention.d.ts +7 -19
- package/dist/command-retention.d.ts.map +1 -1
- package/dist/command-retention.js +1 -117
- package/dist/command-retention.js.map +1 -1
- package/dist/command-rpc.d.ts +4 -1
- package/dist/command-rpc.d.ts.map +1 -1
- package/dist/command-rpc.js +12 -1
- package/dist/command-rpc.js.map +1 -1
- package/dist/command-store.d.ts +15 -52
- package/dist/command-store.d.ts.map +1 -1
- package/dist/command-store.js +5 -493
- package/dist/command-store.js.map +1 -1
- package/dist/daemon-health.d.ts +56 -8
- package/dist/daemon-health.d.ts.map +1 -1
- package/dist/daemon-health.js +44 -9
- package/dist/daemon-health.js.map +1 -1
- package/dist/daemon-local-client.d.ts +28 -0
- package/dist/daemon-local-client.d.ts.map +1 -0
- package/dist/daemon-local-client.js +55 -0
- package/dist/daemon-local-client.js.map +1 -0
- package/dist/delivery-command.d.ts +4 -4
- package/dist/delivery-command.d.ts.map +1 -1
- package/dist/delivery-command.js.map +1 -1
- package/dist/index.d.ts +24 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -8
- package/dist/index.js.map +1 -1
- package/dist/interactions.d.ts +12 -28
- package/dist/interactions.d.ts.map +1 -1
- package/dist/interactions.js +22 -123
- package/dist/interactions.js.map +1 -1
- package/dist/job-admission.d.ts +26 -0
- package/dist/job-admission.d.ts.map +1 -0
- package/dist/job-admission.js +67 -0
- package/dist/job-admission.js.map +1 -0
- package/dist/job-record.d.ts.map +1 -1
- package/dist/job-record.js +5 -1
- package/dist/job-record.js.map +1 -1
- package/dist/journal-fold-policy.d.ts +1 -1
- package/dist/journal-fold-policy.d.ts.map +1 -1
- package/dist/journal-fold-policy.js +26 -2
- package/dist/journal-fold-policy.js.map +1 -1
- package/dist/journal-recovery-files.d.ts +1 -41
- package/dist/journal-recovery-files.d.ts.map +1 -1
- package/dist/journal-recovery-files.js +2 -340
- package/dist/journal-recovery-files.js.map +1 -1
- package/dist/loop-facts.d.ts +28 -0
- package/dist/loop-facts.d.ts.map +1 -0
- package/dist/loop-facts.js +97 -0
- package/dist/loop-facts.js.map +1 -0
- package/dist/memory-facts.d.ts +2 -0
- package/dist/memory-facts.d.ts.map +1 -1
- package/dist/memory-facts.js +5 -0
- package/dist/memory-facts.js.map +1 -1
- package/dist/model-operations.d.ts +11 -4
- package/dist/model-operations.d.ts.map +1 -1
- package/dist/model-operations.js +68 -38
- package/dist/model-operations.js.map +1 -1
- package/dist/operator-decisions.d.ts +15 -25
- package/dist/operator-decisions.d.ts.map +1 -1
- package/dist/operator-decisions.js +5 -84
- package/dist/operator-decisions.js.map +1 -1
- package/dist/projects.d.ts +42 -41
- package/dist/projects.d.ts.map +1 -1
- package/dist/projects.js +46 -184
- package/dist/projects.js.map +1 -1
- package/dist/quota-poll-lanes.d.ts +5 -3
- package/dist/quota-poll-lanes.d.ts.map +1 -1
- package/dist/quota-poll-lanes.js +16 -6
- package/dist/quota-poll-lanes.js.map +1 -1
- package/dist/quota-refresh-batches.d.ts +26 -0
- package/dist/quota-refresh-batches.d.ts.map +1 -0
- package/dist/quota-refresh-batches.js +83 -0
- package/dist/quota-refresh-batches.js.map +1 -0
- package/dist/quota-registry-replay.d.ts +19 -0
- package/dist/quota-registry-replay.d.ts.map +1 -0
- package/dist/quota-registry-replay.js +106 -0
- package/dist/quota-registry-replay.js.map +1 -0
- package/dist/quota-registry-support.d.ts +4 -1
- package/dist/quota-registry-support.d.ts.map +1 -1
- package/dist/quota-registry-support.js +15 -2
- package/dist/quota-registry-support.js.map +1 -1
- package/dist/quota-registry.d.ts +381 -7
- package/dist/quota-registry.d.ts.map +1 -1
- package/dist/quota-registry.js +111 -149
- package/dist/quota-registry.js.map +1 -1
- package/dist/quota-resources.d.ts +105 -0
- package/dist/quota-resources.d.ts.map +1 -0
- package/dist/quota-resources.js +153 -0
- package/dist/quota-resources.js.map +1 -0
- package/dist/runless-turn-recovery.d.ts +2 -9
- package/dist/runless-turn-recovery.d.ts.map +1 -1
- package/dist/runless-turn-recovery.js +0 -14
- package/dist/runless-turn-recovery.js.map +1 -1
- package/dist/server.d.ts +23 -22
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +74 -84
- package/dist/server.js.map +1 -1
- package/dist/store/blob-files.d.ts +71 -0
- package/dist/store/blob-files.d.ts.map +1 -0
- package/dist/store/blob-files.js +160 -0
- package/dist/store/blob-files.js.map +1 -0
- package/dist/store/command-prune.d.ts +37 -0
- package/dist/store/command-prune.d.ts.map +1 -0
- package/dist/store/command-prune.js +123 -0
- package/dist/store/command-prune.js.map +1 -0
- package/dist/store/command-queries.d.ts +41 -0
- package/dist/store/command-queries.d.ts.map +1 -0
- package/dist/store/command-queries.js +186 -0
- package/dist/store/command-queries.js.map +1 -0
- package/dist/store/command-rows.d.ts +66 -0
- package/dist/store/command-rows.d.ts.map +1 -0
- package/dist/store/command-rows.js +141 -0
- package/dist/store/command-rows.js.map +1 -0
- package/dist/store/commands.d.ts +49 -0
- package/dist/store/commands.d.ts.map +1 -0
- package/dist/store/commands.js +247 -0
- package/dist/store/commands.js.map +1 -0
- package/dist/store/cursors.d.ts +33 -0
- package/dist/store/cursors.d.ts.map +1 -0
- package/dist/store/cursors.js +82 -0
- package/dist/store/cursors.js.map +1 -0
- package/dist/store/engine-recovery-files.d.ts +14 -0
- package/dist/store/engine-recovery-files.d.ts.map +1 -0
- package/dist/store/engine-recovery-files.js +53 -0
- package/dist/store/engine-recovery-files.js.map +1 -0
- package/dist/store/engine-state-recovery.d.ts +71 -0
- package/dist/store/engine-state-recovery.d.ts.map +1 -0
- package/dist/store/engine-state-recovery.js +318 -0
- package/dist/store/engine-state-recovery.js.map +1 -0
- package/dist/store/errors.d.ts +80 -0
- package/dist/store/errors.d.ts.map +1 -0
- package/dist/store/errors.js +130 -0
- package/dist/store/errors.js.map +1 -0
- package/dist/store/event-store.d.ts +52 -0
- package/dist/store/event-store.d.ts.map +1 -0
- package/dist/store/event-store.js +117 -0
- package/dist/store/event-store.js.map +1 -0
- package/dist/store/external-files.d.ts +40 -0
- package/dist/store/external-files.d.ts.map +1 -0
- package/dist/store/external-files.js +90 -0
- package/dist/store/external-files.js.map +1 -0
- package/dist/store/flusher-protocol.d.ts +82 -0
- package/dist/store/flusher-protocol.d.ts.map +1 -0
- package/dist/store/flusher-protocol.js +23 -0
- package/dist/store/flusher-protocol.js.map +1 -0
- package/dist/store/flusher-worker.d.ts +24 -0
- package/dist/store/flusher-worker.d.ts.map +1 -0
- package/dist/store/flusher-worker.js +185 -0
- package/dist/store/flusher-worker.js.map +1 -0
- package/dist/store/flusher.d.ts +87 -0
- package/dist/store/flusher.d.ts.map +1 -0
- package/dist/store/flusher.js +264 -0
- package/dist/store/flusher.js.map +1 -0
- package/dist/store/generations.d.ts +43 -0
- package/dist/store/generations.d.ts.map +1 -0
- package/dist/store/generations.js +143 -0
- package/dist/store/generations.js.map +1 -0
- package/dist/store/idempotency.d.ts +25 -0
- package/dist/store/idempotency.d.ts.map +1 -0
- package/dist/store/idempotency.js +53 -0
- package/dist/store/idempotency.js.map +1 -0
- package/dist/store/import-context.d.ts +22 -0
- package/dist/store/import-context.d.ts.map +1 -0
- package/dist/store/import-context.js +87 -0
- package/dist/store/import-context.js.map +1 -0
- package/dist/store/import-discovery.d.ts +6 -0
- package/dist/store/import-discovery.d.ts.map +1 -0
- package/dist/store/import-discovery.js +66 -0
- package/dist/store/import-discovery.js.map +1 -0
- package/dist/store/import-records.d.ts +6 -0
- package/dist/store/import-records.d.ts.map +1 -0
- package/dist/store/import-records.js +191 -0
- package/dist/store/import-records.js.map +1 -0
- package/dist/store/import-resources.d.ts +14 -0
- package/dist/store/import-resources.d.ts.map +1 -0
- package/dist/store/import-resources.js +197 -0
- package/dist/store/import-resources.js.map +1 -0
- package/dist/store/import-source.d.ts +24 -0
- package/dist/store/import-source.d.ts.map +1 -0
- package/dist/store/import-source.js +65 -0
- package/dist/store/import-source.js.map +1 -0
- package/dist/store/import-verify.d.ts +6 -0
- package/dist/store/import-verify.d.ts.map +1 -0
- package/dist/store/import-verify.js +97 -0
- package/dist/store/import-verify.js.map +1 -0
- package/dist/store/import-worker.d.ts +18 -0
- package/dist/store/import-worker.d.ts.map +1 -0
- package/dist/store/import-worker.js +69 -0
- package/dist/store/import-worker.js.map +1 -0
- package/dist/store/importer.d.ts +42 -0
- package/dist/store/importer.d.ts.map +1 -0
- package/dist/store/importer.js +239 -0
- package/dist/store/importer.js.map +1 -0
- package/dist/store/interactions.d.ts +22 -0
- package/dist/store/interactions.d.ts.map +1 -0
- package/dist/store/interactions.js +82 -0
- package/dist/store/interactions.js.map +1 -0
- package/dist/store/legacy-journal/frame-codec.d.ts +94 -0
- package/dist/store/legacy-journal/frame-codec.d.ts.map +1 -0
- package/dist/store/legacy-journal/frame-codec.js +352 -0
- package/dist/store/legacy-journal/frame-codec.js.map +1 -0
- package/dist/store/legacy-journal/frame-reader.d.ts +30 -0
- package/dist/store/legacy-journal/frame-reader.d.ts.map +1 -0
- package/dist/store/legacy-journal/frame-reader.js +97 -0
- package/dist/store/legacy-journal/frame-reader.js.map +1 -0
- package/dist/store/legacy-journal/journal-fold.d.ts +47 -0
- package/dist/store/legacy-journal/journal-fold.d.ts.map +1 -0
- package/dist/store/legacy-journal/journal-fold.js +81 -0
- package/dist/store/legacy-journal/journal-fold.js.map +1 -0
- package/dist/store/legacy-journal/journal-partition.d.ts +2 -0
- package/dist/store/legacy-journal/journal-partition.d.ts.map +1 -0
- package/dist/store/legacy-journal/journal-partition.js +10 -0
- package/dist/store/legacy-journal/journal-partition.js.map +1 -0
- package/dist/store/legacy-journal/read-only-preparation.d.ts +48 -0
- package/dist/store/legacy-journal/read-only-preparation.d.ts.map +1 -0
- package/dist/store/legacy-journal/read-only-preparation.js +430 -0
- package/dist/store/legacy-journal/read-only-preparation.js.map +1 -0
- package/dist/store/maintenance-worker.d.ts +5 -0
- package/dist/store/maintenance-worker.d.ts.map +1 -0
- package/dist/store/maintenance-worker.js +175 -0
- package/dist/store/maintenance-worker.js.map +1 -0
- package/dist/store/maintenance.d.ts +124 -0
- package/dist/store/maintenance.d.ts.map +1 -0
- package/dist/store/maintenance.js +197 -0
- package/dist/store/maintenance.js.map +1 -0
- package/dist/store/mutation.d.ts +34 -0
- package/dist/store/mutation.d.ts.map +1 -0
- package/dist/store/mutation.js +85 -0
- package/dist/store/mutation.js.map +1 -0
- package/dist/store/obligations.d.ts +101 -0
- package/dist/store/obligations.d.ts.map +1 -0
- package/dist/store/obligations.js +226 -0
- package/dist/store/obligations.js.map +1 -0
- package/dist/store/operator-decisions.d.ts +23 -0
- package/dist/store/operator-decisions.d.ts.map +1 -0
- package/dist/store/operator-decisions.js +68 -0
- package/dist/store/operator-decisions.js.map +1 -0
- package/dist/store/owner-generations.d.ts +33 -0
- package/dist/store/owner-generations.d.ts.map +1 -0
- package/dist/store/owner-generations.js +63 -0
- package/dist/store/owner-generations.js.map +1 -0
- package/dist/store/partitions.d.ts +37 -0
- package/dist/store/partitions.d.ts.map +1 -0
- package/dist/store/partitions.js +68 -0
- package/dist/store/partitions.js.map +1 -0
- package/dist/store/pragmas.d.ts +32 -0
- package/dist/store/pragmas.d.ts.map +1 -0
- package/dist/store/pragmas.js +65 -0
- package/dist/store/pragmas.js.map +1 -0
- package/dist/store/project-router.d.ts +325 -0
- package/dist/store/project-router.d.ts.map +1 -0
- package/dist/store/project-router.js +298 -0
- package/dist/store/project-router.js.map +1 -0
- package/dist/store/projects.d.ts +36 -0
- package/dist/store/projects.d.ts.map +1 -0
- package/dist/store/projects.js +238 -0
- package/dist/store/projects.js.map +1 -0
- package/dist/store/publish-blob.d.ts +20 -0
- package/dist/store/publish-blob.d.ts.map +1 -0
- package/dist/store/publish-blob.js +158 -0
- package/dist/store/publish-blob.js.map +1 -0
- package/dist/store/purge-files.d.ts +30 -0
- package/dist/store/purge-files.d.ts.map +1 -0
- package/dist/store/purge-files.js +79 -0
- package/dist/store/purge-files.js.map +1 -0
- package/dist/store/resource-rows.d.ts +40 -0
- package/dist/store/resource-rows.d.ts.map +1 -0
- package/dist/store/resource-rows.js +103 -0
- package/dist/store/resource-rows.js.map +1 -0
- package/dist/store/resources.d.ts +67 -0
- package/dist/store/resources.d.ts.map +1 -0
- package/dist/store/resources.js +147 -0
- package/dist/store/resources.js.map +1 -0
- package/dist/store/retention.d.ts +91 -0
- package/dist/store/retention.d.ts.map +1 -0
- package/dist/store/retention.js +169 -0
- package/dist/store/retention.js.map +1 -0
- package/dist/store/run-events.d.ts +14 -0
- package/dist/store/run-events.d.ts.map +1 -0
- package/dist/store/run-events.js +35 -0
- package/dist/store/run-events.js.map +1 -0
- package/dist/store/runtime.d.ts +24 -0
- package/dist/store/runtime.d.ts.map +1 -0
- package/dist/store/runtime.js +67 -0
- package/dist/store/runtime.js.map +1 -0
- package/dist/store/schema.d.ts +33 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +187 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/setup-bindings.d.ts +20 -0
- package/dist/store/setup-bindings.d.ts.map +1 -0
- package/dist/store/setup-bindings.js +52 -0
- package/dist/store/setup-bindings.js.map +1 -0
- package/dist/store/sql-command-router.d.ts +79 -0
- package/dist/store/sql-command-router.d.ts.map +1 -0
- package/dist/store/sql-command-router.js +92 -0
- package/dist/store/sql-command-router.js.map +1 -0
- package/dist/store/sql-daemon-services.d.ts +61 -0
- package/dist/store/sql-daemon-services.d.ts.map +1 -0
- package/dist/store/sql-daemon-services.js +124 -0
- package/dist/store/sql-daemon-services.js.map +1 -0
- package/dist/store/sql-recovery-export.d.ts +8 -0
- package/dist/store/sql-recovery-export.d.ts.map +1 -0
- package/dist/store/sql-recovery-export.js +110 -0
- package/dist/store/sql-recovery-export.js.map +1 -0
- package/dist/store/sql-recovery-inspection.d.ts +22 -0
- package/dist/store/sql-recovery-inspection.d.ts.map +1 -0
- package/dist/store/sql-recovery-inspection.js +88 -0
- package/dist/store/sql-recovery-inspection.js.map +1 -0
- package/dist/store/sql-recovery.d.ts +69 -0
- package/dist/store/sql-recovery.d.ts.map +1 -0
- package/dist/store/sql-recovery.js +169 -0
- package/dist/store/sql-recovery.js.map +1 -0
- package/dist/store/sql-validation.d.ts +9 -0
- package/dist/store/sql-validation.d.ts.map +1 -0
- package/dist/store/sql-validation.js +103 -0
- package/dist/store/sql-validation.js.map +1 -0
- package/dist/store/statement-observer.d.ts +7 -0
- package/dist/store/statement-observer.d.ts.map +1 -0
- package/dist/store/statement-observer.js +44 -0
- package/dist/store/statement-observer.js.map +1 -0
- package/dist/store/store.d.ts +110 -0
- package/dist/store/store.d.ts.map +1 -0
- package/dist/store/store.js +296 -0
- package/dist/store/store.js.map +1 -0
- package/dist/store/terminal-files.d.ts +21 -0
- package/dist/store/terminal-files.d.ts.map +1 -0
- package/dist/store/terminal-files.js +115 -0
- package/dist/store/terminal-files.js.map +1 -0
- package/dist/store/thread-replay.d.ts +12 -0
- package/dist/store/thread-replay.d.ts.map +1 -0
- package/dist/store/thread-replay.js +49 -0
- package/dist/store/thread-replay.js.map +1 -0
- package/dist/store/thread-rows.d.ts +25 -0
- package/dist/store/thread-rows.d.ts.map +1 -0
- package/dist/store/thread-rows.js +141 -0
- package/dist/store/thread-rows.js.map +1 -0
- package/dist/store/threads.d.ts +105 -0
- package/dist/store/threads.d.ts.map +1 -0
- package/dist/store/threads.js +423 -0
- package/dist/store/threads.js.map +1 -0
- package/dist/store/upload-binding-retention.d.ts +26 -0
- package/dist/store/upload-binding-retention.d.ts.map +1 -0
- package/dist/store/upload-binding-retention.js +142 -0
- package/dist/store/upload-binding-retention.js.map +1 -0
- package/dist/store/uploads.d.ts +30 -0
- package/dist/store/uploads.d.ts.map +1 -0
- package/dist/store/uploads.js +238 -0
- package/dist/store/uploads.js.map +1 -0
- package/dist/store-contracts.d.ts +181 -0
- package/dist/store-contracts.d.ts.map +1 -0
- package/dist/store-contracts.js +2 -0
- package/dist/store-contracts.js.map +1 -0
- package/dist/terminal-authority.d.ts +9 -0
- package/dist/terminal-authority.d.ts.map +1 -1
- package/dist/terminal-authority.js +103 -1
- package/dist/terminal-authority.js.map +1 -1
- package/dist/thread-lane-checkpoints.d.ts +0 -2
- package/dist/thread-lane-checkpoints.d.ts.map +1 -1
- package/dist/thread-lane-checkpoints.js +0 -4
- package/dist/thread-lane-checkpoints.js.map +1 -1
- package/dist/thread-store-support.d.ts +1 -27
- package/dist/thread-store-support.d.ts.map +1 -1
- package/dist/thread-store-support.js +0 -63
- package/dist/thread-store-support.js.map +1 -1
- package/dist/threads.d.ts +1 -113
- package/dist/threads.d.ts.map +1 -1
- package/dist/threads.js +1 -379
- package/dist/threads.js.map +1 -1
- package/package.json +9 -7
- package/dist/command-activity.d.ts +0 -14
- package/dist/command-activity.d.ts.map +0 -1
- package/dist/command-activity.js +0 -16
- package/dist/command-activity.js.map +0 -1
- package/dist/journal-events.d.ts +0 -4
- package/dist/journal-events.d.ts.map +0 -1
- package/dist/journal-events.js +0 -23
- package/dist/journal-events.js.map +0 -1
- package/dist/journal-maintenance.d.ts +0 -50
- package/dist/journal-maintenance.d.ts.map +0 -1
- package/dist/journal-maintenance.js +0 -162
- package/dist/journal-maintenance.js.map +0 -1
- package/dist/journal-manager-journal.d.ts +0 -18
- package/dist/journal-manager-journal.d.ts.map +0 -1
- package/dist/journal-manager-journal.js +0 -25
- package/dist/journal-manager-journal.js.map +0 -1
- package/dist/journal-manager-lifecycle.d.ts +0 -11
- package/dist/journal-manager-lifecycle.d.ts.map +0 -1
- package/dist/journal-manager-lifecycle.js +0 -2
- package/dist/journal-manager-lifecycle.js.map +0 -1
- package/dist/journal-manager.d.ts +0 -99
- package/dist/journal-manager.d.ts.map +0 -1
- package/dist/journal-manager.js +0 -559
- package/dist/journal-manager.js.map +0 -1
- package/dist/journal-prepared-operation.d.ts +0 -53
- package/dist/journal-prepared-operation.d.ts.map +0 -1
- package/dist/journal-prepared-operation.js +0 -158
- package/dist/journal-prepared-operation.js.map +0 -1
- package/dist/journal-projection-slot.d.ts +0 -28
- package/dist/journal-projection-slot.d.ts.map +0 -1
- package/dist/journal-projection-slot.js +0 -71
- package/dist/journal-projection-slot.js.map +0 -1
- package/dist/journal-projection.d.ts +0 -13
- package/dist/journal-projection.d.ts.map +0 -1
- package/dist/journal-projection.js +0 -2
- package/dist/journal-projection.js.map +0 -1
- package/dist/partition-accounts.d.ts +0 -27
- package/dist/partition-accounts.d.ts.map +0 -1
- package/dist/partition-accounts.js +0 -21
- package/dist/partition-accounts.js.map +0 -1
- package/dist/project-partition-preparation.d.ts +0 -87
- package/dist/project-partition-preparation.d.ts.map +0 -1
- package/dist/project-partition-preparation.js +0 -273
- package/dist/project-partition-preparation.js.map +0 -1
- package/dist/project-partitions.d.ts +0 -214
- package/dist/project-partitions.d.ts.map +0 -1
- package/dist/project-partitions.js +0 -486
- package/dist/project-partitions.js.map +0 -1
- package/dist/project-remove.d.ts +0 -11
- package/dist/project-remove.d.ts.map +0 -1
- package/dist/project-remove.js +0 -65
- package/dist/project-remove.js.map +0 -1
- package/dist/project-thread-listing.d.ts +0 -14
- package/dist/project-thread-listing.d.ts.map +0 -1
- package/dist/project-thread-listing.js +0 -37
- package/dist/project-thread-listing.js.map +0 -1
- package/dist/quota-projection.d.ts +0 -11
- package/dist/quota-projection.d.ts.map +0 -1
- package/dist/quota-projection.js +0 -10
- package/dist/quota-projection.js.map +0 -1
- package/dist/resource-store.d.ts +0 -39
- package/dist/resource-store.d.ts.map +0 -1
- package/dist/resource-store.js +0 -464
- package/dist/resource-store.js.map +0 -1
- package/dist/run-event-terminal-index.d.ts +0 -13
- package/dist/run-event-terminal-index.d.ts.map +0 -1
- package/dist/run-event-terminal-index.js +0 -38
- package/dist/run-event-terminal-index.js.map +0 -1
- package/dist/run-events.d.ts +0 -17
- package/dist/run-events.d.ts.map +0 -1
- package/dist/run-events.js +0 -31
- package/dist/run-events.js.map +0 -1
- package/dist/thread-head-ping.d.ts +0 -35
- package/dist/thread-head-ping.d.ts.map +0 -1
- package/dist/thread-head-ping.js +0 -67
- package/dist/thread-head-ping.js.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { deleteUnownedInlineInTx } from "./blob-files.js";
|
|
2
|
+
import { mapStoreError } from "./errors.js";
|
|
3
|
+
/** SQL committed even when a later projection/notification failed. Never retry
|
|
4
|
+
* the mutation as though this were a rollback. All owner generations are set. */
|
|
5
|
+
export class MutationPostCommitError extends AggregateError {
|
|
6
|
+
committed = true;
|
|
7
|
+
constructor(errors) {
|
|
8
|
+
super(errors, "engine store mutation committed; post-commit notification failed");
|
|
9
|
+
this.name = "MutationPostCommitError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Changes are collected during SQL writes, then published synchronously after
|
|
13
|
+
* COMMIT. Record both old and new references when a row changes its owner key. */
|
|
14
|
+
export class MutationDelta {
|
|
15
|
+
owners = new Set();
|
|
16
|
+
callbacks = [];
|
|
17
|
+
blobChanged(...digests) {
|
|
18
|
+
for (const digest of digests)
|
|
19
|
+
if (digest != null)
|
|
20
|
+
this.owners.add(`blob:${digest}`);
|
|
21
|
+
}
|
|
22
|
+
uploadChanged(...ids) {
|
|
23
|
+
for (const id of ids)
|
|
24
|
+
if (id != null)
|
|
25
|
+
this.owners.add(`upload:${id}`);
|
|
26
|
+
}
|
|
27
|
+
afterCommit(callback) {
|
|
28
|
+
this.callbacks.push(callback);
|
|
29
|
+
}
|
|
30
|
+
/** Run once after all row writers, before COMMIT. A later writer in the same
|
|
31
|
+
* mutation may still acquire a reference, so cleanup must not run earlier. */
|
|
32
|
+
clearUnownedInline(sql) {
|
|
33
|
+
for (const key of this.owners)
|
|
34
|
+
if (key.startsWith("blob:"))
|
|
35
|
+
deleteUnownedInlineInTx(sql, key.slice(5));
|
|
36
|
+
}
|
|
37
|
+
/** Used by runMutation only, after EngineStore.transaction returned. */
|
|
38
|
+
publish(store) {
|
|
39
|
+
for (const key of this.owners)
|
|
40
|
+
store.owners.noteChange(key);
|
|
41
|
+
const errors = [];
|
|
42
|
+
for (const callback of this.callbacks) {
|
|
43
|
+
try {
|
|
44
|
+
callback();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
errors.push(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (errors.length > 0)
|
|
51
|
+
throw new MutationPostCommitError(errors);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Prepare file-backed bodies before calling this function, without an await
|
|
55
|
+
* between preparation and commit. No nested transaction or async body. Failed
|
|
56
|
+
* SQL discards the delta; successful SQL publishes every owner before callbacks. */
|
|
57
|
+
export function runMutation(store, body) {
|
|
58
|
+
const changes = new MutationDelta();
|
|
59
|
+
const tx = {
|
|
60
|
+
prepare: (sql) => store.prepare(sql),
|
|
61
|
+
get inTransaction() {
|
|
62
|
+
return store.inTransaction;
|
|
63
|
+
},
|
|
64
|
+
changes,
|
|
65
|
+
now: store.now,
|
|
66
|
+
};
|
|
67
|
+
let result;
|
|
68
|
+
try {
|
|
69
|
+
result = store.transaction(() => {
|
|
70
|
+
const value = body(tx);
|
|
71
|
+
changes.clearUnownedInline(tx);
|
|
72
|
+
return value;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw mapStoreError(error, "mutating engine rows");
|
|
77
|
+
}
|
|
78
|
+
changes.publish(store);
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
export function requireTransaction(sql) {
|
|
82
|
+
if (!sql.inTransaction)
|
|
83
|
+
throw new Error("row writes require the owner's transaction");
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation.js","sourceRoot":"","sources":["../../src/store/mutation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAW5C;iFACiF;AACjF,MAAM,OAAO,uBAAwB,SAAQ,cAAc;IAChD,SAAS,GAAG,IAAI,CAAC;IAE1B,YAAY,MAAiB;QAC3B,KAAK,CAAC,MAAM,EAAE,kEAAkE,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;kFACkF;AAClF,MAAM,OAAO,aAAa;IACP,MAAM,GAAG,IAAI,GAAG,EAAY,CAAC;IAC7B,SAAS,GAAsB,EAAE,CAAC;IAEnD,WAAW,CAAC,GAAG,OAAyC;QACtD,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,IAAI,MAAM,IAAI,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,aAAa,CAAC,GAAG,GAAqC;QACpD,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,IAAI,EAAE,IAAI,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,WAAW,CAAC,QAAoB;QAC9B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED;kFAC8E;IAC9E,kBAAkB,CAAC,GAAoB;QACrC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM;YAC3B,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,uBAAuB,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,wEAAwE;IACxE,OAAO,CAAC,KAAkB;QACxB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM;YAAE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,QAAQ,EAAE,CAAC;YACb,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,uBAAuB,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC;CACF;AAED;;oFAEoF;AACpF,MAAM,UAAU,WAAW,CAAI,KAAkB,EAAE,IAAgC;IACjF,MAAM,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;IACpC,MAAM,EAAE,GAAoB;QAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QACpC,IAAI,aAAa;YACf,OAAO,KAAK,CAAC,aAAa,CAAC;QAC7B,CAAC;QACD,OAAO;QACP,GAAG,EAAE,KAAK,CAAC,GAAG;KACf,CAAC;IACF,IAAI,MAAS,CAAC;IACd,IAAI,CAAC;QACH,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;YAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;YACvB,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,aAAa,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAoB;IACrD,IAAI,CAAC,GAAG,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { EngineStore } from "./store.js";
|
|
2
|
+
import { type MutationContext } from "./mutation.js";
|
|
3
|
+
/** `effect_obligation.kind` values (SYNTHESIS_R5 §4.6). Data, not enum-in-logic:
|
|
4
|
+
* stores register a completion handler per kind at startup. */
|
|
5
|
+
export declare const OBLIGATION_KINDS: readonly ["terminal_files", "publish_blob", "archive_fs", "purge_fs", "quarantine_fs"];
|
|
6
|
+
export type ObligationKind = (typeof OBLIGATION_KINDS)[number];
|
|
7
|
+
export type ObligationState = "pending" | "materialized";
|
|
8
|
+
export interface ObligationRow {
|
|
9
|
+
kind: ObligationKind;
|
|
10
|
+
key: string;
|
|
11
|
+
pid: number;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
payload: unknown;
|
|
14
|
+
state: ObligationState;
|
|
15
|
+
materializedGeneration: number | null;
|
|
16
|
+
}
|
|
17
|
+
/** What a completion handler may do: redo the effect and bind its directories. */
|
|
18
|
+
export interface ObligationEffects {
|
|
19
|
+
register(dir: string): number;
|
|
20
|
+
}
|
|
21
|
+
export type ObligationHandler = (obligation: ObligationRow, effects: ObligationEffects) => void | Promise<void>;
|
|
22
|
+
export interface ObligationCompletionReceipt {
|
|
23
|
+
completed: Array<{
|
|
24
|
+
kind: ObligationKind;
|
|
25
|
+
key: string;
|
|
26
|
+
}>;
|
|
27
|
+
failed: Array<{
|
|
28
|
+
kind: ObligationKind;
|
|
29
|
+
key: string;
|
|
30
|
+
error: string;
|
|
31
|
+
}>;
|
|
32
|
+
unhandled: Array<{
|
|
33
|
+
kind: ObligationKind;
|
|
34
|
+
key: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Obligations (SYNTHESIS_R5 §4.6 as amended by R5_AMENDMENTS A2): the row is
|
|
39
|
+
* created `pending` in the SAME transaction as the decision it protects; the
|
|
40
|
+
* effect runs (files, links, renames) and registers its directories; once
|
|
41
|
+
* EVERY effect succeeded the owner materializes the row in one
|
|
42
|
+
* micro-transaction, recording the generation of the last registration; only
|
|
43
|
+
* `synced(G >= materialized_g)` deletes it. A `pending` row is never touched
|
|
44
|
+
* by `synced`, however many registrations it has. Startup replays every open
|
|
45
|
+
* row through idempotent handlers — their count is unfinished work, never
|
|
46
|
+
* history.
|
|
47
|
+
*/
|
|
48
|
+
export declare class Obligations {
|
|
49
|
+
private readonly store;
|
|
50
|
+
private readonly options;
|
|
51
|
+
private readonly tracked;
|
|
52
|
+
private readonly handlers;
|
|
53
|
+
private readonly unsubscribe;
|
|
54
|
+
/**
|
|
55
|
+
* Uses the store's owner-generation map (A3/C10): an open
|
|
56
|
+
* `publish_blob` row is an owner of its digest, so clearing it is an owner
|
|
57
|
+
* change the blob GC must observe. `log` receives a failed clear (ENOSPC,
|
|
58
|
+
* SQLite error); the rows stay tracked and the clear retries on the next
|
|
59
|
+
* `synced` instead of becoming an uncaught exception on the request thread.
|
|
60
|
+
*/
|
|
61
|
+
constructor(store: EngineStore, options?: {
|
|
62
|
+
log?: (line: string) => void;
|
|
63
|
+
/** Already deleted and committed. Shared blob owner generations are
|
|
64
|
+
* updated before this notification; consumers must not repeat them. */
|
|
65
|
+
onCleared?: (rows: readonly ObligationRow[]) => void;
|
|
66
|
+
});
|
|
67
|
+
/** Pure row write inside the caller's transaction. A duplicate (kind, key)
|
|
68
|
+
* is a constraint violation. The enclosing mutation records any publish_blob
|
|
69
|
+
* reference with changes.blobChanged alongside its upload/resource changes. */
|
|
70
|
+
create(kind: ObligationKind, key: string, pid: number, payload: unknown): void;
|
|
71
|
+
/** Bind a directory the effect touched; returns the registration generation. */
|
|
72
|
+
registerEffect(kind: ObligationKind, key: string, dir: string): number;
|
|
73
|
+
/**
|
|
74
|
+
* Every effect succeeded: `pending → materialized` with `materialized_g` =
|
|
75
|
+
* the last registration (or a fresh mark when the effect registered
|
|
76
|
+
* nothing). Runs as its own micro-transaction. A composed decision uses
|
|
77
|
+
* materializeInTx with its MutationContext instead, so rollback cannot
|
|
78
|
+
* publish materialized state in memory.
|
|
79
|
+
*/
|
|
80
|
+
materialize(kind: ObligationKind, key: string): number;
|
|
81
|
+
/** `generation` is the last file registration (or an empty-effect mark)
|
|
82
|
+
* prepared outside this transaction. Row state and the enclosing decision
|
|
83
|
+
* commit together; only their successful commit enables synced to clear it. */
|
|
84
|
+
materializeInTx(tx: MutationContext, kind: ObligationKind, key: string, generation: number): number;
|
|
85
|
+
open(): ObligationRow[];
|
|
86
|
+
get(kind: ObligationKind, key: string): ObligationRow | undefined;
|
|
87
|
+
/** Stores register one idempotent completion handler per kind at startup. */
|
|
88
|
+
registerHandler(kind: ObligationKind, handler: ObligationHandler): void;
|
|
89
|
+
/**
|
|
90
|
+
* Startup hook: redo every open row through its handler and materialize it
|
|
91
|
+
* with a fresh generation (a row left `materialized` by a crashed process
|
|
92
|
+
* names generations nobody can prove any more). A handler failure leaves
|
|
93
|
+
* the row `pending` (the fact `obligations_open` discloses it); a kind
|
|
94
|
+
* without a handler is reported, never silently dropped.
|
|
95
|
+
*/
|
|
96
|
+
completeOpen(): Promise<ObligationCompletionReceipt>;
|
|
97
|
+
close(): void;
|
|
98
|
+
private entry;
|
|
99
|
+
private clearSynced;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=obligations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../src/store/obligations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { requireTransaction, runMutation } from "./mutation.js";
|
|
2
|
+
import { deleteUnownedInlineInTx } from "./blob-files.js";
|
|
3
|
+
/** `effect_obligation.kind` values (SYNTHESIS_R5 §4.6). Data, not enum-in-logic:
|
|
4
|
+
* stores register a completion handler per kind at startup. */
|
|
5
|
+
export const OBLIGATION_KINDS = [
|
|
6
|
+
"terminal_files",
|
|
7
|
+
"publish_blob",
|
|
8
|
+
"archive_fs",
|
|
9
|
+
"purge_fs",
|
|
10
|
+
"quarantine_fs",
|
|
11
|
+
];
|
|
12
|
+
function fromRow(row) {
|
|
13
|
+
return {
|
|
14
|
+
kind: row.kind,
|
|
15
|
+
key: row.key,
|
|
16
|
+
pid: Number(row.pid),
|
|
17
|
+
createdAt: row.created_at,
|
|
18
|
+
payload: JSON.parse(Buffer.from(row.payload).toString("utf8")),
|
|
19
|
+
state: row.state,
|
|
20
|
+
materializedGeneration: row.materialized_g === null ? null : Number(row.materialized_g),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function trackKey(kind, key) {
|
|
24
|
+
return `${kind}\0${key}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Obligations (SYNTHESIS_R5 §4.6 as amended by R5_AMENDMENTS A2): the row is
|
|
28
|
+
* created `pending` in the SAME transaction as the decision it protects; the
|
|
29
|
+
* effect runs (files, links, renames) and registers its directories; once
|
|
30
|
+
* EVERY effect succeeded the owner materializes the row in one
|
|
31
|
+
* micro-transaction, recording the generation of the last registration; only
|
|
32
|
+
* `synced(G >= materialized_g)` deletes it. A `pending` row is never touched
|
|
33
|
+
* by `synced`, however many registrations it has. Startup replays every open
|
|
34
|
+
* row through idempotent handlers — their count is unfinished work, never
|
|
35
|
+
* history.
|
|
36
|
+
*/
|
|
37
|
+
export class Obligations {
|
|
38
|
+
store;
|
|
39
|
+
options;
|
|
40
|
+
tracked = new Map();
|
|
41
|
+
handlers = new Map();
|
|
42
|
+
unsubscribe;
|
|
43
|
+
/**
|
|
44
|
+
* Uses the store's owner-generation map (A3/C10): an open
|
|
45
|
+
* `publish_blob` row is an owner of its digest, so clearing it is an owner
|
|
46
|
+
* change the blob GC must observe. `log` receives a failed clear (ENOSPC,
|
|
47
|
+
* SQLite error); the rows stay tracked and the clear retries on the next
|
|
48
|
+
* `synced` instead of becoming an uncaught exception on the request thread.
|
|
49
|
+
*/
|
|
50
|
+
constructor(store, options = {}) {
|
|
51
|
+
this.store = store;
|
|
52
|
+
this.options = options;
|
|
53
|
+
this.unsubscribe = store.onSynced((generation) => this.clearSynced(generation));
|
|
54
|
+
}
|
|
55
|
+
/** Pure row write inside the caller's transaction. A duplicate (kind, key)
|
|
56
|
+
* is a constraint violation. The enclosing mutation records any publish_blob
|
|
57
|
+
* reference with changes.blobChanged alongside its upload/resource changes. */
|
|
58
|
+
create(kind, key, pid, payload) {
|
|
59
|
+
if (!this.store.inTransaction) {
|
|
60
|
+
throw new Error("an obligation is created inside the transaction of its decision");
|
|
61
|
+
}
|
|
62
|
+
this.store
|
|
63
|
+
.prepare("INSERT INTO effect_obligation(kind, key, pid, created_at, payload, state) VALUES(?, ?, ?, ?, ?, 'pending')")
|
|
64
|
+
.run(kind, key, pid, this.store.now().toISOString(), Buffer.from(JSON.stringify(payload)));
|
|
65
|
+
}
|
|
66
|
+
/** Bind a directory the effect touched; returns the registration generation. */
|
|
67
|
+
registerEffect(kind, key, dir) {
|
|
68
|
+
if (this.store.inTransaction)
|
|
69
|
+
throw new Error("file effects run outside SQL transactions");
|
|
70
|
+
const g = this.store.registerExternal(dir);
|
|
71
|
+
this.entry(kind, key).lastRegistration = g;
|
|
72
|
+
return g;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Every effect succeeded: `pending → materialized` with `materialized_g` =
|
|
76
|
+
* the last registration (or a fresh mark when the effect registered
|
|
77
|
+
* nothing). Runs as its own micro-transaction. A composed decision uses
|
|
78
|
+
* materializeInTx with its MutationContext instead, so rollback cannot
|
|
79
|
+
* publish materialized state in memory.
|
|
80
|
+
*/
|
|
81
|
+
materialize(kind, key) {
|
|
82
|
+
if (this.store.inTransaction) {
|
|
83
|
+
throw new Error("use materializeInTx with the owner's MutationContext");
|
|
84
|
+
}
|
|
85
|
+
const generation = this.tracked.get(trackKey(kind, key))?.lastRegistration ?? this.store.mark();
|
|
86
|
+
return runMutation(this.store, (tx) => this.materializeInTx(tx, kind, key, generation));
|
|
87
|
+
}
|
|
88
|
+
/** `generation` is the last file registration (or an empty-effect mark)
|
|
89
|
+
* prepared outside this transaction. Row state and the enclosing decision
|
|
90
|
+
* commit together; only their successful commit enables synced to clear it. */
|
|
91
|
+
materializeInTx(tx, kind, key, generation) {
|
|
92
|
+
requireTransaction(tx);
|
|
93
|
+
const result = tx
|
|
94
|
+
.prepare("UPDATE effect_obligation SET state = 'materialized', materialized_g = ? WHERE kind = ? AND key = ?")
|
|
95
|
+
.run(generation, kind, key);
|
|
96
|
+
if (Number(result.changes) === 0)
|
|
97
|
+
throw new Error(`no obligation ${kind}:${key}`);
|
|
98
|
+
tx.changes.afterCommit(() => {
|
|
99
|
+
this.entry(kind, key).materializedGeneration = generation;
|
|
100
|
+
});
|
|
101
|
+
return generation;
|
|
102
|
+
}
|
|
103
|
+
open() {
|
|
104
|
+
return this.store
|
|
105
|
+
.prepare("SELECT kind, key, pid, created_at, payload, state, materialized_g FROM effect_obligation ORDER BY created_at, kind, key")
|
|
106
|
+
.all().map(fromRow);
|
|
107
|
+
}
|
|
108
|
+
get(kind, key) {
|
|
109
|
+
const row = this.store
|
|
110
|
+
.prepare("SELECT kind,key,pid,created_at,payload,state,materialized_g FROM effect_obligation WHERE kind=? AND key=?")
|
|
111
|
+
.get(kind, key);
|
|
112
|
+
return row ? fromRow(row) : undefined;
|
|
113
|
+
}
|
|
114
|
+
/** Stores register one idempotent completion handler per kind at startup. */
|
|
115
|
+
registerHandler(kind, handler) {
|
|
116
|
+
if (this.handlers.has(kind))
|
|
117
|
+
throw new Error(`obligation handler for '${kind}' already registered`);
|
|
118
|
+
this.handlers.set(kind, handler);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Startup hook: redo every open row through its handler and materialize it
|
|
122
|
+
* with a fresh generation (a row left `materialized` by a crashed process
|
|
123
|
+
* names generations nobody can prove any more). A handler failure leaves
|
|
124
|
+
* the row `pending` (the fact `obligations_open` discloses it); a kind
|
|
125
|
+
* without a handler is reported, never silently dropped.
|
|
126
|
+
*/
|
|
127
|
+
async completeOpen() {
|
|
128
|
+
const open = this.open();
|
|
129
|
+
// A generation persisted by another process is not durability evidence.
|
|
130
|
+
// Reset every open row before the first await, including unhandled kinds.
|
|
131
|
+
runMutation(this.store, (tx) => {
|
|
132
|
+
tx.prepare("UPDATE effect_obligation SET state = 'pending', materialized_g = NULL WHERE state = 'materialized' OR materialized_g IS NOT NULL").run();
|
|
133
|
+
tx.changes.afterCommit(() => this.tracked.clear());
|
|
134
|
+
});
|
|
135
|
+
const receipt = { completed: [], failed: [], unhandled: [] };
|
|
136
|
+
for (const obligation of open) {
|
|
137
|
+
const handler = this.handlers.get(obligation.kind);
|
|
138
|
+
if (!handler) {
|
|
139
|
+
receipt.unhandled.push({ kind: obligation.kind, key: obligation.key });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
await handler(obligation, {
|
|
144
|
+
register: (dir) => this.registerEffect(obligation.kind, obligation.key, dir),
|
|
145
|
+
});
|
|
146
|
+
this.materialize(obligation.kind, obligation.key);
|
|
147
|
+
receipt.completed.push({ kind: obligation.kind, key: obligation.key });
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
receipt.failed.push({
|
|
151
|
+
kind: obligation.kind,
|
|
152
|
+
key: obligation.key,
|
|
153
|
+
error: error instanceof Error ? error.message : String(error),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return receipt;
|
|
158
|
+
}
|
|
159
|
+
close() {
|
|
160
|
+
this.unsubscribe();
|
|
161
|
+
this.tracked.clear();
|
|
162
|
+
}
|
|
163
|
+
entry(kind, key) {
|
|
164
|
+
const id = trackKey(kind, key);
|
|
165
|
+
let entry = this.tracked.get(id);
|
|
166
|
+
if (!entry) {
|
|
167
|
+
entry = { lastRegistration: null, materializedGeneration: null };
|
|
168
|
+
this.tracked.set(id, entry);
|
|
169
|
+
}
|
|
170
|
+
return entry;
|
|
171
|
+
}
|
|
172
|
+
clearSynced(generation) {
|
|
173
|
+
if (this.store.isClosed)
|
|
174
|
+
return;
|
|
175
|
+
const clearable = [];
|
|
176
|
+
for (const [id, entry] of this.tracked) {
|
|
177
|
+
if (entry.materializedGeneration === null || entry.materializedGeneration > generation)
|
|
178
|
+
continue;
|
|
179
|
+
const [kind, key] = id.split("\0");
|
|
180
|
+
clearable.push([kind, key]);
|
|
181
|
+
}
|
|
182
|
+
if (clearable.length === 0)
|
|
183
|
+
return;
|
|
184
|
+
let cleared;
|
|
185
|
+
try {
|
|
186
|
+
const remove = this.store.prepare("DELETE FROM effect_obligation WHERE kind = ? AND key = ? AND state = 'materialized' AND materialized_g <= ? RETURNING kind, key, pid, created_at, payload, state, materialized_g");
|
|
187
|
+
cleared = this.store.transaction(() => {
|
|
188
|
+
const removed = [];
|
|
189
|
+
for (const [kind, key] of clearable) {
|
|
190
|
+
removed.push(...remove.all(kind, key, generation).map(fromRow));
|
|
191
|
+
}
|
|
192
|
+
for (const row of removed) {
|
|
193
|
+
const sha = row.kind === "publish_blob" ? row.payload?.sha : null;
|
|
194
|
+
if (typeof sha === "string")
|
|
195
|
+
deleteUnownedInlineInTx(this.store, sha);
|
|
196
|
+
}
|
|
197
|
+
return removed;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
// The rows stay tracked and materialized; the next synced retries.
|
|
202
|
+
this.options.log?.(`obligation clear deferred: ${error instanceof Error ? error.message : String(error)}`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
for (const [kind, key] of clearable)
|
|
206
|
+
this.tracked.delete(trackKey(kind, key));
|
|
207
|
+
// The deleted publish_blob rows were owners of their digests (A3): the GC
|
|
208
|
+
// waiting on this very barrier must see the owner change and wait again.
|
|
209
|
+
for (const row of cleared) {
|
|
210
|
+
if (row.kind !== "publish_blob")
|
|
211
|
+
continue;
|
|
212
|
+
const digest = row.payload?.sha;
|
|
213
|
+
if (typeof digest === "string")
|
|
214
|
+
this.store.owners.noteChange(`blob:${digest}`);
|
|
215
|
+
}
|
|
216
|
+
if (cleared.length > 0) {
|
|
217
|
+
try {
|
|
218
|
+
this.options.onCleared?.(cleared);
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
this.options.log?.(`obligation rows cleared and committed; notification failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=obligations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obligations.js","sourceRoot":"","sources":["../../src/store/obligations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type DecisionMutation, type OperatorDecisionRecord, type RecordedOperatorDecision } from "../operator-decisions.js";
|
|
2
|
+
import type { SqlEventLedger } from "./event-store.js";
|
|
3
|
+
import { type SqlWriteContext } from "./mutation.js";
|
|
4
|
+
import type { EngineStore } from "./store.js";
|
|
5
|
+
/** Latest decision and every original request binding share the row transaction. */
|
|
6
|
+
export declare function applyDecisionInTx(sql: SqlWriteContext, pid: number, input: DecisionMutation): void;
|
|
7
|
+
export declare class SqlOperatorDecisionStore {
|
|
8
|
+
private readonly store;
|
|
9
|
+
private readonly events;
|
|
10
|
+
constructor(store: EngineStore, events: SqlEventLedger);
|
|
11
|
+
get(runId: string): OperatorDecisionRecord | null;
|
|
12
|
+
findByIdempotency(runId: string, idempotency: {
|
|
13
|
+
key: string;
|
|
14
|
+
client: string;
|
|
15
|
+
request: unknown;
|
|
16
|
+
}): OperatorDecisionRecord | null;
|
|
17
|
+
record(input: OperatorDecisionRecord, idempotency?: {
|
|
18
|
+
key: string;
|
|
19
|
+
client: string;
|
|
20
|
+
request: unknown;
|
|
21
|
+
}): RecordedOperatorDecision;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=operator-decisions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-decisions.d.ts","sourceRoot":"","sources":["../../src/store/operator-decisions.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,oFAAoF;AACpF,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,gBAAgB,GACtB,IAAI,CAwBN;AAED,qBAAa,wBAAwB;IAEjC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFzB,YACmB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,cAAc,EACrC;IAEJ,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAKhD;IAED,iBAAiB,CACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAC7D,sBAAsB,GAAG,IAAI,CAW/B;IAED,MAAM,CACJ,KAAK,EAAE,sBAAsB,EAC7B,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAC9D,wBAAwB,CAkB1B;CACF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { operatorDecisionBinding, parseDecisionMutation, parseOperatorDecision, } from "../operator-decisions.js";
|
|
2
|
+
import { bindIdempotencyInTx, lookupIdempotency } from "./idempotency.js";
|
|
3
|
+
import { requireTransaction, runMutation } from "./mutation.js";
|
|
4
|
+
/** Latest decision and every original request binding share the row transaction. */
|
|
5
|
+
export function applyDecisionInTx(sql, pid, input) {
|
|
6
|
+
requireTransaction(sql);
|
|
7
|
+
const mutation = parseDecisionMutation(input);
|
|
8
|
+
const result = sql
|
|
9
|
+
.prepare("INSERT INTO operator_decision(run_id,pid,body) VALUES(?,?,?) ON CONFLICT(run_id) DO UPDATE SET body=excluded.body WHERE operator_decision.pid=excluded.pid")
|
|
10
|
+
.run(mutation.decision.runId, pid, Buffer.from(JSON.stringify(mutation.decision)));
|
|
11
|
+
if (Number(result.changes) !== 1)
|
|
12
|
+
throw new Error("operator decision belongs to a different partition");
|
|
13
|
+
if (mutation.idempotency) {
|
|
14
|
+
const { keyDigest, requestDigest, runId } = mutation.idempotency;
|
|
15
|
+
const binding = bindIdempotencyInTx(sql, {
|
|
16
|
+
owner: "decision",
|
|
17
|
+
pid,
|
|
18
|
+
keyDigest,
|
|
19
|
+
requestDigest,
|
|
20
|
+
targetId: runId,
|
|
21
|
+
operation: "run.decision",
|
|
22
|
+
createdAt: mutation.decision.decidedAt,
|
|
23
|
+
});
|
|
24
|
+
if (binding.targetId !== runId)
|
|
25
|
+
throw new Error("conflicting operator decision idempotency history");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class SqlOperatorDecisionStore {
|
|
29
|
+
store;
|
|
30
|
+
events;
|
|
31
|
+
constructor(store, events) {
|
|
32
|
+
this.store = store;
|
|
33
|
+
this.events = events;
|
|
34
|
+
}
|
|
35
|
+
get(runId) {
|
|
36
|
+
const row = this.store
|
|
37
|
+
.prepare("SELECT body FROM operator_decision WHERE run_id=? AND pid=?")
|
|
38
|
+
.get(runId, this.events.generation.pid);
|
|
39
|
+
return row ? parseOperatorDecision(JSON.parse(Buffer.from(row.body).toString("utf8"))) : null;
|
|
40
|
+
}
|
|
41
|
+
findByIdempotency(runId, idempotency) {
|
|
42
|
+
const key = operatorDecisionBinding(this.events.generation.name, runId, idempotency);
|
|
43
|
+
const binding = lookupIdempotency(this.store, { owner: "decision", pid: this.events.generation.pid, keyDigest: key.keyDigest }, key.requestDigest);
|
|
44
|
+
if (!binding)
|
|
45
|
+
return null;
|
|
46
|
+
const decision = this.get(binding.targetId);
|
|
47
|
+
if (!decision)
|
|
48
|
+
throw new Error("operator decision idempotency index is dangling");
|
|
49
|
+
return decision;
|
|
50
|
+
}
|
|
51
|
+
record(input, idempotency) {
|
|
52
|
+
const decision = parseOperatorDecision(input);
|
|
53
|
+
const binding = operatorDecisionBinding(this.events.generation.name, decision.runId, idempotency);
|
|
54
|
+
if (idempotency) {
|
|
55
|
+
const prior = this.findByIdempotency(decision.runId, idempotency);
|
|
56
|
+
if (prior)
|
|
57
|
+
return { record: prior, reused: true };
|
|
58
|
+
}
|
|
59
|
+
const mutation = { decision, ...(binding ? { idempotency: binding } : {}) };
|
|
60
|
+
const event = this.events.prepare("operator.decision_recorded", mutation);
|
|
61
|
+
runMutation(this.store, (tx) => {
|
|
62
|
+
applyDecisionInTx(tx, this.events.generation.pid, mutation);
|
|
63
|
+
this.events.appendInTx(tx, event);
|
|
64
|
+
});
|
|
65
|
+
return { record: decision, reused: false };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=operator-decisions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-decisions.js","sourceRoot":"","sources":["../../src/store/operator-decisions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { EngineStore } from "./store.js";
|
|
2
|
+
/** `blob:<sha256>` or `upload:<uploadId>`: the file families the sweep/GC may unlink by "no owner". */
|
|
3
|
+
export type OwnerKey = `blob:${string}` | `upload:${string}`;
|
|
4
|
+
export type UnlinkOutcome = "removed" | "owned";
|
|
5
|
+
export interface UnlinkRequest {
|
|
6
|
+
path: string;
|
|
7
|
+
/** Synchronous owner check in the recheck section (reverse indexes / the `upload` row). */
|
|
8
|
+
owners: () => boolean;
|
|
9
|
+
/** Runs in the same synchronous section right after the unlink (e.g. the `blob` row delete). */
|
|
10
|
+
afterUnlink?: () => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The one rule for every unlink by "no owner" (R5_AMENDMENTS C10, generalizing
|
|
14
|
+
* A3/C3 and replacing the C9 mechanism). The main thread records, after every
|
|
15
|
+
* COMMIT that inserts, deletes or changes an owner row of a key, the
|
|
16
|
+
* generation of that change; the unlink waits for the barrier covering the
|
|
17
|
+
* latest such generation and then, in ONE synchronous section, retries when
|
|
18
|
+
* the owner moved during the wait, keeps when an owner exists, else unlinks
|
|
19
|
+
* (ENOENT is success). One flight per key; concurrent callers join it.
|
|
20
|
+
*/
|
|
21
|
+
export declare class OwnerGenerations {
|
|
22
|
+
private readonly store;
|
|
23
|
+
private readonly generations;
|
|
24
|
+
private readonly inflight;
|
|
25
|
+
constructor(store: EngineStore);
|
|
26
|
+
/** Right after the COMMIT of a transaction that touched the key's owner row(s). */
|
|
27
|
+
noteChange(key: OwnerKey): number;
|
|
28
|
+
/** Test seam: the generation currently bound to a key. */
|
|
29
|
+
generationOf(key: OwnerKey): number | undefined;
|
|
30
|
+
unlinkWhenUnowned(key: OwnerKey, request: UnlinkRequest): Promise<UnlinkOutcome>;
|
|
31
|
+
private loop;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=owner-generations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-generations.d.ts","sourceRoot":"","sources":["../../src/store/owner-generations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,uGAAuG;AACvG,MAAM,MAAM,QAAQ,GAAG,QAAQ,MAAM,EAAE,GAAG,UAAU,MAAM,EAAE,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAIf,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHlC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+C;IAExE,YAA6B,KAAK,EAAE,WAAW,EAAI;IAEnD,mFAAmF;IACnF,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAIhC;IAED,0DAA0D;IAC1D,YAAY,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAE9C;IAED,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAQ/E;YAEa,IAAI;CAoBnB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { unlinkSync } from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* The one rule for every unlink by "no owner" (R5_AMENDMENTS C10, generalizing
|
|
4
|
+
* A3/C3 and replacing the C9 mechanism). The main thread records, after every
|
|
5
|
+
* COMMIT that inserts, deletes or changes an owner row of a key, the
|
|
6
|
+
* generation of that change; the unlink waits for the barrier covering the
|
|
7
|
+
* latest such generation and then, in ONE synchronous section, retries when
|
|
8
|
+
* the owner moved during the wait, keeps when an owner exists, else unlinks
|
|
9
|
+
* (ENOENT is success). One flight per key; concurrent callers join it.
|
|
10
|
+
*/
|
|
11
|
+
export class OwnerGenerations {
|
|
12
|
+
store;
|
|
13
|
+
generations = new Map();
|
|
14
|
+
inflight = new Map();
|
|
15
|
+
constructor(store) {
|
|
16
|
+
this.store = store;
|
|
17
|
+
}
|
|
18
|
+
/** Right after the COMMIT of a transaction that touched the key's owner row(s). */
|
|
19
|
+
noteChange(key) {
|
|
20
|
+
const g = this.store.mark();
|
|
21
|
+
this.generations.set(key, g);
|
|
22
|
+
return g;
|
|
23
|
+
}
|
|
24
|
+
/** Test seam: the generation currently bound to a key. */
|
|
25
|
+
generationOf(key) {
|
|
26
|
+
return this.generations.get(key);
|
|
27
|
+
}
|
|
28
|
+
unlinkWhenUnowned(key, request) {
|
|
29
|
+
const running = this.inflight.get(key);
|
|
30
|
+
if (running)
|
|
31
|
+
return running;
|
|
32
|
+
const flight = this.loop(key, request).finally(() => {
|
|
33
|
+
if (this.inflight.get(key) === flight)
|
|
34
|
+
this.inflight.delete(key);
|
|
35
|
+
});
|
|
36
|
+
this.inflight.set(key, flight);
|
|
37
|
+
return flight;
|
|
38
|
+
}
|
|
39
|
+
async loop(key, request) {
|
|
40
|
+
for (;;) {
|
|
41
|
+
const gWait = this.generations.get(key) ?? this.store.mark();
|
|
42
|
+
await this.store.synced(gWait);
|
|
43
|
+
// One synchronous section: no await below this line.
|
|
44
|
+
if ((this.generations.get(key) ?? gWait) > gWait)
|
|
45
|
+
continue;
|
|
46
|
+
if (request.owners()) {
|
|
47
|
+
this.generations.delete(key);
|
|
48
|
+
return "owned";
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
unlinkSync(request.path);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error.code !== "ENOENT")
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
request.afterUnlink?.();
|
|
58
|
+
this.generations.delete(key);
|
|
59
|
+
return "removed";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=owner-generations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-generations.js","sourceRoot":"","sources":["../../src/store/owner-generations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAgBrC;;;;;;;;GAQG;AACH,MAAM,OAAO,gBAAgB;IAIE,KAAK;IAHjB,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,QAAQ,GAAG,IAAI,GAAG,EAAoC,CAAC;IAExE,YAA6B,KAAkB;qBAAlB,KAAK;IAAgB,CAAC;IAEnD,mFAAmF;IACnF,UAAU,CAAC,GAAa;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC7B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,0DAA0D;IAC1D,YAAY,CAAC,GAAa;QACxB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,iBAAiB,CAAC,GAAa,EAAE,OAAsB;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,MAAM;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,GAAa,EAAE,OAAsB;QACtD,SAAS,CAAC;YACR,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/B,qDAAqD;YACrD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK;gBAAE,SAAS;YAC3D,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACrB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7B,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,IAAI,CAAC;gBACH,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YACtE,CAAC;YACD,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7B,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
|