@optimystic/db-p2p 0.13.5 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/src/cluster/block-transfer-service.d.ts +67 -8
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +101 -62
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/client.d.ts +18 -1
- package/dist/src/cluster/client.d.ts.map +1 -1
- package/dist/src/cluster/client.js +55 -39
- package/dist/src/cluster/client.js.map +1 -1
- package/dist/src/cluster/cluster-error.d.ts +38 -0
- package/dist/src/cluster/cluster-error.d.ts.map +1 -0
- package/dist/src/cluster/cluster-error.js +51 -0
- package/dist/src/cluster/cluster-error.js.map +1 -0
- package/dist/src/cluster/cluster-repo.d.ts +135 -3
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +333 -58
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/commit-cert.d.ts +63 -0
- package/dist/src/cluster/commit-cert.d.ts.map +1 -0
- package/dist/src/cluster/commit-cert.js +108 -0
- package/dist/src/cluster/commit-cert.js.map +1 -0
- package/dist/src/cluster/service.d.ts +46 -11
- package/dist/src/cluster/service.d.ts.map +1 -1
- package/dist/src/cluster/service.js +97 -33
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/cluster/spread-on-churn.d.ts +13 -0
- package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
- package/dist/src/cluster/spread-on-churn.js +34 -4
- package/dist/src/cluster/spread-on-churn.js.map +1 -1
- package/dist/src/cohort-topic/bootstrap-evidence-builder.d.ts +59 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.js +79 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.js.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.d.ts +81 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.js +93 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.js.map +1 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.d.ts +108 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.js +108 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.js.map +1 -0
- package/dist/src/cohort-topic/change-bridge.d.ts +65 -0
- package/dist/src/cohort-topic/change-bridge.d.ts.map +1 -0
- package/dist/src/cohort-topic/change-bridge.js +76 -0
- package/dist/src/cohort-topic/change-bridge.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts +74 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.js +87 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts +42 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js +57 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js.map +1 -0
- package/dist/src/cohort-topic/fret-trust-anchor.d.ts +100 -0
- package/dist/src/cohort-topic/fret-trust-anchor.d.ts.map +1 -0
- package/dist/src/cohort-topic/fret-trust-anchor.js +115 -0
- package/dist/src/cohort-topic/fret-trust-anchor.js.map +1 -0
- package/dist/src/cohort-topic/host.d.ts +573 -0
- package/dist/src/cohort-topic/host.d.ts.map +1 -0
- package/dist/src/cohort-topic/host.js +1460 -0
- package/dist/src/cohort-topic/host.js.map +1 -0
- package/dist/src/cohort-topic/index.d.ts +14 -0
- package/dist/src/cohort-topic/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/index.js +14 -0
- package/dist/src/cohort-topic/index.js.map +1 -0
- package/dist/src/cohort-topic/membership-publish-sink.d.ts +14 -0
- package/dist/src/cohort-topic/membership-publish-sink.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership-publish-sink.js +17 -0
- package/dist/src/cohort-topic/membership-publish-sink.js.map +1 -0
- package/dist/src/cohort-topic/membership-source.d.ts +36 -0
- package/dist/src/cohort-topic/membership-source.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership-source.js +58 -0
- package/dist/src/cohort-topic/membership-source.js.map +1 -0
- package/dist/src/cohort-topic/peer-codec.d.ts +18 -0
- package/dist/src/cohort-topic/peer-codec.d.ts.map +1 -0
- package/dist/src/cohort-topic/peer-codec.js +26 -0
- package/dist/src/cohort-topic/peer-codec.js.map +1 -0
- package/dist/src/cohort-topic/peer-sig.d.ts +52 -0
- package/dist/src/cohort-topic/peer-sig.d.ts.map +1 -0
- package/dist/src/cohort-topic/peer-sig.js +83 -0
- package/dist/src/cohort-topic/peer-sig.js.map +1 -0
- package/dist/src/cohort-topic/protocols.d.ts +49 -0
- package/dist/src/cohort-topic/protocols.d.ts.map +1 -0
- package/dist/src/cohort-topic/protocols.js +58 -0
- package/dist/src/cohort-topic/protocols.js.map +1 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.d.ts +49 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.d.ts.map +1 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.js +42 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.js.map +1 -0
- package/dist/src/cohort-topic/size-estimator.d.ts +16 -0
- package/dist/src/cohort-topic/size-estimator.d.ts.map +1 -0
- package/dist/src/cohort-topic/size-estimator.js +16 -0
- package/dist/src/cohort-topic/size-estimator.js.map +1 -0
- package/dist/src/cohort-topic/stream-util.d.ts +19 -0
- package/dist/src/cohort-topic/stream-util.d.ts.map +1 -0
- package/dist/src/cohort-topic/stream-util.js +76 -0
- package/dist/src/cohort-topic/stream-util.js.map +1 -0
- package/dist/src/cohort-topic/threshold-crypto.d.ts +94 -0
- package/dist/src/cohort-topic/threshold-crypto.d.ts.map +1 -0
- package/dist/src/cohort-topic/threshold-crypto.js +178 -0
- package/dist/src/cohort-topic/threshold-crypto.js.map +1 -0
- package/dist/src/cohort-topic/topic-router.d.ts +41 -0
- package/dist/src/cohort-topic/topic-router.d.ts.map +1 -0
- package/dist/src/cohort-topic/topic-router.js +63 -0
- package/dist/src/cohort-topic/topic-router.js.map +1 -0
- package/dist/src/dispute/cascade.d.ts +179 -0
- package/dist/src/dispute/cascade.d.ts.map +1 -0
- package/dist/src/dispute/cascade.js +315 -0
- package/dist/src/dispute/cascade.js.map +1 -0
- package/dist/src/dispute/client.d.ts +2 -1
- package/dist/src/dispute/client.d.ts.map +1 -1
- package/dist/src/dispute/client.js +12 -3
- package/dist/src/dispute/client.js.map +1 -1
- package/dist/src/dispute/dispute-service.d.ts +41 -1
- package/dist/src/dispute/dispute-service.d.ts.map +1 -1
- package/dist/src/dispute/dispute-service.js +147 -21
- package/dist/src/dispute/dispute-service.js.map +1 -1
- package/dist/src/dispute/index.d.ts +2 -0
- package/dist/src/dispute/index.d.ts.map +1 -1
- package/dist/src/dispute/index.js +2 -0
- package/dist/src/dispute/index.js.map +1 -1
- package/dist/src/dispute/invalidation.d.ts +266 -0
- package/dist/src/dispute/invalidation.d.ts.map +1 -0
- package/dist/src/dispute/invalidation.js +405 -0
- package/dist/src/dispute/invalidation.js.map +1 -0
- package/dist/src/dispute/types.d.ts +14 -0
- package/dist/src/dispute/types.d.ts.map +1 -1
- package/dist/src/dispute/types.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +7 -0
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +49 -5
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +45 -3
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +522 -5
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/matchmaking/aggregate-counts.d.ts +67 -0
- package/dist/src/matchmaking/aggregate-counts.d.ts.map +1 -0
- package/dist/src/matchmaking/aggregate-counts.js +60 -0
- package/dist/src/matchmaking/aggregate-counts.js.map +1 -0
- package/dist/src/matchmaking/index.d.ts +20 -0
- package/dist/src/matchmaking/index.d.ts.map +1 -0
- package/dist/src/matchmaking/index.js +20 -0
- package/dist/src/matchmaking/index.js.map +1 -0
- package/dist/src/matchmaking/module.d.ts +181 -0
- package/dist/src/matchmaking/module.d.ts.map +1 -0
- package/dist/src/matchmaking/module.js +221 -0
- package/dist/src/matchmaking/module.js.map +1 -0
- package/dist/src/matchmaking/protocols.d.ts +37 -0
- package/dist/src/matchmaking/protocols.d.ts.map +1 -0
- package/dist/src/matchmaking/protocols.js +42 -0
- package/dist/src/matchmaking/protocols.js.map +1 -0
- package/dist/src/matchmaking/provider-manager.d.ts +52 -0
- package/dist/src/matchmaking/provider-manager.d.ts.map +1 -0
- package/dist/src/matchmaking/provider-manager.js +74 -0
- package/dist/src/matchmaking/provider-manager.js.map +1 -0
- package/dist/src/matchmaking/query-handler.d.ts +34 -0
- package/dist/src/matchmaking/query-handler.d.ts.map +1 -0
- package/dist/src/matchmaking/query-handler.js +62 -0
- package/dist/src/matchmaking/query-handler.js.map +1 -0
- package/dist/src/matchmaking/query-transport.d.ts +180 -0
- package/dist/src/matchmaking/query-transport.d.ts.map +1 -0
- package/dist/src/matchmaking/query-transport.js +315 -0
- package/dist/src/matchmaking/query-transport.js.map +1 -0
- package/dist/src/matchmaking/seeker-manager.d.ts +39 -0
- package/dist/src/matchmaking/seeker-manager.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker-manager.js +49 -0
- package/dist/src/matchmaking/seeker-manager.js.map +1 -0
- package/dist/src/matchmaking/seeker-walk-client.d.ts +127 -0
- package/dist/src/matchmaking/seeker-walk-client.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker-walk-client.js +189 -0
- package/dist/src/matchmaking/seeker-walk-client.js.map +1 -0
- package/dist/src/matchmaking/traffic-validation.d.ts +128 -0
- package/dist/src/matchmaking/traffic-validation.d.ts.map +1 -0
- package/dist/src/matchmaking/traffic-validation.js +105 -0
- package/dist/src/matchmaking/traffic-validation.js.map +1 -0
- package/dist/src/network/network-manager-service.d.ts +4 -2
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +9 -3
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/protocol-client.d.ts +13 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +74 -2
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/reactivity/forwarder-host.d.ts +198 -0
- package/dist/src/reactivity/forwarder-host.d.ts.map +1 -0
- package/dist/src/reactivity/forwarder-host.js +355 -0
- package/dist/src/reactivity/forwarder-host.js.map +1 -0
- package/dist/src/reactivity/index.d.ts +19 -0
- package/dist/src/reactivity/index.d.ts.map +1 -0
- package/dist/src/reactivity/index.js +19 -0
- package/dist/src/reactivity/index.js.map +1 -0
- package/dist/src/reactivity/notify-transport.d.ts +70 -0
- package/dist/src/reactivity/notify-transport.d.ts.map +1 -0
- package/dist/src/reactivity/notify-transport.js +111 -0
- package/dist/src/reactivity/notify-transport.js.map +1 -0
- package/dist/src/reactivity/origination-manager.d.ts +110 -0
- package/dist/src/reactivity/origination-manager.d.ts.map +1 -0
- package/dist/src/reactivity/origination-manager.js +129 -0
- package/dist/src/reactivity/origination-manager.js.map +1 -0
- package/dist/src/reactivity/protocols.d.ts +43 -0
- package/dist/src/reactivity/protocols.d.ts.map +1 -0
- package/dist/src/reactivity/protocols.js +50 -0
- package/dist/src/reactivity/protocols.js.map +1 -0
- package/dist/src/reactivity/push-state-gossip.d.ts +132 -0
- package/dist/src/reactivity/push-state-gossip.d.ts.map +1 -0
- package/dist/src/reactivity/push-state-gossip.js +231 -0
- package/dist/src/reactivity/push-state-gossip.js.map +1 -0
- package/dist/src/reactivity/recover-transport.d.ts +167 -0
- package/dist/src/reactivity/recover-transport.d.ts.map +1 -0
- package/dist/src/reactivity/recover-transport.js +308 -0
- package/dist/src/reactivity/recover-transport.js.map +1 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.d.ts +142 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.d.ts.map +1 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.js +223 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.js.map +1 -0
- package/dist/src/reactivity/subscriber-registry.d.ts +47 -0
- package/dist/src/reactivity/subscriber-registry.d.ts.map +1 -0
- package/dist/src/reactivity/subscriber-registry.js +87 -0
- package/dist/src/reactivity/subscriber-registry.js.map +1 -0
- package/dist/src/reactivity/subscription-manager.d.ts +221 -0
- package/dist/src/reactivity/subscription-manager.d.ts.map +1 -0
- package/dist/src/reactivity/subscription-manager.js +302 -0
- package/dist/src/reactivity/subscription-manager.js.map +1 -0
- package/dist/src/reactivity/topic-bytes.d.ts +32 -0
- package/dist/src/reactivity/topic-bytes.d.ts.map +1 -0
- package/dist/src/reactivity/topic-bytes.js +34 -0
- package/dist/src/reactivity/topic-bytes.js.map +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +51 -23
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/service.d.ts +46 -1
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +79 -45
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/rpc-deadline.d.ts +37 -0
- package/dist/src/rpc-deadline.d.ts.map +1 -0
- package/dist/src/rpc-deadline.js +31 -0
- package/dist/src/rpc-deadline.js.map +1 -0
- package/dist/src/storage/block-storage.d.ts +2 -0
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +95 -2
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +25 -0
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.d.ts +53 -2
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +193 -9
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/sync/client.d.ts +4 -1
- package/dist/src/sync/client.d.ts.map +1 -1
- package/dist/src/sync/client.js +5 -2
- package/dist/src/sync/client.js.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts +219 -0
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/cohort-topic-mesh-harness.js +467 -0
- package/dist/src/testing/cohort-topic-mesh-harness.js.map +1 -0
- package/dist/src/testing/matchmaking-mesh-harness.d.ts +187 -0
- package/dist/src/testing/matchmaking-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/matchmaking-mesh-harness.js +358 -0
- package/dist/src/testing/matchmaking-mesh-harness.js.map +1 -0
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +23 -1
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/dist/src/testing/reactivity-mesh-harness.d.ts +298 -0
- package/dist/src/testing/reactivity-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/reactivity-mesh-harness.js +663 -0
- package/dist/src/testing/reactivity-mesh-harness.js.map +1 -0
- package/package.json +7 -4
- package/src/cluster/block-transfer-service.ts +133 -68
- package/src/cluster/client.ts +64 -45
- package/src/cluster/cluster-error.ts +64 -0
- package/src/cluster/cluster-repo.ts +405 -55
- package/src/cluster/commit-cert.ts +139 -0
- package/src/cluster/service.ts +116 -44
- package/src/cluster/spread-on-churn.ts +328 -285
- package/src/cohort-topic/bootstrap-evidence-builder.ts +122 -0
- package/src/cohort-topic/bootstrap-evidence-verifiers.ts +132 -0
- package/src/cohort-topic/bootstrap-parent-reference.ts +159 -0
- package/src/cohort-topic/change-bridge.ts +109 -0
- package/src/cohort-topic/cohort-gossip-driver.ts +144 -0
- package/src/cohort-topic/cohort-gossip-transport.ts +74 -0
- package/src/cohort-topic/fret-trust-anchor.ts +153 -0
- package/src/cohort-topic/host.ts +2175 -0
- package/src/cohort-topic/index.ts +13 -0
- package/src/cohort-topic/membership-publish-sink.ts +20 -0
- package/src/cohort-topic/membership-source.ts +68 -0
- package/src/cohort-topic/peer-codec.ts +31 -0
- package/src/cohort-topic/peer-sig.ts +86 -0
- package/src/cohort-topic/protocols.ts +71 -0
- package/src/cohort-topic/reactivity-membership-gate.ts +77 -0
- package/src/cohort-topic/size-estimator.ts +16 -0
- package/src/cohort-topic/stream-util.ts +87 -0
- package/src/cohort-topic/threshold-crypto.ts +239 -0
- package/src/cohort-topic/topic-router.ts +77 -0
- package/src/dispute/cascade.ts +517 -0
- package/src/dispute/client.ts +12 -2
- package/src/dispute/dispute-service.ts +171 -24
- package/src/dispute/index.ts +42 -0
- package/src/dispute/invalidation.ts +587 -0
- package/src/dispute/types.ts +14 -0
- package/src/index.ts +4 -0
- package/src/libp2p-key-network.ts +49 -6
- package/src/libp2p-node-base.ts +620 -12
- package/src/matchmaking/aggregate-counts.ts +104 -0
- package/src/matchmaking/index.ts +20 -0
- package/src/matchmaking/module.ts +363 -0
- package/src/matchmaking/protocols.ts +51 -0
- package/src/matchmaking/provider-manager.ts +95 -0
- package/src/matchmaking/query-handler.ts +88 -0
- package/src/matchmaking/query-transport.ts +483 -0
- package/src/matchmaking/seeker-manager.ts +64 -0
- package/src/matchmaking/seeker-walk-client.ts +293 -0
- package/src/matchmaking/traffic-validation.ts +195 -0
- package/src/network/network-manager-service.ts +9 -2
- package/src/protocol-client.ts +64 -3
- package/src/reactivity/forwarder-host.ts +438 -0
- package/src/reactivity/index.ts +19 -0
- package/src/reactivity/notify-transport.ts +144 -0
- package/src/reactivity/origination-manager.ts +192 -0
- package/src/reactivity/protocols.ts +61 -0
- package/src/reactivity/push-state-gossip.ts +291 -0
- package/src/reactivity/recover-transport.ts +408 -0
- package/src/reactivity/rotation-rereg-scheduler.ts +256 -0
- package/src/reactivity/subscriber-registry.ts +96 -0
- package/src/reactivity/subscription-manager.ts +450 -0
- package/src/reactivity/topic-bytes.ts +37 -0
- package/src/repo/client.ts +54 -23
- package/src/repo/service.ts +90 -42
- package/src/rpc-deadline.ts +45 -0
- package/src/storage/block-storage.ts +106 -3
- package/src/storage/i-block-storage.ts +27 -0
- package/src/storage/storage-repo.ts +209 -13
- package/src/sync/client.ts +5 -2
- package/src/testing/cohort-topic-mesh-harness.ts +613 -0
- package/src/testing/matchmaking-mesh-harness.ts +475 -0
- package/src/testing/mesh-harness.ts +22 -2
- package/src/testing/reactivity-mesh-harness.ts +922 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactivity — subscription manager (db-p2p, wires to the cohort-topic substrate).
|
|
3
|
+
*
|
|
4
|
+
* Drives a subscriber's lifecycle against the participant-facing {@link CohortTopicService}: register at
|
|
5
|
+
* cohort-topic tier **T3 (luxury)** with the reactivity `appPayload`, renew to keep the registration
|
|
6
|
+
* alive within its TTL (Edge 60 s / Core 90 s), and withdraw by ceasing renewal — all the cohort-topic
|
|
7
|
+
* standard (`docs/reactivity.md` §Subscription). The reactivity-specific shape lives in db-core: the
|
|
8
|
+
* tail-anchored `topicId = H(tailId ‖ "reactivity")`, the {@link SubscribeAppPayloadV1}, and the
|
|
9
|
+
* subscriber-side verify/deliver path ({@link ReactivitySubscriber}).
|
|
10
|
+
*
|
|
11
|
+
* Inbound notifications are handed to {@link ReactivitySubscriptionManager.onNotification}, which runs
|
|
12
|
+
* the db-core delivery path (verify against the cached tail-cohort `MembershipCertV1` with one
|
|
13
|
+
* fetch-and-retry, revision-contiguity, gap → backfill seam, `(collectionId, revision)` dedupe, surface).
|
|
14
|
+
* The notification transport (the reactivity application protocol that delivers `NotificationV1` frames
|
|
15
|
+
* to a subscriber's primary) is the sibling tickets' concern; this manager owns attach + delivery logic.
|
|
16
|
+
*/
|
|
17
|
+
import { Tier, reactivityTopicId, subscribeAppPayloadBytes, subscriberTtlForProfile, deltaMaxForProfile, createNotificationVerifier, createReactivitySubscriber, createBackfillRequester, createStickyCohortHintCache, createRejoinJitter, applyResumeReply, detectRotation, planReRegistration, bytesToB64url, } from "@optimystic/db-core";
|
|
18
|
+
import { RotationRedirectError } from "./recover-transport.js";
|
|
19
|
+
import { createLogger } from "../logger.js";
|
|
20
|
+
const log = createLogger("reactivity-subscription");
|
|
21
|
+
/** Wires one reactivity subscription to the cohort-topic substrate at tier T3. */
|
|
22
|
+
export class ReactivitySubscriptionManager {
|
|
23
|
+
service;
|
|
24
|
+
collectionId;
|
|
25
|
+
collectionIdB64;
|
|
26
|
+
tailIdAtAttach;
|
|
27
|
+
topicId;
|
|
28
|
+
ttlMs;
|
|
29
|
+
deltaMaxBytes;
|
|
30
|
+
lastKnownRev;
|
|
31
|
+
subscriber;
|
|
32
|
+
verifier;
|
|
33
|
+
options;
|
|
34
|
+
cohortHintCache;
|
|
35
|
+
clock;
|
|
36
|
+
tailIdAtAttachB64;
|
|
37
|
+
rejoinJitter;
|
|
38
|
+
/** Resolved ring coordinate signed into a {@link ResumeV1} (real coord, or the collectionId placeholder). */
|
|
39
|
+
subscriberCoord;
|
|
40
|
+
/** True iff {@link subscriberCoord} fell back to the collectionId placeholder (no real coord supplied). */
|
|
41
|
+
subscriberCoordIsFallback;
|
|
42
|
+
/** The successor tail a rotation has already been surfaced for, so the notice fires once per rotation. */
|
|
43
|
+
rotationHandledFor;
|
|
44
|
+
/** Memoized db-core backfill driver (built on first gap, once `this.subscriber` is assigned). */
|
|
45
|
+
backfillRequester;
|
|
46
|
+
handle;
|
|
47
|
+
constructor(options) {
|
|
48
|
+
this.options = options;
|
|
49
|
+
this.service = options.service;
|
|
50
|
+
this.collectionId = options.collectionId;
|
|
51
|
+
this.collectionIdB64 = bytesToB64url(options.collectionId);
|
|
52
|
+
this.tailIdAtAttach = options.tailIdAtAttach;
|
|
53
|
+
this.topicId = reactivityTopicId(options.tailIdAtAttach);
|
|
54
|
+
this.ttlMs = options.ttlMs ?? (options.profile !== undefined ? subscriberTtlForProfile(options.profile) : undefined) ?? DEFAULT_SUBSCRIBER_TTL_MS;
|
|
55
|
+
this.deltaMaxBytes = options.deltaMaxBytes ?? (options.profile !== undefined ? deltaMaxForProfile(options.profile) : DEFAULT_EDGE_SAFE_DELTA_MAX);
|
|
56
|
+
this.lastKnownRev = options.lastKnownRev ?? 0;
|
|
57
|
+
this.cohortHintCache = options.cohortHintCache ?? createStickyCohortHintCache();
|
|
58
|
+
this.clock = options.clock ?? (() => Date.now());
|
|
59
|
+
this.tailIdAtAttachB64 = bytesToB64url(options.tailIdAtAttach);
|
|
60
|
+
this.rejoinJitter = options.rejoinJitter ?? createRejoinJitter();
|
|
61
|
+
this.subscriberCoordIsFallback = options.subscriberCoord === undefined;
|
|
62
|
+
this.subscriberCoord = options.subscriberCoord ?? this.collectionIdB64;
|
|
63
|
+
// Verify against the tail cohort's membership cert (the verifier owns the one fetch-and-retry).
|
|
64
|
+
this.verifier = createNotificationVerifier({ verifier: this.service.verifier(), tier: Tier.T3 });
|
|
65
|
+
this.subscriber = createReactivitySubscriber({
|
|
66
|
+
collectionId: this.collectionIdB64,
|
|
67
|
+
verifier: this.verifier,
|
|
68
|
+
deliver: options.deliver,
|
|
69
|
+
// Bind the seam to a method so it resolves the (possibly transport-backed) driver lazily —
|
|
70
|
+
// `this.subscriber` is not yet assigned during this very call.
|
|
71
|
+
requestBackfill: (from, to) => this.onBackfillGap(from, to),
|
|
72
|
+
lastKnownRev: this.lastKnownRev,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The subscriber detected a revision gap. When a {@link ReactivitySubscriptionManagerOptions.backfillTransport}
|
|
77
|
+
* + signer are configured, drive the db-core {@link createBackfillRequester} (build → sign → send →
|
|
78
|
+
* replay reply through delivery → underflow escalation, built lazily once); otherwise fall back to the
|
|
79
|
+
* explicit {@link ReactivitySubscriptionManagerOptions.requestBackfill} callback (or no-op).
|
|
80
|
+
*/
|
|
81
|
+
onBackfillGap(from, to) {
|
|
82
|
+
const { backfillTransport, signBackfill } = this.options;
|
|
83
|
+
if (backfillTransport !== undefined && signBackfill !== undefined) {
|
|
84
|
+
if (this.backfillRequester === undefined) {
|
|
85
|
+
this.backfillRequester = createBackfillRequester({
|
|
86
|
+
collectionId: this.collectionIdB64,
|
|
87
|
+
sign: signBackfill,
|
|
88
|
+
transport: backfillTransport,
|
|
89
|
+
subscriber: this.subscriber,
|
|
90
|
+
clock: this.clock,
|
|
91
|
+
onUnderflow: this.options.onBackfillUnderflow,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// Fire-and-forget off the gap seam (NOT the deliver path — backfill is hint-only and must never
|
|
95
|
+
// block or fault commit/delivery). The driver resolves (no throw) on an `available`-window
|
|
96
|
+
// underflow — that path is handled by `onBackfillUnderflow`; only a genuine **transport failure**
|
|
97
|
+
// rejects, which escalates here. `escalateBackfill` never rejects, so nothing leaks as an
|
|
98
|
+
// unhandled rejection.
|
|
99
|
+
void this.backfillRequester(from, to).catch(() => { void this.escalateBackfill(from, to); });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.options.requestBackfill?.(from, to);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A backfill RPC failed at the transport (the sticky-hint dial + cohort-walk fallback inside the
|
|
106
|
+
* transport were already exhausted). Re-attempt up to {@link ReactivitySubscriptionManagerOptions.backfillMaxRetries}
|
|
107
|
+
* times, then escalate to {@link resume} (when a resume transport is configured) and finally to
|
|
108
|
+
* {@link ReactivitySubscriptionManagerOptions.onChainRead}. Never rejects (it runs detached off the gap
|
|
109
|
+
* seam) and never touches the commit/delivery path.
|
|
110
|
+
*/
|
|
111
|
+
async escalateBackfill(from, to) {
|
|
112
|
+
const max = this.options.backfillMaxRetries ?? DEFAULT_BACKFILL_MAX_RETRIES;
|
|
113
|
+
for (let attempt = 1; attempt <= max; attempt++) {
|
|
114
|
+
try {
|
|
115
|
+
await this.backfillRequester(from, to);
|
|
116
|
+
return; // a re-attempt closed (or underflow-escalated) the gap
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (err instanceof RotationRedirectError) {
|
|
120
|
+
// The serving cohort's outgoing tail rotated: move to the new tree (no chain-read fallback).
|
|
121
|
+
this.honorRotationRedirect(err);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
log("backfill retry %d/%d for [%d,%d] failed: %o", attempt, max, from, to, err);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Still failing after the bounded retries: fall back to a resume (a wider recovery window) when one is
|
|
128
|
+
// wired, else signal a chain read. Distinct from the underflow seam, which carries the held window.
|
|
129
|
+
if (this.options.resumeTransport !== undefined && this.options.signResume !== undefined) {
|
|
130
|
+
try {
|
|
131
|
+
await this.resume();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
log("backfill escalation to resume() failed for [%d,%d]: %o", from, to, err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.options.onChainRead?.(undefined, undefined);
|
|
139
|
+
}
|
|
140
|
+
/** The live registration handle, or `undefined` before the first {@link register}. */
|
|
141
|
+
get registration() {
|
|
142
|
+
return this.handle;
|
|
143
|
+
}
|
|
144
|
+
/** Last contiguously-delivered revision. */
|
|
145
|
+
get lastRevision() {
|
|
146
|
+
return this.subscriber.lastRevision;
|
|
147
|
+
}
|
|
148
|
+
/** Register the subscriber at tier T3 with the reactivity `appPayload`. */
|
|
149
|
+
async register() {
|
|
150
|
+
const appPayload = subscribeAppPayloadBytes({
|
|
151
|
+
collectionId: bytesToB64url(this.collectionId),
|
|
152
|
+
tailIdAtAttach: bytesToB64url(this.tailIdAtAttach),
|
|
153
|
+
lastKnownRev: this.lastKnownRev,
|
|
154
|
+
deltaMaxBytes: this.deltaMaxBytes,
|
|
155
|
+
});
|
|
156
|
+
this.handle = await this.service.register({
|
|
157
|
+
topicId: this.topicId,
|
|
158
|
+
tier: Tier.T3,
|
|
159
|
+
appPayload,
|
|
160
|
+
ttl: this.ttlMs,
|
|
161
|
+
});
|
|
162
|
+
return this.handle;
|
|
163
|
+
}
|
|
164
|
+
/** Run one renewal cycle (keep-alive touch). No-op before the first {@link register}. */
|
|
165
|
+
async renew() {
|
|
166
|
+
if (this.handle === undefined) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
await this.service.renew(this.handle);
|
|
170
|
+
}
|
|
171
|
+
/** Withdraw: stop renewing and send a best-effort signed tombstone so the cohort frees the
|
|
172
|
+
* registration immediately (TTL expiry remains the fallback if the primary is unreachable). */
|
|
173
|
+
async withdraw() {
|
|
174
|
+
if (this.handle !== undefined) {
|
|
175
|
+
await this.service.withdraw(this.handle);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Resume after a sleep/flap (`docs/reactivity.md` §Resume). Sends one {@link ResumeV1} from
|
|
180
|
+
* `lastRevision + 1` to the serving cohort over the injected {@link ResumeTransport} and applies the
|
|
181
|
+
* classified reply via the db-core {@link applyResumeReply}: a `backfill` / `checkpoint_window` reply
|
|
182
|
+
* replays its entries through the delivery path (verified, deduped); `out_of_window` and an untrusted
|
|
183
|
+
* checkpoint escalate to {@link ReactivitySubscriptionManagerOptions.onChainRead}; `tail_rotated`
|
|
184
|
+
* escalates to {@link ReactivitySubscriptionManagerOptions.onTailRotated} and invalidates the sticky
|
|
185
|
+
* cohort-hint cache (the cached primary is under the old tree). Throws if no resume transport/signer
|
|
186
|
+
* was configured.
|
|
187
|
+
*
|
|
188
|
+
* The sticky cohort-hint cache (Edge) lets a resume after a brief flap dial the cached primary directly
|
|
189
|
+
* for a one-RT recovery instead of re-walking from `d_max`; it is the transport's to consult via
|
|
190
|
+
* {@link cohortHint}.
|
|
191
|
+
*/
|
|
192
|
+
async resume() {
|
|
193
|
+
const { resumeTransport, signResume } = this.options;
|
|
194
|
+
if (resumeTransport === undefined || signResume === undefined) {
|
|
195
|
+
throw new Error("ReactivitySubscriptionManager.resume: no resumeTransport/signResume configured");
|
|
196
|
+
}
|
|
197
|
+
if (this.subscriberCoordIsFallback) {
|
|
198
|
+
log("resume: no real ring coordinate supplied; signing ResumeV1 with the collectionId as a placeholder subscriberCoord (collection=%s)", this.collectionIdB64);
|
|
199
|
+
}
|
|
200
|
+
const unsigned = {
|
|
201
|
+
v: 1,
|
|
202
|
+
collectionId: this.collectionIdB64,
|
|
203
|
+
fromRevision: this.subscriber.lastRevision + 1,
|
|
204
|
+
latestKnownTailId: bytesToB64url(this.tailIdAtAttach),
|
|
205
|
+
subscriberCoord: this.subscriberCoord,
|
|
206
|
+
timestamp: this.clock(),
|
|
207
|
+
};
|
|
208
|
+
const req = { ...unsigned, signature: signResume(unsigned) };
|
|
209
|
+
let reply;
|
|
210
|
+
try {
|
|
211
|
+
reply = await resumeTransport(req);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
if (err instanceof RotationRedirectError) {
|
|
215
|
+
// The resume reached the serving cohort's outgoing (draining) tail: honor the redirect (surface
|
|
216
|
+
// the rotation through onRotation, invalidate the sticky cache) and resolve as a tail rotation —
|
|
217
|
+
// never throw the redirect out to the caller / the gap seam's commit-delivery path.
|
|
218
|
+
this.honorRotationRedirect(err);
|
|
219
|
+
return "tail_rotated";
|
|
220
|
+
}
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
return applyResumeReply(reply, {
|
|
224
|
+
subscriber: this.subscriber,
|
|
225
|
+
verifier: this.verifier,
|
|
226
|
+
onCheckpointDigest: this.options.onCheckpointDigest,
|
|
227
|
+
onChainRead: this.options.onChainRead,
|
|
228
|
+
onTailRotated: (newTailId, newRevisionAtRotation) => {
|
|
229
|
+
// The cached primary is under the now-stale tree; drop it so the re-registration re-walks.
|
|
230
|
+
this.cohortHintCache.invalidate(this.collectionIdB64);
|
|
231
|
+
this.options.onTailRotated?.(newTailId, newRevisionAtRotation);
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** The sticky cohort-hint cache backing one-RT resume after a flap (Edge). */
|
|
236
|
+
get cohortHint() {
|
|
237
|
+
return this.cohortHintCache;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Run the db-core delivery path for one inbound notification, then check for tail rotation
|
|
241
|
+
* (`docs/reactivity.md` §Tail rotation): a delivered `tailId` that differs from `tailIdAtAttach`, or a
|
|
242
|
+
* `rotationHint` pre-announce, invalidates the sticky cohort-hint cache (the cached primary is under the
|
|
243
|
+
* old tree) and surfaces a jittered re-registration plan via {@link ReactivitySubscriptionManagerOptions.onRotation}.
|
|
244
|
+
* Fired at most once per successor tail.
|
|
245
|
+
*/
|
|
246
|
+
async onNotification(n) {
|
|
247
|
+
const outcome = await this.subscriber.onNotification(n);
|
|
248
|
+
this.checkRotation(n);
|
|
249
|
+
return outcome;
|
|
250
|
+
}
|
|
251
|
+
/** Detect a tail rotation from an inbound notification and surface it once per successor tail. */
|
|
252
|
+
checkRotation(n) {
|
|
253
|
+
const detection = detectRotation(this.tailIdAtAttachB64, n);
|
|
254
|
+
if (!detection.rotated || detection.newTailId === undefined) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
this.surfaceRotation(detection.newTailId, detection.preAnnounced);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Surface a rotation to the host **once per successor tail** (`docs/reactivity.md` §Tail rotation):
|
|
261
|
+
* invalidate the sticky cohort-hint cache (the cached primary is under the now-stale tree, so a later
|
|
262
|
+
* resume re-walks) and — when an {@link ReactivitySubscriptionManagerOptions.onRotation} observer is
|
|
263
|
+
* configured — hand it a jittered re-registration plan carrying `lastRevision` (continuous across the
|
|
264
|
+
* rotation). The single seam both the notification-driven detection ({@link checkRotation}) and the
|
|
265
|
+
* recover-driven {@link RotationRedirectError} ({@link honorRotationRedirect}) end in; the
|
|
266
|
+
* {@link rotationHandledFor} guard self-corrects across a chained OLD→A→B rotation.
|
|
267
|
+
*/
|
|
268
|
+
surfaceRotation(newTailId, preAnnounced) {
|
|
269
|
+
if (newTailId === this.rotationHandledFor) {
|
|
270
|
+
return; // already surfaced this successor
|
|
271
|
+
}
|
|
272
|
+
this.rotationHandledFor = newTailId;
|
|
273
|
+
// The cached primary is under the now-stale tree; drop it so the re-registration re-walks.
|
|
274
|
+
this.cohortHintCache.invalidate(this.collectionIdB64);
|
|
275
|
+
if (this.options.onRotation === undefined) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const plan = planReRegistration({
|
|
279
|
+
hint: { newTailId },
|
|
280
|
+
lastRevision: this.subscriber.lastRevision,
|
|
281
|
+
now: this.clock(),
|
|
282
|
+
jitter: this.rejoinJitter,
|
|
283
|
+
});
|
|
284
|
+
this.options.onRotation({ newTailId, preAnnounced, plan });
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Honor a recover-surfaced {@link RotationRedirectError}: the serving cohort's outgoing tail rotated and
|
|
288
|
+
* bounced this request to the new tree. Route it through the **same** {@link surfaceRotation} seam a
|
|
289
|
+
* delivered pre-announce uses (`preAnnounced: false`), so both the notify-driven and recover-driven
|
|
290
|
+
* rotation paths converge on one `RotationNotice` for the host's re-registration scheduler to consume.
|
|
291
|
+
*/
|
|
292
|
+
honorRotationRedirect(err) {
|
|
293
|
+
this.surfaceRotation(err.redirect.newTailId, false);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/** Default application-level backfill re-attempts after a transport failure before escalating to resume/chain. */
|
|
297
|
+
const DEFAULT_BACKFILL_MAX_RETRIES = 1;
|
|
298
|
+
/** Fallback subscriber TTL when neither `ttlMs` nor `profile` is supplied (Core default). */
|
|
299
|
+
const DEFAULT_SUBSCRIBER_TTL_MS = 90_000;
|
|
300
|
+
/** Edge-safe delta budget when neither `deltaMaxBytes` nor `profile` is supplied: decline deltas. */
|
|
301
|
+
const DEFAULT_EDGE_SAFE_DELTA_MAX = 0;
|
|
302
|
+
//# sourceMappingURL=subscription-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-manager.js","sourceRoot":"","sources":["../../../src/reactivity/subscription-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactivity — the one pinned `BlockId` → raw tail-bytes encoding, shared by origination and subscription.
|
|
3
|
+
*
|
|
4
|
+
* `reactivityTopicId` (db-core) hashes `H(tailBytes ‖ "reactivity")` to derive the topic's `coord_0`
|
|
5
|
+
* cohort. Origination (the cohort-change membership gate, {@link
|
|
6
|
+
* import("../cohort-topic/reactivity-membership-gate.js").createReactivitySelfMembershipGate}) and the
|
|
7
|
+
* subscriber side (the production subscribe factory that converts a `BlockId` `tailIdAtAttach` to the bytes
|
|
8
|
+
* {@link import("./subscription-manager.js").ReactivitySubscriptionManager} feeds `reactivityTopicId`) MUST
|
|
9
|
+
* feed it the **same** bytes for a given tail, or they resolve different coords and origination silently
|
|
10
|
+
* never reaches subscribers (green tests, dead feature).
|
|
11
|
+
*
|
|
12
|
+
* This module is that single source of truth: `reactivityTailBytes(tailId) = TextEncoder().encode(tailId)`,
|
|
13
|
+
* the synchronous block-id→bytes convention the rest of db-p2p already uses for ring hashing of tail ids
|
|
14
|
+
* (`cluster/client.ts`, `repo/client.ts`). db-core's async `blockIdToBytes` (which `sha256`s the utf8 bytes
|
|
15
|
+
* first) is deliberately NOT used: it would (a) double-hash relative to the spec's `H(tailId ‖ "reactivity")`
|
|
16
|
+
* and (b) force the synchronous origination gate to become async.
|
|
17
|
+
*
|
|
18
|
+
* It lives in the reactivity surface (not buried in the gate) so the subscribe path and the gate import the
|
|
19
|
+
* exact same function rather than re-deriving the encoding independently. The
|
|
20
|
+
* `cohort-topic/reactivity-membership-gate.ts` module re-exports it for its existing callers.
|
|
21
|
+
*/
|
|
22
|
+
import type { BlockId } from "@optimystic/db-core";
|
|
23
|
+
/**
|
|
24
|
+
* The pinned `BlockId` → raw tail bytes encoding fed into `reactivityTopicId`: the **raw** utf8 bytes of the
|
|
25
|
+
* tail block-id string (NOT a pre-hashed routing key, NOT db-core's double-hashing `blockIdToBytes`).
|
|
26
|
+
*
|
|
27
|
+
* Load-bearing: origination and the subscriber side must call this **same** function for a given tail (see
|
|
28
|
+
* the module doc) — a mismatch resolves different `coord_0`s and origination silently never reaches
|
|
29
|
+
* subscribers. The `topic-bytes-encoding` spec pins the coord-equality both ways.
|
|
30
|
+
*/
|
|
31
|
+
export declare function reactivityTailBytes(tailId: BlockId): Uint8Array;
|
|
32
|
+
//# sourceMappingURL=topic-bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topic-bytes.d.ts","sourceRoot":"","sources":["../../../src/reactivity/topic-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAInD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,CAE/D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactivity — the one pinned `BlockId` → raw tail-bytes encoding, shared by origination and subscription.
|
|
3
|
+
*
|
|
4
|
+
* `reactivityTopicId` (db-core) hashes `H(tailBytes ‖ "reactivity")` to derive the topic's `coord_0`
|
|
5
|
+
* cohort. Origination (the cohort-change membership gate, {@link
|
|
6
|
+
* import("../cohort-topic/reactivity-membership-gate.js").createReactivitySelfMembershipGate}) and the
|
|
7
|
+
* subscriber side (the production subscribe factory that converts a `BlockId` `tailIdAtAttach` to the bytes
|
|
8
|
+
* {@link import("./subscription-manager.js").ReactivitySubscriptionManager} feeds `reactivityTopicId`) MUST
|
|
9
|
+
* feed it the **same** bytes for a given tail, or they resolve different coords and origination silently
|
|
10
|
+
* never reaches subscribers (green tests, dead feature).
|
|
11
|
+
*
|
|
12
|
+
* This module is that single source of truth: `reactivityTailBytes(tailId) = TextEncoder().encode(tailId)`,
|
|
13
|
+
* the synchronous block-id→bytes convention the rest of db-p2p already uses for ring hashing of tail ids
|
|
14
|
+
* (`cluster/client.ts`, `repo/client.ts`). db-core's async `blockIdToBytes` (which `sha256`s the utf8 bytes
|
|
15
|
+
* first) is deliberately NOT used: it would (a) double-hash relative to the spec's `H(tailId ‖ "reactivity")`
|
|
16
|
+
* and (b) force the synchronous origination gate to become async.
|
|
17
|
+
*
|
|
18
|
+
* It lives in the reactivity surface (not buried in the gate) so the subscribe path and the gate import the
|
|
19
|
+
* exact same function rather than re-deriving the encoding independently. The
|
|
20
|
+
* `cohort-topic/reactivity-membership-gate.ts` module re-exports it for its existing callers.
|
|
21
|
+
*/
|
|
22
|
+
const utf8 = new TextEncoder();
|
|
23
|
+
/**
|
|
24
|
+
* The pinned `BlockId` → raw tail bytes encoding fed into `reactivityTopicId`: the **raw** utf8 bytes of the
|
|
25
|
+
* tail block-id string (NOT a pre-hashed routing key, NOT db-core's double-hashing `blockIdToBytes`).
|
|
26
|
+
*
|
|
27
|
+
* Load-bearing: origination and the subscriber side must call this **same** function for a given tail (see
|
|
28
|
+
* the module doc) — a mismatch resolves different `coord_0`s and origination silently never reaches
|
|
29
|
+
* subscribers. The `topic-bytes-encoding` spec pins the coord-equality both ways.
|
|
30
|
+
*/
|
|
31
|
+
export function reactivityTailBytes(tailId) {
|
|
32
|
+
return utf8.encode(tailId);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=topic-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topic-bytes.js","sourceRoot":"","sources":["../../../src/reactivity/topic-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe;IAClD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/repo/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAC7F,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAC3D,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/repo/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAC7F,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAC3D,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,qBAAa,UAAW,SAAQ,cAAe,YAAW,KAAK;IACC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM;IAA/F,OAAO;IAIP,mCAAmC;WACrB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU;IAI9F,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAO5E,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC;IAOxF,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAOpF,OAAO,CAAC,oBAAoB;YASd,kBAAkB;YAkElB,wBAAwB;YA6BxB,kCAAkC;CAQhD"}
|
package/dist/src/repo/client.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { blockIdsForTransforms, blockIdToBytes } from "@optimystic/db-core";
|
|
1
2
|
import { ProtocolClient } from "../protocol-client.js";
|
|
2
3
|
import { peerIdFromString } from "@libp2p/peer-id";
|
|
3
4
|
export class RepoClient extends ProtocolClient {
|
|
@@ -41,20 +42,36 @@ export class RepoClient extends ProtocolClient {
|
|
|
41
42
|
};
|
|
42
43
|
const correlationId = this.extractCorrelationId(operations);
|
|
43
44
|
const deadline = options.expiration ?? (Date.now() + 30_000);
|
|
44
|
-
const
|
|
45
|
-
const withTimeout = async (fn) => {
|
|
46
|
-
return await Promise.race([
|
|
47
|
-
fn(),
|
|
48
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('RepoClient timeout')), msLeft))
|
|
49
|
-
]);
|
|
50
|
-
};
|
|
51
|
-
let response;
|
|
45
|
+
const deadlineMs = Math.max(1, deadline - Date.now());
|
|
52
46
|
const preferred = (this.protocolPrefix ?? '/db-p2p') + '/repo/1.0.0';
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
// Drive the remaining `expiration` budget through an AbortController whose
|
|
48
|
+
// abort *reason* is the caller-facing `'RepoClient timeout'` Error, combined
|
|
49
|
+
// with any caller signal. processMessage forwards `signal` to both the dial
|
|
50
|
+
// and the response-read and calls `stream.abort(signal.reason)` on abort, so —
|
|
51
|
+
// unlike the old `Promise.race`, whose losing branch left the inner read
|
|
52
|
+
// running and leaked a pending read + stream on every timed-out RPC to a silent
|
|
53
|
+
// peer — the deadline now genuinely cancels the inner read while the caller
|
|
54
|
+
// still observes an error whose `.message === 'RepoClient timeout'`.
|
|
55
|
+
//
|
|
56
|
+
// Intentionally no `responseTimeoutMs`: the combined signal already bounds the
|
|
57
|
+
// read at `deadlineMs`. A second, shorter cap would surface as
|
|
58
|
+
// ResponseTimeoutError and mask the caller-facing 'RepoClient timeout' message.
|
|
59
|
+
const deadlineController = new AbortController();
|
|
60
|
+
const timer = setTimeout(() => deadlineController.abort(new Error('RepoClient timeout')), deadlineMs);
|
|
61
|
+
const combinedSignal = options?.signal
|
|
62
|
+
? AbortSignal.any([options.signal, deadlineController.signal])
|
|
63
|
+
: deadlineController.signal;
|
|
64
|
+
let response;
|
|
65
|
+
try {
|
|
66
|
+
response = await super.processMessage(message, preferred, {
|
|
67
|
+
signal: combinedSignal,
|
|
68
|
+
correlationId,
|
|
69
|
+
dialTimeoutMs: options?.dialTimeoutMs,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
}
|
|
58
75
|
if (response?.redirect?.peers?.length) {
|
|
59
76
|
if (hop >= 2) {
|
|
60
77
|
throw new Error('Redirect loop detected in RepoClient (max hops reached)');
|
|
@@ -65,35 +82,46 @@ export class RepoClient extends ProtocolClient {
|
|
|
65
82
|
if (next.id === currentIdStr) {
|
|
66
83
|
throw new Error('Redirect loop detected in RepoClient (same peer)');
|
|
67
84
|
}
|
|
68
|
-
// cache hint
|
|
69
|
-
|
|
85
|
+
// cache hint — await so the recorded key bytes match what findCoordinator
|
|
86
|
+
// later looks up (blockIdToBytes is async); deterministic ordering also
|
|
87
|
+
// keeps the hint testable. The redirect retry below is async anyway.
|
|
88
|
+
await this.recordCoordinatorForOpsIfSupported(operations, nextId);
|
|
70
89
|
// single-hop retry against target peer using repo protocol
|
|
71
90
|
const nextClient = RepoClient.create(nextId, this.peerNetwork, this.protocolPrefix);
|
|
72
91
|
return await nextClient.processRepoMessage(operations, options, hop + 1);
|
|
73
92
|
}
|
|
74
93
|
return response;
|
|
75
94
|
}
|
|
76
|
-
extractKeyFromOperations(ops) {
|
|
95
|
+
async extractKeyFromOperations(ops) {
|
|
77
96
|
const op = ops[0];
|
|
97
|
+
// The recorded key MUST be the sha256 digest produced by blockIdToBytes — the
|
|
98
|
+
// exact bytes findCoordinator/recordCoordinator key the coordinator cache on
|
|
99
|
+
// (NetworkTransactor passes blockIdToBytes(blockId)). Raw utf8 of the id would
|
|
100
|
+
// never match, so the hint would silently never be retrieved.
|
|
78
101
|
if ('get' in op) {
|
|
79
102
|
const id = op.get.blockIds[0];
|
|
80
|
-
return id ?
|
|
103
|
+
return id ? await blockIdToBytes(id) : undefined;
|
|
81
104
|
}
|
|
82
105
|
if ('pend' in op) {
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
// Key on a real block id the pend touches, NOT a structural transforms field
|
|
107
|
+
// name ('inserts'/'updates'/'deletes'); see RepoService.deriveBlockKey.
|
|
108
|
+
const id = blockIdsForTransforms(op.pend.transforms)[0];
|
|
109
|
+
return id ? await blockIdToBytes(id) : undefined;
|
|
85
110
|
}
|
|
86
111
|
if ('commit' in op) {
|
|
87
|
-
|
|
112
|
+
// Anchor on blockIds[0] (where CoordinatorRepo.commit runs consensus +
|
|
113
|
+
// verifyResponsibility), NOT tailId — they differ for a non-tail batch.
|
|
114
|
+
const id = op.commit.blockIds[0];
|
|
115
|
+
return id ? await blockIdToBytes(id) : undefined;
|
|
88
116
|
}
|
|
89
117
|
if ('cancel' in op) {
|
|
90
118
|
const id = op.cancel.actionRef.blockIds[0];
|
|
91
|
-
return id ?
|
|
119
|
+
return id ? await blockIdToBytes(id) : undefined;
|
|
92
120
|
}
|
|
93
121
|
return undefined;
|
|
94
122
|
}
|
|
95
|
-
recordCoordinatorForOpsIfSupported(ops, peerId) {
|
|
96
|
-
const keyBytes = this.extractKeyFromOperations(ops);
|
|
123
|
+
async recordCoordinatorForOpsIfSupported(ops, peerId) {
|
|
124
|
+
const keyBytes = await this.extractKeyFromOperations(ops);
|
|
97
125
|
const pn = this.peerNetwork;
|
|
98
126
|
if (keyBytes != null && typeof pn?.recordCoordinator === 'function') {
|
|
99
127
|
pn.recordCoordinator(keyBytes, peerId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/repo/client.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,OAAO,UAAW,SAAQ,cAAc;IAC2B;IAAxE,YAAoB,MAAc,EAAE,WAAyB,EAAW,cAAuB;QAC9F,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAD4C,mBAAc,GAAd,cAAc,CAAS;IAE/F,CAAC;IAED,mCAAmC;IAC5B,MAAM,CAAC,MAAM,CAAC,MAAc,EAAE,WAAyB,EAAE,cAAuB;QACtF,OAAO,IAAI,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAoB,EAAE,OAAuB;QACtD,OAAO,IAAI,CAAC,kBAAkB,CAC7B,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EACpB,OAAO,CACP,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAoB,EAAE,OAAuB;QACvD,OAAO,IAAI,CAAC,kBAAkB,CAC7B,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACnB,OAAO,CACP,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAuB,EAAE,OAAuB;QAC5D,OAAO,IAAI,CAAC,kBAAkB,CAC7B,CAAC,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,EAC3B,OAAO,CACP,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAsB,EAAE,OAAuB;QAC3D,OAAO,IAAI,CAAC,kBAAkB,CAC7B,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EACrB,OAAO,CACP,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,UAAqC;QACjE,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,EAAE;YAAE,OAAO,SAAS,CAAC;QAC1B,IAAI,MAAM,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC1C,IAAI,QAAQ,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC9C,IAAI,QAAQ,IAAI,EAAE;YAAE,OAAO,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QACxD,OAAO,SAAS,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC/B,UAAqC,EACrC,OAAuB,EACvB,MAAc,CAAC;QAEf,MAAM,OAAO,GAAgB;YAC5B,UAAU;YACV,UAAU,EAAE,OAAO,CAAC,UAAU;SAC9B,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,CAAA;QAC5D,MAAM,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/repo/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Startable, Logger, StreamHandler, PeerId } from '@libp2p/interface';
|
|
1
|
+
import type { Startable, Logger, StreamHandler, PeerId, Libp2p } from '@libp2p/interface';
|
|
2
2
|
import type { IRepo, RepoMessage } from '@optimystic/db-core';
|
|
3
3
|
import { type RedirectPayload } from './redirect.js';
|
|
4
4
|
interface BaseComponents {
|
|
@@ -18,6 +18,13 @@ export type RepoServiceComponents = BaseComponents & {
|
|
|
18
18
|
networkManager?: NetworkManagerLike;
|
|
19
19
|
peerId?: PeerId;
|
|
20
20
|
getConnectionAddrs?: (peerId: PeerId) => string[];
|
|
21
|
+
/**
|
|
22
|
+
* Optional libp2p node. The production wiring injects the node post-construction
|
|
23
|
+
* via {@link RepoService.setLibp2p} (the `components.libp2p` proxy does not
|
|
24
|
+
* reliably resolve from inside a service at request time); this field is a
|
|
25
|
+
* best-effort fallback resolver used only when no node has been injected.
|
|
26
|
+
*/
|
|
27
|
+
libp2p?: Libp2p;
|
|
21
28
|
};
|
|
22
29
|
export type RepoServiceInit = {
|
|
23
30
|
protocol?: string;
|
|
@@ -50,8 +57,23 @@ export declare class RepoService implements Startable {
|
|
|
50
57
|
private running;
|
|
51
58
|
/** Responsibility K - how many peers are responsible for a key (for redirect decisions) */
|
|
52
59
|
private readonly responsibilityK;
|
|
60
|
+
/**
|
|
61
|
+
* The libp2p node, injected post-construction by the node wiring (see
|
|
62
|
+
* libp2p-node-base.ts, mirroring how `networkManager`/`fret` receive theirs).
|
|
63
|
+
* The libp2p `components.libp2p` proxy does NOT reliably resolve from inside a
|
|
64
|
+
* service at request time, so the redirect path resolves the network manager,
|
|
65
|
+
* self identity, and connection addrs through this explicitly-set reference.
|
|
66
|
+
*/
|
|
67
|
+
private libp2pRef;
|
|
53
68
|
constructor(components: RepoServiceComponents, init?: RepoServiceInit);
|
|
54
69
|
readonly [Symbol.toStringTag] = "@libp2p/repo-service";
|
|
70
|
+
/**
|
|
71
|
+
* Inject the running libp2p node. Called once post-construction by the node
|
|
72
|
+
* wiring so the redirect path can resolve the network manager / self id / addrs.
|
|
73
|
+
*/
|
|
74
|
+
setLibp2p(libp2p: Libp2p): void;
|
|
75
|
+
/** Resolve the libp2p node: the injected ref first, then the (best-effort) components proxy. */
|
|
76
|
+
private getLibp2p;
|
|
55
77
|
/**
|
|
56
78
|
* Start the service
|
|
57
79
|
*/
|
|
@@ -63,6 +85,29 @@ export declare class RepoService implements Startable {
|
|
|
63
85
|
private getNetworkManager;
|
|
64
86
|
private getSelfId;
|
|
65
87
|
private getPeerAddrs;
|
|
88
|
+
/**
|
|
89
|
+
* Derive the redirect routing key and op name for a single operation.
|
|
90
|
+
*
|
|
91
|
+
* The key MUST be the block the corresponding handler actually coordinates and
|
|
92
|
+
* verifies responsibility on, so redirect routing stays consistent with where the
|
|
93
|
+
* op is executed:
|
|
94
|
+
* - get → blockIds[0]
|
|
95
|
+
* - pend → blockIdsForTransforms(transforms)[0]
|
|
96
|
+
* - cancel → actionRef.blockIds[0]
|
|
97
|
+
* - commit → blockIds[0] (CoordinatorRepo.commit anchors consensus on
|
|
98
|
+
* getClusterSize(blockIds[0]) / executeClusterTransaction(blockIds[0]) and guards
|
|
99
|
+
* with verifyResponsibility(blockIds) — NOT tailId; for a per-block commit batch
|
|
100
|
+
* whose blockIds[0] !== tailId, keying on tailId redirected the commit to the
|
|
101
|
+
* collection tail's cluster, which then fails verifyResponsibility for the non-tail block.)
|
|
102
|
+
*
|
|
103
|
+
* Returns blockKey === undefined when the op carries no routable key (e.g. a cancel
|
|
104
|
+
* with an empty blockIds list), in which case the caller handles it locally without a
|
|
105
|
+
* redirect check.
|
|
106
|
+
*/
|
|
107
|
+
deriveBlockKey(operation: RepoMessage['operations'][number]): {
|
|
108
|
+
blockKey: string | undefined;
|
|
109
|
+
opName: string;
|
|
110
|
+
};
|
|
66
111
|
/**
|
|
67
112
|
* Check if this node should redirect the request for a given key.
|
|
68
113
|
* Returns a RedirectPayload if not responsible, null if should handle locally.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAsB,aAAa,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"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"}
|