@earendil-works/chord 1.3.0 → 1.5.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/CHANGELOG.md +54 -0
- package/README.md +129 -10
- package/dist/cell.d.ts +7 -7
- package/dist/cell.d.ts.map +1 -1
- package/dist/cell.js.map +1 -1
- package/dist/context/index.d.ts +8 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +15 -0
- package/dist/context/index.js.map +1 -1
- package/dist/contract.d.ts +51 -52
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +19 -24
- package/dist/contract.js.map +1 -1
- package/dist/delta/apply-immutable-trusted.js +3 -4
- package/dist/delta/apply-immutable-trusted.js.map +1 -1
- package/dist/delta/diff.d.ts.map +1 -1
- package/dist/delta/diff.js +5 -3
- package/dist/delta/diff.js.map +1 -1
- package/dist/delta/index.d.ts +9 -1
- package/dist/delta/index.d.ts.map +1 -1
- package/dist/delta/index.js +15 -11
- package/dist/delta/index.js.map +1 -1
- package/dist/delta/pending.d.ts +36 -0
- package/dist/delta/pending.d.ts.map +1 -0
- package/dist/delta/pending.js +143 -0
- package/dist/delta/pending.js.map +1 -0
- package/dist/delta/tracker.d.ts +12 -0
- package/dist/delta/tracker.d.ts.map +1 -1
- package/dist/delta/tracker.js +109 -39
- package/dist/delta/tracker.js.map +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +9 -7
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/next/contracts/accepts.d.ts +81 -0
- package/dist/next/contracts/accepts.d.ts.map +1 -0
- package/dist/next/contracts/accepts.js +123 -0
- package/dist/next/contracts/accepts.js.map +1 -0
- package/dist/next/contracts/contract.d.ts +121 -0
- package/dist/next/contracts/contract.d.ts.map +1 -0
- package/dist/next/contracts/contract.js +50 -0
- package/dist/next/contracts/contract.js.map +1 -0
- package/dist/next/contracts/declare.d.ts +107 -0
- package/dist/next/contracts/declare.d.ts.map +1 -0
- package/dist/next/contracts/declare.js +136 -0
- package/dist/next/contracts/declare.js.map +1 -0
- package/dist/next/contracts/evolve.d.ts +92 -0
- package/dist/next/contracts/evolve.d.ts.map +1 -0
- package/dist/next/contracts/evolve.js +179 -0
- package/dist/next/contracts/evolve.js.map +1 -0
- package/dist/next/contracts/fingerprint.d.ts +16 -0
- package/dist/next/contracts/fingerprint.d.ts.map +1 -0
- package/dist/next/contracts/fingerprint.js +50 -0
- package/dist/next/contracts/fingerprint.js.map +1 -0
- package/dist/next/contracts/history.d.ts +71 -0
- package/dist/next/contracts/history.d.ts.map +1 -0
- package/dist/next/contracts/history.js +3 -0
- package/dist/next/contracts/history.js.map +1 -0
- package/dist/next/contracts/host-kind.d.ts +40 -0
- package/dist/next/contracts/host-kind.d.ts.map +1 -0
- package/dist/next/contracts/host-kind.js +37 -0
- package/dist/next/contracts/host-kind.js.map +1 -0
- package/dist/next/contracts/index.d.ts +7 -0
- package/dist/next/contracts/index.d.ts.map +1 -0
- package/dist/next/contracts/index.js +6 -0
- package/dist/next/contracts/index.js.map +1 -0
- package/dist/next/contracts/internal.d.ts +10 -0
- package/dist/next/contracts/internal.d.ts.map +1 -0
- package/dist/next/contracts/internal.js +9 -0
- package/dist/next/contracts/internal.js.map +1 -0
- package/dist/next/contracts/names.d.ts +3 -0
- package/dist/next/contracts/names.d.ts.map +1 -0
- package/dist/next/contracts/names.js +13 -0
- package/dist/next/contracts/names.js.map +1 -0
- package/dist/next/contracts/params.d.ts +28 -0
- package/dist/next/contracts/params.d.ts.map +1 -0
- package/dist/next/contracts/params.js +50 -0
- package/dist/next/contracts/params.js.map +1 -0
- package/dist/next/contracts/schema.d.ts +102 -0
- package/dist/next/contracts/schema.d.ts.map +1 -0
- package/dist/next/contracts/schema.js +103 -0
- package/dist/next/contracts/schema.js.map +1 -0
- package/dist/next/contracts/snapshot.d.ts +16 -0
- package/dist/next/contracts/snapshot.d.ts.map +1 -0
- package/dist/next/contracts/snapshot.js +167 -0
- package/dist/next/contracts/snapshot.js.map +1 -0
- package/dist/next/data/args.d.ts +50 -0
- package/dist/next/data/args.d.ts.map +1 -0
- package/dist/next/data/args.js +83 -0
- package/dist/next/data/args.js.map +1 -0
- package/dist/next/data/errors.d.ts +73 -0
- package/dist/next/data/errors.d.ts.map +1 -0
- package/dist/next/data/errors.js +107 -0
- package/dist/next/data/errors.js.map +1 -0
- package/dist/next/data/failure.d.ts +26 -0
- package/dist/next/data/failure.d.ts.map +1 -0
- package/dist/next/data/failure.js +72 -0
- package/dist/next/data/failure.js.map +1 -0
- package/dist/next/data/index.d.ts +4 -0
- package/dist/next/data/index.d.ts.map +1 -0
- package/dist/next/data/index.js +4 -0
- package/dist/next/data/index.js.map +1 -0
- package/dist/next/data/internal.d.ts +7 -0
- package/dist/next/data/internal.d.ts.map +1 -0
- package/dist/next/data/internal.js +8 -0
- package/dist/next/data/internal.js.map +1 -0
- package/dist/next/data/params.d.ts +20 -0
- package/dist/next/data/params.d.ts.map +1 -0
- package/dist/next/data/params.js +31 -0
- package/dist/next/data/params.js.map +1 -0
- package/dist/next/data/principal.d.ts +17 -0
- package/dist/next/data/principal.d.ts.map +1 -0
- package/dist/next/data/principal.js +41 -0
- package/dist/next/data/principal.js.map +1 -0
- package/dist/next/data/validator.d.ts +12 -0
- package/dist/next/data/validator.d.ts.map +1 -0
- package/dist/next/data/validator.js +34 -0
- package/dist/next/data/validator.js.map +1 -0
- package/dist/next/documents/address-source.d.ts +20 -0
- package/dist/next/documents/address-source.d.ts.map +1 -0
- package/dist/next/documents/address-source.js +44 -0
- package/dist/next/documents/address-source.js.map +1 -0
- package/dist/next/documents/definition.d.ts +84 -0
- package/dist/next/documents/definition.d.ts.map +1 -0
- package/dist/next/documents/definition.js +73 -0
- package/dist/next/documents/definition.js.map +1 -0
- package/dist/next/documents/documents.d.ts +106 -0
- package/dist/next/documents/documents.d.ts.map +1 -0
- package/dist/next/documents/documents.js +224 -0
- package/dist/next/documents/documents.js.map +1 -0
- package/dist/next/documents/fence.d.ts +9 -0
- package/dist/next/documents/fence.d.ts.map +1 -0
- package/dist/next/documents/fence.js +15 -0
- package/dist/next/documents/fence.js.map +1 -0
- package/dist/next/documents/handles.d.ts +76 -0
- package/dist/next/documents/handles.d.ts.map +1 -0
- package/dist/next/documents/handles.js +66 -0
- package/dist/next/documents/handles.js.map +1 -0
- package/dist/next/documents/index.d.ts +4 -0
- package/dist/next/documents/index.d.ts.map +1 -0
- package/dist/next/documents/index.js +3 -0
- package/dist/next/documents/index.js.map +1 -0
- package/dist/next/documents/internal.d.ts +9 -0
- package/dist/next/documents/internal.d.ts.map +1 -0
- package/dist/next/documents/internal.js +9 -0
- package/dist/next/documents/internal.js.map +1 -0
- package/dist/next/documents/keyed-slot.d.ts +103 -0
- package/dist/next/documents/keyed-slot.d.ts.map +1 -0
- package/dist/next/documents/keyed-slot.js +395 -0
- package/dist/next/documents/keyed-slot.js.map +1 -0
- package/dist/next/documents/line.d.ts +7 -0
- package/dist/next/documents/line.d.ts.map +1 -0
- package/dist/next/documents/line.js +14 -0
- package/dist/next/documents/line.js.map +1 -0
- package/dist/next/documents/persistence.d.ts +104 -0
- package/dist/next/documents/persistence.d.ts.map +1 -0
- package/dist/next/documents/persistence.js +128 -0
- package/dist/next/documents/persistence.js.map +1 -0
- package/dist/next/documents/residency.d.ts +31 -0
- package/dist/next/documents/residency.d.ts.map +1 -0
- package/dist/next/documents/residency.js +93 -0
- package/dist/next/documents/residency.js.map +1 -0
- package/dist/next/documents/slot.d.ts +109 -0
- package/dist/next/documents/slot.d.ts.map +1 -0
- package/dist/next/documents/slot.js +181 -0
- package/dist/next/documents/slot.js.map +1 -0
- package/dist/next/documents/transaction.d.ts +133 -0
- package/dist/next/documents/transaction.d.ts.map +1 -0
- package/dist/next/documents/transaction.js +409 -0
- package/dist/next/documents/transaction.js.map +1 -0
- package/dist/next/host/activity.d.ts +31 -0
- package/dist/next/host/activity.d.ts.map +1 -0
- package/dist/next/host/activity.js +40 -0
- package/dist/next/host/activity.js.map +1 -0
- package/dist/next/host/adapted.d.ts +49 -0
- package/dist/next/host/adapted.d.ts.map +1 -0
- package/dist/next/host/adapted.js +214 -0
- package/dist/next/host/adapted.js.map +1 -0
- package/dist/next/host/attempt.d.ts +278 -0
- package/dist/next/host/attempt.d.ts.map +1 -0
- package/dist/next/host/attempt.js +1072 -0
- package/dist/next/host/attempt.js.map +1 -0
- package/dist/next/host/backoff.d.ts +29 -0
- package/dist/next/host/backoff.d.ts.map +1 -0
- package/dist/next/host/backoff.js +69 -0
- package/dist/next/host/backoff.js.map +1 -0
- package/dist/next/host/ctx.d.ts +47 -0
- package/dist/next/host/ctx.d.ts.map +1 -0
- package/dist/next/host/ctx.js +108 -0
- package/dist/next/host/ctx.js.map +1 -0
- package/dist/next/host/deadline.d.ts +12 -0
- package/dist/next/host/deadline.d.ts.map +1 -0
- package/dist/next/host/deadline.js +40 -0
- package/dist/next/host/deadline.js.map +1 -0
- package/dist/next/host/dependencies.d.ts +65 -0
- package/dist/next/host/dependencies.d.ts.map +1 -0
- package/dist/next/host/dependencies.js +115 -0
- package/dist/next/host/dependencies.js.map +1 -0
- package/dist/next/host/destination.d.ts +48 -0
- package/dist/next/host/destination.d.ts.map +1 -0
- package/dist/next/host/destination.js +101 -0
- package/dist/next/host/destination.js.map +1 -0
- package/dist/next/host/facet.d.ts +79 -0
- package/dist/next/host/facet.d.ts.map +1 -0
- package/dist/next/host/facet.js +55 -0
- package/dist/next/host/facet.js.map +1 -0
- package/dist/next/host/follow.d.ts +52 -0
- package/dist/next/host/follow.d.ts.map +1 -0
- package/dist/next/host/follow.js +207 -0
- package/dist/next/host/follow.js.map +1 -0
- package/dist/next/host/host.d.ts +495 -0
- package/dist/next/host/host.d.ts.map +1 -0
- package/dist/next/host/host.js +1075 -0
- package/dist/next/host/host.js.map +1 -0
- package/dist/next/host/index.d.ts +17 -0
- package/dist/next/host/index.d.ts.map +1 -0
- package/dist/next/host/index.js +6 -0
- package/dist/next/host/index.js.map +1 -0
- package/dist/next/host/internal.d.ts +10 -0
- package/dist/next/host/internal.d.ts.map +1 -0
- package/dist/next/host/internal.js +8 -0
- package/dist/next/host/internal.js.map +1 -0
- package/dist/next/host/members.d.ts +50 -0
- package/dist/next/host/members.d.ts.map +1 -0
- package/dist/next/host/members.js +107 -0
- package/dist/next/host/members.js.map +1 -0
- package/dist/next/host/native.d.ts +55 -0
- package/dist/next/host/native.d.ts.map +1 -0
- package/dist/next/host/native.js +92 -0
- package/dist/next/host/native.js.map +1 -0
- package/dist/next/host/object.d.ts +290 -0
- package/dist/next/host/object.d.ts.map +1 -0
- package/dist/next/host/object.js +1127 -0
- package/dist/next/host/object.js.map +1 -0
- package/dist/next/host/parked.d.ts +23 -0
- package/dist/next/host/parked.d.ts.map +1 -0
- package/dist/next/host/parked.js +79 -0
- package/dist/next/host/parked.js.map +1 -0
- package/dist/next/host/presence.d.ts +34 -0
- package/dist/next/host/presence.d.ts.map +1 -0
- package/dist/next/host/presence.js +117 -0
- package/dist/next/host/presence.js.map +1 -0
- package/dist/next/host/ref-state.d.ts +53 -0
- package/dist/next/host/ref-state.d.ts.map +1 -0
- package/dist/next/host/ref-state.js +83 -0
- package/dist/next/host/ref-state.js.map +1 -0
- package/dist/next/host/reference-keys.d.ts +36 -0
- package/dist/next/host/reference-keys.d.ts.map +1 -0
- package/dist/next/host/reference-keys.js +168 -0
- package/dist/next/host/reference-keys.js.map +1 -0
- package/dist/next/host/reference-source.d.ts +65 -0
- package/dist/next/host/reference-source.d.ts.map +1 -0
- package/dist/next/host/reference-source.js +285 -0
- package/dist/next/host/reference-source.js.map +1 -0
- package/dist/next/host/reference.d.ts +308 -0
- package/dist/next/host/reference.d.ts.map +1 -0
- package/dist/next/host/reference.js +775 -0
- package/dist/next/host/reference.js.map +1 -0
- package/dist/next/host/retry-on.d.ts +28 -0
- package/dist/next/host/retry-on.d.ts.map +1 -0
- package/dist/next/host/retry-on.js +52 -0
- package/dist/next/host/retry-on.js.map +1 -0
- package/dist/next/host/revocation.d.ts +16 -0
- package/dist/next/host/revocation.d.ts.map +1 -0
- package/dist/next/host/revocation.js +27 -0
- package/dist/next/host/revocation.js.map +1 -0
- package/dist/next/host/root.d.ts +27 -0
- package/dist/next/host/root.d.ts.map +1 -0
- package/dist/next/host/root.js +68 -0
- package/dist/next/host/root.js.map +1 -0
- package/dist/next/host/route.d.ts +64 -0
- package/dist/next/host/route.d.ts.map +1 -0
- package/dist/next/host/route.js +190 -0
- package/dist/next/host/route.js.map +1 -0
- package/dist/next/host/routines.d.ts +76 -0
- package/dist/next/host/routines.d.ts.map +1 -0
- package/dist/next/host/routines.js +350 -0
- package/dist/next/host/routines.js.map +1 -0
- package/dist/next/host/sleep.d.ts +9 -0
- package/dist/next/host/sleep.d.ts.map +1 -0
- package/dist/next/host/sleep.js +40 -0
- package/dist/next/host/sleep.js.map +1 -0
- package/dist/next/host/staging.d.ts +94 -0
- package/dist/next/host/staging.d.ts.map +1 -0
- package/dist/next/host/staging.js +302 -0
- package/dist/next/host/staging.js.map +1 -0
- package/dist/next/host/unbound.d.ts +30 -0
- package/dist/next/host/unbound.d.ts.map +1 -0
- package/dist/next/host/unbound.js +67 -0
- package/dist/next/host/unbound.js.map +1 -0
- package/dist/next/host/uuid.d.ts +3 -0
- package/dist/next/host/uuid.d.ts.map +1 -0
- package/dist/next/host/uuid.js +38 -0
- package/dist/next/host/uuid.js.map +1 -0
- package/dist/next/index.d.ts +28 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +18 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/jobs/definition.d.ts +96 -0
- package/dist/next/jobs/definition.d.ts.map +1 -0
- package/dist/next/jobs/definition.js +83 -0
- package/dist/next/jobs/definition.js.map +1 -0
- package/dist/next/jobs/index.d.ts +5 -0
- package/dist/next/jobs/index.d.ts.map +1 -0
- package/dist/next/jobs/index.js +3 -0
- package/dist/next/jobs/index.js.map +1 -0
- package/dist/next/jobs/internal.d.ts +3 -0
- package/dist/next/jobs/internal.d.ts.map +1 -0
- package/dist/next/jobs/internal.js +4 -0
- package/dist/next/jobs/internal.js.map +1 -0
- package/dist/next/jobs/job.d.ts +152 -0
- package/dist/next/jobs/job.d.ts.map +1 -0
- package/dist/next/jobs/job.js +320 -0
- package/dist/next/jobs/job.js.map +1 -0
- package/dist/next/jobs/persisted.d.ts +38 -0
- package/dist/next/jobs/persisted.d.ts.map +1 -0
- package/dist/next/jobs/persisted.js +95 -0
- package/dist/next/jobs/persisted.js.map +1 -0
- package/dist/next/jobs/records.d.ts +231 -0
- package/dist/next/jobs/records.d.ts.map +1 -0
- package/dist/next/jobs/records.js +869 -0
- package/dist/next/jobs/records.js.map +1 -0
- package/dist/next/jobs/run-states.d.ts +69 -0
- package/dist/next/jobs/run-states.d.ts.map +1 -0
- package/dist/next/jobs/run-states.js +228 -0
- package/dist/next/jobs/run-states.js.map +1 -0
- package/dist/next/jobs/run.d.ts +113 -0
- package/dist/next/jobs/run.d.ts.map +1 -0
- package/dist/next/jobs/run.js +200 -0
- package/dist/next/jobs/run.js.map +1 -0
- package/dist/next/jobs/running.d.ts +44 -0
- package/dist/next/jobs/running.d.ts.map +1 -0
- package/dist/next/jobs/running.js +117 -0
- package/dist/next/jobs/running.js.map +1 -0
- package/dist/next/jobs/stored.d.ts +63 -0
- package/dist/next/jobs/stored.d.ts.map +1 -0
- package/dist/next/jobs/stored.js +55 -0
- package/dist/next/jobs/stored.js.map +1 -0
- package/dist/next/link/binary.d.ts +4 -0
- package/dist/next/link/binary.d.ts.map +1 -0
- package/dist/next/link/binary.js +534 -0
- package/dist/next/link/binary.js.map +1 -0
- package/dist/next/link/channel.d.ts +63 -0
- package/dist/next/link/channel.d.ts.map +1 -0
- package/dist/next/link/channel.js +202 -0
- package/dist/next/link/channel.js.map +1 -0
- package/dist/next/link/errors.d.ts +7 -0
- package/dist/next/link/errors.d.ts.map +1 -0
- package/dist/next/link/errors.js +21 -0
- package/dist/next/link/errors.js.map +1 -0
- package/dist/next/link/index.d.ts +8 -0
- package/dist/next/link/index.d.ts.map +1 -0
- package/dist/next/link/index.js +8 -0
- package/dist/next/link/index.js.map +1 -0
- package/dist/next/link/internal.d.ts +9 -0
- package/dist/next/link/internal.d.ts.map +1 -0
- package/dist/next/link/internal.js +10 -0
- package/dist/next/link/internal.js.map +1 -0
- package/dist/next/link/ipc.d.ts +22 -0
- package/dist/next/link/ipc.d.ts.map +1 -0
- package/dist/next/link/ipc.js +64 -0
- package/dist/next/link/ipc.js.map +1 -0
- package/dist/next/link/link.d.ts +34 -0
- package/dist/next/link/link.d.ts.map +1 -0
- package/dist/next/link/link.js +87 -0
- package/dist/next/link/link.js.map +1 -0
- package/dist/next/link/message.d.ts +249 -0
- package/dist/next/link/message.d.ts.map +1 -0
- package/dist/next/link/message.js +123 -0
- package/dist/next/link/message.js.map +1 -0
- package/dist/next/link/part.d.ts +80 -0
- package/dist/next/link/part.d.ts.map +1 -0
- package/dist/next/link/part.js +164 -0
- package/dist/next/link/part.js.map +1 -0
- package/dist/next/link/text.d.ts +6 -0
- package/dist/next/link/text.d.ts.map +1 -0
- package/dist/next/link/text.js +335 -0
- package/dist/next/link/text.js.map +1 -0
- package/dist/next/link/values.d.ts +40 -0
- package/dist/next/link/values.d.ts.map +1 -0
- package/dist/next/link/values.js +117 -0
- package/dist/next/link/values.js.map +1 -0
- package/dist/next/link/websocket.d.ts +26 -0
- package/dist/next/link/websocket.d.ts.map +1 -0
- package/dist/next/link/websocket.js +91 -0
- package/dist/next/link/websocket.js.map +1 -0
- package/dist/next/registries/contribution.d.ts +50 -0
- package/dist/next/registries/contribution.d.ts.map +1 -0
- package/dist/next/registries/contribution.js +129 -0
- package/dist/next/registries/contribution.js.map +1 -0
- package/dist/next/registries/entries.d.ts +18 -0
- package/dist/next/registries/entries.d.ts.map +1 -0
- package/dist/next/registries/entries.js +42 -0
- package/dist/next/registries/entries.js.map +1 -0
- package/dist/next/registries/index.d.ts +3 -0
- package/dist/next/registries/index.d.ts.map +1 -0
- package/dist/next/registries/index.js +5 -0
- package/dist/next/registries/index.js.map +1 -0
- package/dist/next/registries/internal.d.ts +4 -0
- package/dist/next/registries/internal.d.ts.map +1 -0
- package/dist/next/registries/internal.js +5 -0
- package/dist/next/registries/internal.js.map +1 -0
- package/dist/next/registries/record.d.ts +94 -0
- package/dist/next/registries/record.d.ts.map +1 -0
- package/dist/next/registries/record.js +253 -0
- package/dist/next/registries/record.js.map +1 -0
- package/dist/next/registries/registry.d.ts +74 -0
- package/dist/next/registries/registry.d.ts.map +1 -0
- package/dist/next/registries/registry.js +14 -0
- package/dist/next/registries/registry.js.map +1 -0
- package/dist/next/registries/value.d.ts +48 -0
- package/dist/next/registries/value.d.ts.map +1 -0
- package/dist/next/registries/value.js +199 -0
- package/dist/next/registries/value.js.map +1 -0
- package/dist/next/remote/calls.d.ts +25 -0
- package/dist/next/remote/calls.d.ts.map +1 -0
- package/dist/next/remote/calls.js +62 -0
- package/dist/next/remote/calls.js.map +1 -0
- package/dist/next/remote/consumer.d.ts +42 -0
- package/dist/next/remote/consumer.d.ts.map +1 -0
- package/dist/next/remote/consumer.js +343 -0
- package/dist/next/remote/consumer.js.map +1 -0
- package/dist/next/remote/hold.d.ts +130 -0
- package/dist/next/remote/hold.d.ts.map +1 -0
- package/dist/next/remote/hold.js +537 -0
- package/dist/next/remote/hold.js.map +1 -0
- package/dist/next/remote/host-link.d.ts +77 -0
- package/dist/next/remote/host-link.d.ts.map +1 -0
- package/dist/next/remote/host-link.js +182 -0
- package/dist/next/remote/host-link.js.map +1 -0
- package/dist/next/remote/internal.d.ts +6 -0
- package/dist/next/remote/internal.d.ts.map +1 -0
- package/dist/next/remote/internal.js +6 -0
- package/dist/next/remote/internal.js.map +1 -0
- package/dist/next/remote/path.d.ts +46 -0
- package/dist/next/remote/path.d.ts.map +1 -0
- package/dist/next/remote/path.js +73 -0
- package/dist/next/remote/path.js.map +1 -0
- package/dist/next/remote/provider.d.ts +76 -0
- package/dist/next/remote/provider.d.ts.map +1 -0
- package/dist/next/remote/provider.js +506 -0
- package/dist/next/remote/provider.js.map +1 -0
- package/dist/next/remote/relay.d.ts +58 -0
- package/dist/next/remote/relay.d.ts.map +1 -0
- package/dist/next/remote/relay.js +117 -0
- package/dist/next/remote/relay.js.map +1 -0
- package/dist/next/remote/remote-object.d.ts +133 -0
- package/dist/next/remote/remote-object.d.ts.map +1 -0
- package/dist/next/remote/remote-object.js +411 -0
- package/dist/next/remote/remote-object.js.map +1 -0
- package/dist/next/remote/replica.d.ts +59 -0
- package/dist/next/remote/replica.d.ts.map +1 -0
- package/dist/next/remote/replica.js +125 -0
- package/dist/next/remote/replica.js.map +1 -0
- package/dist/next/state/batch.d.ts +64 -0
- package/dist/next/state/batch.d.ts.map +1 -0
- package/dist/next/state/batch.js +163 -0
- package/dist/next/state/batch.js.map +1 -0
- package/dist/next/state/derive.d.ts +52 -0
- package/dist/next/state/derive.d.ts.map +1 -0
- package/dist/next/state/derive.js +182 -0
- package/dist/next/state/derive.js.map +1 -0
- package/dist/next/state/index.d.ts +6 -0
- package/dist/next/state/index.d.ts.map +1 -0
- package/dist/next/state/index.js +4 -0
- package/dist/next/state/index.js.map +1 -0
- package/dist/next/state/internal.d.ts +6 -0
- package/dist/next/state/internal.d.ts.map +1 -0
- package/dist/next/state/internal.js +8 -0
- package/dist/next/state/internal.js.map +1 -0
- package/dist/next/state/native-source.d.ts +106 -0
- package/dist/next/state/native-source.d.ts.map +1 -0
- package/dist/next/state/native-source.js +240 -0
- package/dist/next/state/native-source.js.map +1 -0
- package/dist/next/state/watchable.d.ts +114 -0
- package/dist/next/state/watchable.d.ts.map +1 -0
- package/dist/next/state/watchable.js +156 -0
- package/dist/next/state/watchable.js.map +1 -0
- package/dist/next/state/writable.d.ts +32 -0
- package/dist/next/state/writable.d.ts.map +1 -0
- package/dist/next/state/writable.js +49 -0
- package/dist/next/state/writable.js.map +1 -0
- package/dist/next/store/adapter.d.ts +67 -0
- package/dist/next/store/adapter.d.ts.map +1 -0
- package/dist/next/store/adapter.js +118 -0
- package/dist/next/store/adapter.js.map +1 -0
- package/dist/next/store/allocator.d.ts +17 -0
- package/dist/next/store/allocator.d.ts.map +1 -0
- package/dist/next/store/allocator.js +30 -0
- package/dist/next/store/allocator.js.map +1 -0
- package/dist/next/store/applier.d.ts +8 -0
- package/dist/next/store/applier.d.ts.map +1 -0
- package/dist/next/store/applier.js +375 -0
- package/dist/next/store/applier.js.map +1 -0
- package/dist/next/store/apply-batch.d.ts +12 -0
- package/dist/next/store/apply-batch.d.ts.map +1 -0
- package/dist/next/store/apply-batch.js +83 -0
- package/dist/next/store/apply-batch.js.map +1 -0
- package/dist/next/store/archive.d.ts +32 -0
- package/dist/next/store/archive.d.ts.map +1 -0
- package/dist/next/store/archive.js +129 -0
- package/dist/next/store/archive.js.map +1 -0
- package/dist/next/store/backend.d.ts +10 -0
- package/dist/next/store/backend.d.ts.map +1 -0
- package/dist/next/store/backend.js +15 -0
- package/dist/next/store/backend.js.map +1 -0
- package/dist/next/store/catalog.d.ts +24 -0
- package/dist/next/store/catalog.d.ts.map +1 -0
- package/dist/next/store/catalog.js +17 -0
- package/dist/next/store/catalog.js.map +1 -0
- package/dist/next/store/claims.d.ts +23 -0
- package/dist/next/store/claims.d.ts.map +1 -0
- package/dist/next/store/claims.js +65 -0
- package/dist/next/store/claims.js.map +1 -0
- package/dist/next/store/columns.d.ts +77 -0
- package/dist/next/store/columns.d.ts.map +1 -0
- package/dist/next/store/columns.js +77 -0
- package/dist/next/store/columns.js.map +1 -0
- package/dist/next/store/engine.d.ts +176 -0
- package/dist/next/store/engine.d.ts.map +1 -0
- package/dist/next/store/engine.js +283 -0
- package/dist/next/store/engine.js.map +1 -0
- package/dist/next/store/evaluate.d.ts +17 -0
- package/dist/next/store/evaluate.d.ts.map +1 -0
- package/dist/next/store/evaluate.js +128 -0
- package/dist/next/store/evaluate.js.map +1 -0
- package/dist/next/store/export.d.ts +17 -0
- package/dist/next/store/export.d.ts.map +1 -0
- package/dist/next/store/export.js +200 -0
- package/dist/next/store/export.js.map +1 -0
- package/dist/next/store/expression.d.ts +150 -0
- package/dist/next/store/expression.d.ts.map +1 -0
- package/dist/next/store/expression.js +268 -0
- package/dist/next/store/expression.js.map +1 -0
- package/dist/next/store/import.d.ts +10 -0
- package/dist/next/store/import.d.ts.map +1 -0
- package/dist/next/store/import.js +276 -0
- package/dist/next/store/import.js.map +1 -0
- package/dist/next/store/index.d.ts +16 -0
- package/dist/next/store/index.d.ts.map +1 -0
- package/dist/next/store/index.js +13 -0
- package/dist/next/store/index.js.map +1 -0
- package/dist/next/store/json-column.d.ts +33 -0
- package/dist/next/store/json-column.d.ts.map +1 -0
- package/dist/next/store/json-column.js +61 -0
- package/dist/next/store/json-column.js.map +1 -0
- package/dist/next/store/jsonl.d.ts +9 -0
- package/dist/next/store/jsonl.d.ts.map +1 -0
- package/dist/next/store/jsonl.js +61 -0
- package/dist/next/store/jsonl.js.map +1 -0
- package/dist/next/store/outbox.d.ts +26 -0
- package/dist/next/store/outbox.d.ts.map +1 -0
- package/dist/next/store/outbox.js +80 -0
- package/dist/next/store/outbox.js.map +1 -0
- package/dist/next/store/query.d.ts +39 -0
- package/dist/next/store/query.d.ts.map +1 -0
- package/dist/next/store/query.js +97 -0
- package/dist/next/store/query.js.map +1 -0
- package/dist/next/store/refusal.d.ts +15 -0
- package/dist/next/store/refusal.d.ts.map +1 -0
- package/dist/next/store/refusal.js +36 -0
- package/dist/next/store/refusal.js.map +1 -0
- package/dist/next/store/rows.d.ts +80 -0
- package/dist/next/store/rows.d.ts.map +1 -0
- package/dist/next/store/rows.js +183 -0
- package/dist/next/store/rows.js.map +1 -0
- package/dist/next/store/schema.d.ts +25 -0
- package/dist/next/store/schema.d.ts.map +1 -0
- package/dist/next/store/schema.js +115 -0
- package/dist/next/store/schema.js.map +1 -0
- package/dist/next/store/sql.d.ts +73 -0
- package/dist/next/store/sql.d.ts.map +1 -0
- package/dist/next/store/sql.js +234 -0
- package/dist/next/store/sql.js.map +1 -0
- package/dist/next/store/step.d.ts +48 -0
- package/dist/next/store/step.d.ts.map +1 -0
- package/dist/next/store/step.js +50 -0
- package/dist/next/store/step.js.map +1 -0
- package/dist/next/store/store.d.ts +161 -0
- package/dist/next/store/store.d.ts.map +1 -0
- package/dist/next/store/store.js +627 -0
- package/dist/next/store/store.js.map +1 -0
- package/dist/next/store/table-changes.d.ts +29 -0
- package/dist/next/store/table-changes.d.ts.map +1 -0
- package/dist/next/store/table-changes.js +102 -0
- package/dist/next/store/table-changes.js.map +1 -0
- package/dist/next/store/table-evolve.d.ts +74 -0
- package/dist/next/store/table-evolve.d.ts.map +1 -0
- package/dist/next/store/table-evolve.js +201 -0
- package/dist/next/store/table-evolve.js.map +1 -0
- package/dist/next/store/table-handle.d.ts +67 -0
- package/dist/next/store/table-handle.d.ts.map +1 -0
- package/dist/next/store/table-handle.js +101 -0
- package/dist/next/store/table-handle.js.map +1 -0
- package/dist/next/store/table-history.d.ts +75 -0
- package/dist/next/store/table-history.d.ts.map +1 -0
- package/dist/next/store/table-history.js +42 -0
- package/dist/next/store/table-history.js.map +1 -0
- package/dist/next/store/table-migration.d.ts +16 -0
- package/dist/next/store/table-migration.d.ts.map +1 -0
- package/dist/next/store/table-migration.js +202 -0
- package/dist/next/store/table-migration.js.map +1 -0
- package/dist/next/store/table-writes.d.ts +125 -0
- package/dist/next/store/table-writes.d.ts.map +1 -0
- package/dist/next/store/table-writes.js +165 -0
- package/dist/next/store/table-writes.js.map +1 -0
- package/dist/next/store/table.d.ts +80 -0
- package/dist/next/store/table.d.ts.map +1 -0
- package/dist/next/store/table.js +103 -0
- package/dist/next/store/table.js.map +1 -0
- package/dist/next/store/text.d.ts +14 -0
- package/dist/next/store/text.d.ts.map +1 -0
- package/dist/next/store/text.js +51 -0
- package/dist/next/store/text.js.map +1 -0
- package/dist/next/store/writes.d.ts +5 -0
- package/dist/next/store/writes.d.ts.map +1 -0
- package/dist/next/store/writes.js +4 -0
- package/dist/next/store/writes.js.map +1 -0
- package/dist/next-node/compression.d.ts +7 -0
- package/dist/next-node/compression.d.ts.map +1 -0
- package/dist/next-node/compression.js +24 -0
- package/dist/next-node/compression.js.map +1 -0
- package/dist/next-node/http/admission.d.ts +63 -0
- package/dist/next-node/http/admission.d.ts.map +1 -0
- package/dist/next-node/http/admission.js +134 -0
- package/dist/next-node/http/admission.js.map +1 -0
- package/dist/next-node/http/authenticate.d.ts +21 -0
- package/dist/next-node/http/authenticate.d.ts.map +1 -0
- package/dist/next-node/http/authenticate.js +34 -0
- package/dist/next-node/http/authenticate.js.map +1 -0
- package/dist/next-node/http/cookies.d.ts +24 -0
- package/dist/next-node/http/cookies.d.ts.map +1 -0
- package/dist/next-node/http/cookies.js +62 -0
- package/dist/next-node/http/cookies.js.map +1 -0
- package/dist/next-node/http/file.d.ts +23 -0
- package/dist/next-node/http/file.d.ts.map +1 -0
- package/dist/next-node/http/file.js +94 -0
- package/dist/next-node/http/file.js.map +1 -0
- package/dist/next-node/http/headers.d.ts +37 -0
- package/dist/next-node/http/headers.d.ts.map +1 -0
- package/dist/next-node/http/headers.js +129 -0
- package/dist/next-node/http/headers.js.map +1 -0
- package/dist/next-node/http/http.d.ts +100 -0
- package/dist/next-node/http/http.d.ts.map +1 -0
- package/dist/next-node/http/http.js +462 -0
- package/dist/next-node/http/http.js.map +1 -0
- package/dist/next-node/http/incoming.d.ts +19 -0
- package/dist/next-node/http/incoming.d.ts.map +1 -0
- package/dist/next-node/http/incoming.js +31 -0
- package/dist/next-node/http/incoming.js.map +1 -0
- package/dist/next-node/http/index.d.ts +11 -0
- package/dist/next-node/http/index.d.ts.map +1 -0
- package/dist/next-node/http/index.js +12 -0
- package/dist/next-node/http/index.js.map +1 -0
- package/dist/next-node/http/node.d.ts +78 -0
- package/dist/next-node/http/node.d.ts.map +1 -0
- package/dist/next-node/http/node.js +291 -0
- package/dist/next-node/http/node.js.map +1 -0
- package/dist/next-node/http/request.d.ts +54 -0
- package/dist/next-node/http/request.d.ts.map +1 -0
- package/dist/next-node/http/request.js +116 -0
- package/dist/next-node/http/request.js.map +1 -0
- package/dist/next-node/http/response.d.ts +63 -0
- package/dist/next-node/http/response.d.ts.map +1 -0
- package/dist/next-node/http/response.js +202 -0
- package/dist/next-node/http/response.js.map +1 -0
- package/dist/next-node/http/router.d.ts +114 -0
- package/dist/next-node/http/router.d.ts.map +1 -0
- package/dist/next-node/http/router.js +261 -0
- package/dist/next-node/http/router.js.map +1 -0
- package/dist/next-node/http/upgrades.d.ts +58 -0
- package/dist/next-node/http/upgrades.d.ts.map +1 -0
- package/dist/next-node/http/upgrades.js +184 -0
- package/dist/next-node/http/upgrades.js.map +1 -0
- package/dist/next-node/plugins/build.d.ts +57 -0
- package/dist/next-node/plugins/build.d.ts.map +1 -0
- package/dist/next-node/plugins/build.js +334 -0
- package/dist/next-node/plugins/build.js.map +1 -0
- package/dist/next-node/plugins/discover.d.ts +36 -0
- package/dist/next-node/plugins/discover.d.ts.map +1 -0
- package/dist/next-node/plugins/discover.js +91 -0
- package/dist/next-node/plugins/discover.js.map +1 -0
- package/dist/next-node/plugins/evaluate.d.ts +33 -0
- package/dist/next-node/plugins/evaluate.d.ts.map +1 -0
- package/dist/next-node/plugins/evaluate.js +98 -0
- package/dist/next-node/plugins/evaluate.js.map +1 -0
- package/dist/next-node/plugins/index.d.ts +9 -0
- package/dist/next-node/plugins/index.d.ts.map +1 -0
- package/dist/next-node/plugins/index.js +11 -0
- package/dist/next-node/plugins/index.js.map +1 -0
- package/dist/next-node/plugins/install.d.ts +13 -0
- package/dist/next-node/plugins/install.d.ts.map +1 -0
- package/dist/next-node/plugins/install.js +37 -0
- package/dist/next-node/plugins/install.js.map +1 -0
- package/dist/next-node/plugins/plugins.d.ts +135 -0
- package/dist/next-node/plugins/plugins.d.ts.map +1 -0
- package/dist/next-node/plugins/plugins.js +206 -0
- package/dist/next-node/plugins/plugins.js.map +1 -0
- package/dist/next-node/plugins/runtime.d.ts +41 -0
- package/dist/next-node/plugins/runtime.d.ts.map +1 -0
- package/dist/next-node/plugins/runtime.js +136 -0
- package/dist/next-node/plugins/runtime.js.map +1 -0
- package/dist/next-node/plugins/stack.d.ts +16 -0
- package/dist/next-node/plugins/stack.d.ts.map +1 -0
- package/dist/next-node/plugins/stack.js +61 -0
- package/dist/next-node/plugins/stack.js.map +1 -0
- package/dist/next-node/plugins/watcher.d.ts +58 -0
- package/dist/next-node/plugins/watcher.d.ts.map +1 -0
- package/dist/next-node/plugins/watcher.js +281 -0
- package/dist/next-node/plugins/watcher.js.map +1 -0
- package/dist/next-node/workers/control.d.ts +83 -0
- package/dist/next-node/workers/control.d.ts.map +1 -0
- package/dist/next-node/workers/control.js +77 -0
- package/dist/next-node/workers/control.js.map +1 -0
- package/dist/next-node/workers/index.d.ts +5 -0
- package/dist/next-node/workers/index.d.ts.map +1 -0
- package/dist/next-node/workers/index.js +7 -0
- package/dist/next-node/workers/index.js.map +1 -0
- package/dist/next-node/workers/lock.d.ts +21 -0
- package/dist/next-node/workers/lock.d.ts.map +1 -0
- package/dist/next-node/workers/lock.js +137 -0
- package/dist/next-node/workers/lock.js.map +1 -0
- package/dist/next-node/workers/main.d.ts +46 -0
- package/dist/next-node/workers/main.d.ts.map +1 -0
- package/dist/next-node/workers/main.js +230 -0
- package/dist/next-node/workers/main.js.map +1 -0
- package/dist/next-node/workers/process.d.ts +42 -0
- package/dist/next-node/workers/process.d.ts.map +1 -0
- package/dist/next-node/workers/process.js +125 -0
- package/dist/next-node/workers/process.js.map +1 -0
- package/dist/next-node/workers/workers.d.ts +80 -0
- package/dist/next-node/workers/workers.d.ts.map +1 -0
- package/dist/next-node/workers/workers.js +572 -0
- package/dist/next-node/workers/workers.js.map +1 -0
- package/dist/object.d.ts +4 -4
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +3 -4
- package/dist/object.js.map +1 -1
- package/dist/output.d.ts +9 -3
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +21 -9
- package/dist/output.js.map +1 -1
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +2 -2
- package/dist/remote.js.map +1 -1
- package/dist/schema.d.ts +8 -4
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +180 -5
- package/dist/schema.js.map +1 -1
- package/dist/sqlite/cloudflare.d.ts +54 -0
- package/dist/sqlite/cloudflare.d.ts.map +1 -0
- package/dist/sqlite/cloudflare.js +144 -0
- package/dist/sqlite/cloudflare.js.map +1 -0
- package/dist/sqlite/database.d.ts +40 -0
- package/dist/sqlite/database.d.ts.map +1 -0
- package/dist/sqlite/database.js +2 -0
- package/dist/sqlite/database.js.map +1 -0
- package/dist/sqlite/index.d.ts +4 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +3 -0
- package/dist/sqlite/index.js.map +1 -0
- package/dist/sqlite/migrations.d.ts +10 -0
- package/dist/sqlite/migrations.d.ts.map +1 -0
- package/dist/sqlite/migrations.js +33 -0
- package/dist/sqlite/migrations.js.map +1 -0
- package/dist/sqlite/node.d.ts +41 -0
- package/dist/sqlite/node.d.ts.map +1 -0
- package/dist/sqlite/node.js +191 -0
- package/dist/sqlite/node.js.map +1 -0
- package/dist/sqlite/schema.d.ts +3 -0
- package/dist/sqlite/schema.d.ts.map +1 -0
- package/dist/sqlite/schema.js +10 -0
- package/dist/sqlite/schema.js.map +1 -0
- package/dist/telemetry-sqlite/index.d.ts +24 -0
- package/dist/telemetry-sqlite/index.d.ts.map +1 -0
- package/dist/telemetry-sqlite/index.js +273 -0
- package/dist/telemetry-sqlite/index.js.map +1 -0
- package/dist/telemetry-sqlite/store.d.ts +9 -0
- package/dist/telemetry-sqlite/store.d.ts.map +1 -0
- package/dist/telemetry-sqlite/store.js +110 -0
- package/dist/telemetry-sqlite/store.js.map +1 -0
- package/dist/watch.d.ts +194 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +383 -0
- package/dist/watch.js.map +1 -0
- package/dist/wire.d.ts +174 -193
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +81 -80
- package/dist/wire.js.map +1 -1
- package/docs/guide.md +15 -15
- package/docs/next/benchmarks.md +959 -0
- package/docs/next/decisions.md +2957 -0
- package/docs/next/dependencies/book.md +1671 -0
- package/docs/next/dependencies/index.html +2641 -0
- package/docs/next/dependencies/model.md +330 -0
- package/docs/next/design.md +2554 -0
- package/docs/next/durable-observers/book.md +432 -0
- package/docs/next/durable-observers/index.html +517 -0
- package/docs/next/flow-control/book.md +333 -0
- package/docs/next/flow-control/fold/index.html +265 -0
- package/docs/next/flow-control/index.html +548 -0
- package/docs/next/flow-control/window/index.html +228 -0
- package/docs/next/guide-plugins-hosts/book.md +607 -0
- package/docs/next/guide-plugins-hosts/index.html +652 -0
- package/docs/next/http-workers/book.md +378 -0
- package/docs/next/http-workers/index.html +515 -0
- package/docs/next/layer-1.md +311 -0
- package/docs/next/layer-2.md +216 -0
- package/docs/next/plugin-model/book.md +186 -0
- package/docs/next/plugin-model/index.html +310 -0
- package/docs/next/plugin-primer/book.md +273 -0
- package/docs/next/plugin-primer/index.html +430 -0
- package/docs/next/slice-1.md +236 -0
- package/docs/next/slice-10.md +285 -0
- package/docs/next/slice-11.md +93 -0
- package/docs/next/slice-2.md +174 -0
- package/docs/next/slice-3a.md +296 -0
- package/docs/next/slice-3b.md +197 -0
- package/docs/next/slice-4.md +146 -0
- package/docs/next/slice-4a.md +418 -0
- package/docs/next/slice-4b.md +208 -0
- package/docs/next/slice-5.md +281 -0
- package/docs/next/slice-6a.md +676 -0
- package/docs/next/slice-6b.md +332 -0
- package/docs/next/slice-7a.md +130 -0
- package/docs/next/slice-7b/book.md +608 -0
- package/docs/next/slice-7b/index.html +842 -0
- package/docs/next/slice-7b.md +255 -0
- package/docs/next/slice-7c.md +165 -0
- package/docs/next/slice-8.md +194 -0
- package/docs/next/slices.md +230 -0
- package/docs/next/store/book.md +665 -0
- package/docs/next/store/index.html +861 -0
- package/docs/next/store/walkthrough.md +193 -0
- package/docs/spec.md +9 -9
- package/docs/tutorial.md +26 -25
- package/package.json +42 -5
- package/src/delta/README.md +69 -0
|
@@ -0,0 +1,1127 @@
|
|
|
1
|
+
// Objects (§6): one per identity, from its first attempt to its end. Its state across attempts (its documents, line
|
|
2
|
+
// and job runs), the instance its references follow (`followed`: decision "References are the only indirection"), its
|
|
3
|
+
// holders, retries after failures (backoff, `ref.retry()`, passed
|
|
4
|
+
// on while parked), what it shows while its attempt is parked on dependencies (dependency model §3), its first outcome
|
|
5
|
+
// (the start barrier, decision (a)), a live object's failure (slice 6a §1.4), the waits and cycle checks of activations
|
|
6
|
+
// (Q5, its instance id and the activation chain it was created for), lingering after its last reference (§3, D8), the
|
|
7
|
+
// job runs that keep it alive (§15), its contributions to registries while live and its wake signals (`retryOn`, slice
|
|
8
|
+
// 8), its ending, revocation included (§4, R11), and what a reload does to it (slice 7b §4): a pure swap in place, a
|
|
9
|
+
// native restart after the drain, a retry on the new code, or its end by its type's removal, after which its
|
|
10
|
+
// references wait with their last values and follow the next object of the identity.
|
|
11
|
+
import { awaitWithContext } from "../../context/index.js";
|
|
12
|
+
import { ChordError } from "../data/index.js";
|
|
13
|
+
import { asChordError, binds, invalid, sameCause } from "../data/internal.js";
|
|
14
|
+
import { Documents } from "../documents/internal.js";
|
|
15
|
+
import { JobRecords } from "../jobs/internal.js";
|
|
16
|
+
import { CHAIN } from "../link/internal.js";
|
|
17
|
+
import { refusal } from "./adapted.js";
|
|
18
|
+
import { Attempt } from "./attempt.js";
|
|
19
|
+
import { LIVE, LOADING } from "./ref-state.js";
|
|
20
|
+
import { retryWalk } from "./reference.js";
|
|
21
|
+
import { RetryWakes } from "./retry-on.js";
|
|
22
|
+
import { migratesTables } from "./staging.js";
|
|
23
|
+
import { uuidv7 } from "./uuid.js";
|
|
24
|
+
const END = { kind: "end" };
|
|
25
|
+
const CLOSE = { kind: "close" };
|
|
26
|
+
const RELOAD = { kind: "reload" };
|
|
27
|
+
/** No dependencies waited for: the shared empty list. */
|
|
28
|
+
const NO_DEPENDENCIES = [];
|
|
29
|
+
/** No contributions leaving: the shared empty list. */
|
|
30
|
+
const NO_CONTRIBUTIONS = [];
|
|
31
|
+
/**
|
|
32
|
+
* One object. Each attempt is a fresh `Attempt`; the documents, the line, the job runs and the holders outlive it. An
|
|
33
|
+
* attempt parked on its dependencies waits for them without a timer; a transient failure (its own) is retried after its
|
|
34
|
+
* backoff window, or at once when a reference asks (`retry`); a broken one stays failed until a reference asks.
|
|
35
|
+
* The object ends with its last reference, a live one after its type's `linger` (never, for a host-lifetime object),
|
|
36
|
+
* or when the host closes.
|
|
37
|
+
*/
|
|
38
|
+
export class ChordObject {
|
|
39
|
+
host;
|
|
40
|
+
/** Its served type: replaced by a reload that swaps, restarts or retries it. */
|
|
41
|
+
served;
|
|
42
|
+
params;
|
|
43
|
+
/** Its params' identity key (empty for empty params). */
|
|
44
|
+
key;
|
|
45
|
+
/** The principal in a remote object's identity, which its factory gets; `undefined` for a local object. */
|
|
46
|
+
principal;
|
|
47
|
+
identity;
|
|
48
|
+
/** The object in errors, reports and cycles: its type, and its params key when it has params. */
|
|
49
|
+
label;
|
|
50
|
+
/**
|
|
51
|
+
* The activation chain it was created for (Q5): the instance ids of the activations waiting for it, from the hold
|
|
52
|
+
* that created it (a trusted link's) or the activation here that declared it; empty otherwise.
|
|
53
|
+
*/
|
|
54
|
+
chain;
|
|
55
|
+
/** Its documents and line, across its attempts. */
|
|
56
|
+
documents;
|
|
57
|
+
/** The context of every attempt: its creator's, without the creator's cancellation. */
|
|
58
|
+
#context;
|
|
59
|
+
/** Its job runs by job name, across its attempts. */
|
|
60
|
+
#jobs = new Map();
|
|
61
|
+
/** This instance's id (uuidv7), minted at its first attempt: a restarted object is a new instance (D4). */
|
|
62
|
+
#instance;
|
|
63
|
+
#state = { kind: "waiting" };
|
|
64
|
+
/** References and holds of this object. */
|
|
65
|
+
#holders = new Set();
|
|
66
|
+
/** The dependencies its parked attempt waits for; their objects are followed to find cycles (Q5). */
|
|
67
|
+
#waitingFor = NO_DEPENDENCIES;
|
|
68
|
+
/**
|
|
69
|
+
* Its first outcome (decision (a)): live, failed, parked with no blocker here still without one, or ended; once.
|
|
70
|
+
* The promise is made by the first who waits for it (the start barrier, for host-lifetime objects).
|
|
71
|
+
*/
|
|
72
|
+
#firstOutcome;
|
|
73
|
+
#hasFirstOutcome = false;
|
|
74
|
+
/** The error of the last failed attempt, or the last cause a parked attempt showed, until one goes live. */
|
|
75
|
+
#lastFailure;
|
|
76
|
+
/** Ends the object when its type's `linger` passed after its last reference; cleared by a new one. */
|
|
77
|
+
#lingering;
|
|
78
|
+
/** Its running and finishing job runs: they keep it alive like references (D4), without being references. */
|
|
79
|
+
#runs = 0;
|
|
80
|
+
/**
|
|
81
|
+
* The instance its references follow (`followed`): the live one, the old one while a swap brings its successor in
|
|
82
|
+
* place, or the last one that went live while it still changes after a failure or a restart (references take their
|
|
83
|
+
* last values from it when it stops); `undefined` before the first went live and once it stopped changing.
|
|
84
|
+
*/
|
|
85
|
+
#exposed;
|
|
86
|
+
/**
|
|
87
|
+
* Whether references still follow `#exposed`, which may still change: while it is live, drains (a restart), retires
|
|
88
|
+
* (a swap's old instance until its successor is live or it retired), or failed live until the commits admitted
|
|
89
|
+
* before it published (every member, its own and re-exposed ones: audit A10); not once it stopped changing.
|
|
90
|
+
*/
|
|
91
|
+
#following = false;
|
|
92
|
+
/** The one timer storing its jobs' held state changes by their earliest deadline (D8), while one is held. */
|
|
93
|
+
#flush;
|
|
94
|
+
/** Its wake signals (`retryOn`), the last attempt's declaration; made by the first. */
|
|
95
|
+
#wakes;
|
|
96
|
+
/** Its swapped-out attempts while they retire (bounded by `closeTimeout`); made by the first swap. */
|
|
97
|
+
#retiring;
|
|
98
|
+
constructor(host, served, params, principal, key, identity, context, chain) {
|
|
99
|
+
this.host = host;
|
|
100
|
+
this.served = served;
|
|
101
|
+
this.params = params;
|
|
102
|
+
this.principal = principal;
|
|
103
|
+
this.key = key;
|
|
104
|
+
this.identity = identity;
|
|
105
|
+
this.label = key === "" ? served.contract.name : `${served.contract.name}(${key})`;
|
|
106
|
+
this.chain = chain;
|
|
107
|
+
this.#context = context;
|
|
108
|
+
const { store } = host;
|
|
109
|
+
this.documents = new Documents({
|
|
110
|
+
label: this.label,
|
|
111
|
+
batch: host.batch,
|
|
112
|
+
context,
|
|
113
|
+
store: store === undefined ? undefined : { store, owner: served.contract.name },
|
|
114
|
+
fail: (error) => {
|
|
115
|
+
if (this.#state.kind === "live")
|
|
116
|
+
this.failLive(this.#state.attempt, { kind: "broken", error });
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/** The object's state as its references show it. */
|
|
121
|
+
get state() {
|
|
122
|
+
const state = this.#state;
|
|
123
|
+
if (state.kind === "failed")
|
|
124
|
+
return state.failure;
|
|
125
|
+
if (state.kind === "live")
|
|
126
|
+
return LIVE;
|
|
127
|
+
if (state.kind === "ended")
|
|
128
|
+
return state.ended;
|
|
129
|
+
return state.kind === "activating" ? state.shown : LOADING;
|
|
130
|
+
}
|
|
131
|
+
/** Whether its state members have values: once live (a local object stays live until it ends). */
|
|
132
|
+
get hydrated() {
|
|
133
|
+
return this.#state.kind === "live";
|
|
134
|
+
}
|
|
135
|
+
/** Resolves at its first outcome (the start barrier waits for it); never rejects. */
|
|
136
|
+
get firstOutcome() {
|
|
137
|
+
if (this.#hasFirstOutcome)
|
|
138
|
+
return Promise.resolve();
|
|
139
|
+
this.#firstOutcome ??= Promise.withResolvers();
|
|
140
|
+
return this.#firstOutcome.promise;
|
|
141
|
+
}
|
|
142
|
+
/** Whether it holds up the start barrier: it has no first outcome yet. */
|
|
143
|
+
get blocksFirstPass() {
|
|
144
|
+
return !this.#hasFirstOutcome;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* The error of its last failure while none went live since: a failed attempt's, or the cause its parked attempt
|
|
148
|
+
* showed last (kept when the dependency falls back to `loading`, so a getter's deadline names it).
|
|
149
|
+
*/
|
|
150
|
+
get lastFailure() {
|
|
151
|
+
return this.#lastFailure;
|
|
152
|
+
}
|
|
153
|
+
/** Its instance id while an attempt activates; `undefined` otherwise (a hold's chain names only activations). */
|
|
154
|
+
get activationId() {
|
|
155
|
+
return this.#state.kind === "activating" ? this.#instance : undefined;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The chain a hold this object's activation makes over a link carries (Q5): its own chain and its instance id, the
|
|
159
|
+
* last 32; `undefined` when it is not activating.
|
|
160
|
+
*/
|
|
161
|
+
activationChain() {
|
|
162
|
+
const id = this.activationId;
|
|
163
|
+
if (id === undefined)
|
|
164
|
+
return undefined;
|
|
165
|
+
const { chain } = this;
|
|
166
|
+
return [...(chain.length < CHAIN ? chain : chain.slice(chain.length - CHAIN + 1)), id];
|
|
167
|
+
}
|
|
168
|
+
/** Its holders, for a presence list made after they took it. */
|
|
169
|
+
get holders() {
|
|
170
|
+
return this.#holders;
|
|
171
|
+
}
|
|
172
|
+
/** The variant a live remote object's factory chose; `undefined` for a local object and before it is live. */
|
|
173
|
+
get variant() {
|
|
174
|
+
return this.#state.kind === "live" ? this.#state.attempt.variant : undefined;
|
|
175
|
+
}
|
|
176
|
+
/** The live object's state members, as Chord follows them. */
|
|
177
|
+
get stateMembers() {
|
|
178
|
+
return this.#live().stateMembers;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Starts an attempt when waiting or failed and returns it; a trigger while an attempt runs (or once live) is ignored.
|
|
182
|
+
* After a failure the holders are told: their references are loading again.
|
|
183
|
+
*/
|
|
184
|
+
attempt() {
|
|
185
|
+
const state = this.#state;
|
|
186
|
+
if (state.kind !== "waiting" && state.kind !== "failed")
|
|
187
|
+
return undefined;
|
|
188
|
+
this.#instance ??= uuidv7();
|
|
189
|
+
const attempt = new Attempt(this, this.#context);
|
|
190
|
+
this.#state = { kind: "activating", attempt, shown: LOADING };
|
|
191
|
+
if (state.kind === "failed")
|
|
192
|
+
this.#notify();
|
|
193
|
+
void this.#run(attempt, this.host.endingOf(this.identity));
|
|
194
|
+
return attempt;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* `ref.retry()` and a `retry` message, as a step of `walk` (handled once per walk: a diamond reaches it twice): an
|
|
198
|
+
* attempt now when failed (a broken one too) or waiting, its backoff window skipped; passed on to the failed
|
|
199
|
+
* dependencies while parked `failed { waiting }`; ignored otherwise (an attempt runs, or it is live).
|
|
200
|
+
*/
|
|
201
|
+
retry(walk = retryWalk()) {
|
|
202
|
+
if (walk.visited.has(this))
|
|
203
|
+
return;
|
|
204
|
+
walk.visited.add(this);
|
|
205
|
+
const state = this.#state;
|
|
206
|
+
if (state.kind === "activating") {
|
|
207
|
+
if (state.shown.kind === "failed")
|
|
208
|
+
state.attempt.retryDependencies(walk);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (state.kind !== "waiting" && state.kind !== "failed")
|
|
212
|
+
return;
|
|
213
|
+
this.host.backoff.skip(this.identity);
|
|
214
|
+
this.attempt();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Follows `sources` as its wake signals instead of the last attempt's (`self.retryOn`, right after a factory
|
|
218
|
+
* returned): a new value retries it while failed, as `ref.retry()` does; one while it activates retries it at once
|
|
219
|
+
* if that attempt fails; one while live does nothing.
|
|
220
|
+
*/
|
|
221
|
+
retryOn(sources) {
|
|
222
|
+
if (this.#wakes === undefined && sources.length === 0)
|
|
223
|
+
return;
|
|
224
|
+
this.#wakes ??= new RetryWakes();
|
|
225
|
+
this.#wakes.replace(sources, () => this.#wake());
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Calls a method of the live object for `caller`, bound at `version` (an older one maps its arguments and result,
|
|
229
|
+
* Q10). While a reload's pure swap runs, the call waits for its new attempt (the gate), bounded by `readyTimeout`.
|
|
230
|
+
*/
|
|
231
|
+
async call(method, args, context, caller, version) {
|
|
232
|
+
const state = this.#state;
|
|
233
|
+
if (state.kind === "activating" && state.swap !== undefined)
|
|
234
|
+
await this.#gate(state.swap, context);
|
|
235
|
+
return this.#live().call(method, args, context, caller, version);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Whether a reload's pure swap runs in place: the new attempt neither parked nor failed yet. Holds stay bound
|
|
239
|
+
* meanwhile (their calls wait at the gate) and get a fresh `bound` once it is live.
|
|
240
|
+
*/
|
|
241
|
+
get swapsInPlace() {
|
|
242
|
+
const state = this.#state;
|
|
243
|
+
return state.kind === "activating" && state.swap !== undefined && !state.swap.parked;
|
|
244
|
+
}
|
|
245
|
+
/** Whether a consumer of `contract`'s version and fingerprint binds to this object's provider now (R6, Q10). */
|
|
246
|
+
binds(contract) {
|
|
247
|
+
return binds(this.served.provider, contract.version, contract.fingerprint);
|
|
248
|
+
}
|
|
249
|
+
/** Its params as checked, with their identity key. */
|
|
250
|
+
get checkedParams() {
|
|
251
|
+
return { params: this.params, key: this.key };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* What a reference of `version` follows for state member `member` now (decision "References are the only
|
|
255
|
+
* indirection"): the shown instance's member (its mapping at an older version) while that instance is live, while a
|
|
256
|
+
* swap brings its successor in place, and after a live failure until its admitted commits published; else nothing:
|
|
257
|
+
* `failed` with the cause's error, or `loading`, with that member to take a last value from.
|
|
258
|
+
*/
|
|
259
|
+
followed(member, version) {
|
|
260
|
+
const exposed = this.#exposed;
|
|
261
|
+
let shown;
|
|
262
|
+
let lacking;
|
|
263
|
+
if (exposed !== undefined) {
|
|
264
|
+
try {
|
|
265
|
+
shown = exposed.memberAt(member, version);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
const failure = asChordError(error, this.label);
|
|
269
|
+
// The shown instance does not serve this version (a swap's old one, while a reload brings it): nothing yet.
|
|
270
|
+
if (failure.code !== "contract_mismatch")
|
|
271
|
+
lacking = failure;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (exposed !== undefined && this.#following) {
|
|
275
|
+
if (shown !== undefined)
|
|
276
|
+
return { kind: "live", source: shown, instance: exposed };
|
|
277
|
+
if (lacking !== undefined)
|
|
278
|
+
return { kind: "lacking", error: lacking };
|
|
279
|
+
return { kind: "loading", last: undefined, instance: undefined };
|
|
280
|
+
}
|
|
281
|
+
const state = this.#state;
|
|
282
|
+
const failure = state.kind === "failed"
|
|
283
|
+
? state.failure
|
|
284
|
+
: state.kind === "activating" && state.shown.kind === "failed"
|
|
285
|
+
? state.shown
|
|
286
|
+
: undefined;
|
|
287
|
+
if (failure !== undefined)
|
|
288
|
+
return { kind: "failed", error: failure.cause.error, last: shown, instance: exposed };
|
|
289
|
+
return { kind: "loading", last: shown, instance: exposed };
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* The instance its references follow now (they attach to it; they take last values only from an instance they
|
|
293
|
+
* attached to); `undefined` once it stopped changing.
|
|
294
|
+
*/
|
|
295
|
+
get attachable() {
|
|
296
|
+
return this.#following ? this.#exposed : undefined;
|
|
297
|
+
}
|
|
298
|
+
/** The live instance, which references pin their keys on (a new one: they pin again); `undefined` when not live. */
|
|
299
|
+
get instance() {
|
|
300
|
+
return this.#state.kind === "live" ? this.#state.attempt : undefined;
|
|
301
|
+
}
|
|
302
|
+
/** The live instance's state member `member` as a consumer of `version` follows it (a hold over a link). */
|
|
303
|
+
liveMember(member, version) {
|
|
304
|
+
return this.#live().memberAt(member, version);
|
|
305
|
+
}
|
|
306
|
+
/** How a consumer of `version` reads keyed member `member`'s documents: mapped back when older (`undefined`: as they are). */
|
|
307
|
+
keyedMapping(member, version) {
|
|
308
|
+
return this.#live().keyMapping(member, version);
|
|
309
|
+
}
|
|
310
|
+
/** Waits until `swap` ended (its new attempt live, parked, failed, or the object ended). */
|
|
311
|
+
async #gate(swap, context) {
|
|
312
|
+
// No timer of its own: the swap ends when its new attempt is live, parked or failed, and `readyTimeout` bounds
|
|
313
|
+
// the new attempt's own steps (Fable).
|
|
314
|
+
await awaitWithContext(swap.done.promise, context);
|
|
315
|
+
}
|
|
316
|
+
/** The keyed member `member` of the live object: its ultimate slot (slice 6a §12). */
|
|
317
|
+
keyedMember(member) {
|
|
318
|
+
return this.#live().keyedMember(member);
|
|
319
|
+
}
|
|
320
|
+
/** Pins `key` of keyed member `member` on the live instance, as a consumer of `version` reads it (`Attempt.pinKey`). */
|
|
321
|
+
pinKey(member, key, version, context) {
|
|
322
|
+
return this.#live().pinKey(member, key, version, context);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Counts `holder` as a reference to this object (the holder reads `state` itself), listed in its type's presence; a
|
|
326
|
+
* lingering object stays.
|
|
327
|
+
*/
|
|
328
|
+
hold(holder) {
|
|
329
|
+
// A version it binds whose member the live provider refuses (an older consumer): it waits unbound instead.
|
|
330
|
+
const state = this.#state;
|
|
331
|
+
const unfit = state.kind === "live" ? this.#unfit(holder, state.attempt) : undefined;
|
|
332
|
+
if (unfit !== undefined) {
|
|
333
|
+
this.#unbound(holder, unfit);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
this.#holders.add(holder);
|
|
337
|
+
this.#stopLingering();
|
|
338
|
+
// Last: a derive over the presence list may close a link synchronously, which may release this holder again.
|
|
339
|
+
this.host.referenced(this, holder, this.#context);
|
|
340
|
+
}
|
|
341
|
+
/** `holder` was released: the object may end (`#idle`). */
|
|
342
|
+
unhold(holder) {
|
|
343
|
+
if (!this.#holders.delete(holder))
|
|
344
|
+
return;
|
|
345
|
+
this.#dropUnheld(holder.contract.version);
|
|
346
|
+
this.#idle();
|
|
347
|
+
// Last: a derive over the presence list may close a link synchronously, which releases other holders again.
|
|
348
|
+
this.host.unreferenced(this, [holder], this.#context);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* The records of job `definition`'s runs, made by its first declaration. A later declaration (a new attempt's, after a
|
|
352
|
+
* reload) at another version takes the records over (each run keeps its version, slice 7b §8); one at the same
|
|
353
|
+
* version with another fingerprint is refused (`checkJob`).
|
|
354
|
+
*/
|
|
355
|
+
jobRecords(definition) {
|
|
356
|
+
const records = this.#jobs.get(definition.name);
|
|
357
|
+
if (records === undefined) {
|
|
358
|
+
const { store } = this.host;
|
|
359
|
+
const owner = {
|
|
360
|
+
label: this.label,
|
|
361
|
+
host: this.host,
|
|
362
|
+
context: this.#context,
|
|
363
|
+
documents: this.documents,
|
|
364
|
+
store: store === undefined ? undefined : { store, owner: this.served.contract.name },
|
|
365
|
+
countRuns: (delta) => this.countRuns(delta),
|
|
366
|
+
held: (deadline) => this.#heldUntil(deadline),
|
|
367
|
+
};
|
|
368
|
+
const made = new JobRecords(definition, owner);
|
|
369
|
+
this.#jobs.set(definition.name, made);
|
|
370
|
+
return made;
|
|
371
|
+
}
|
|
372
|
+
this.checkJob(definition);
|
|
373
|
+
records.redefine(definition);
|
|
374
|
+
return records;
|
|
375
|
+
}
|
|
376
|
+
/** Refuses a declaration of a job its records cannot take (`JobRecords.check`); a reload's staging checks it too. */
|
|
377
|
+
checkJob(definition) {
|
|
378
|
+
this.#jobs.get(definition.name)?.check(definition);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Claims table `table` (its SQL name) in the host's store for this object, until its end (slice 6b claims); held by
|
|
382
|
+
* another owner: `invalid/args`, which fails the declaring factory.
|
|
383
|
+
*/
|
|
384
|
+
claimTable(table) {
|
|
385
|
+
this.host.store.claims.table(table, this);
|
|
386
|
+
}
|
|
387
|
+
/** Claims this object's documents in `namespace` of the host's store, as `claimTable`. */
|
|
388
|
+
claimDocuments(namespace) {
|
|
389
|
+
this.host.store.claims.documents(this.served.contract.name, namespace, this);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* A runtime failure of the live attempt `attempt`: `broken` (a `migrate` failing on access, a stored version newer
|
|
393
|
+
* than the code, a refused commit) or `transient` (a followed runtime failed, R4): the attempt is sealed and the
|
|
394
|
+
* object `failed` with `cause`; calls reject with it, holders are told, its references keep their last values once the
|
|
395
|
+
* admitted commits adopted (`followed`), the natives close in the background (then its references are released),
|
|
396
|
+
* `onError` gets `object_failed` once. Documents and job runs stay. Recovery: a broken failure by `ref.retry()`, a
|
|
397
|
+
* transient one after its identity's backoff too (a new attempt, whose members its references follow once live). A
|
|
398
|
+
* failure of a sealed attempt is ignored, so several at once fail it once.
|
|
399
|
+
*/
|
|
400
|
+
failLive(attempt, cause) {
|
|
401
|
+
const state = this.#state;
|
|
402
|
+
if (state.kind !== "live" || state.attempt !== attempt)
|
|
403
|
+
return;
|
|
404
|
+
const { error } = cause;
|
|
405
|
+
if (cause.kind === "transient")
|
|
406
|
+
this.host.backoff.failed(this.identity);
|
|
407
|
+
else
|
|
408
|
+
this.host.backoff.delete(this.identity);
|
|
409
|
+
const failure = { kind: "failed", cause, retryAt: this.host.backoff.until(this.identity) };
|
|
410
|
+
this.#state = { kind: "failed", failure };
|
|
411
|
+
this.#lastFailure = error;
|
|
412
|
+
this.#withdraw(attempt);
|
|
413
|
+
attempt.seal(error);
|
|
414
|
+
// Its references follow every member on until the commits admitted before the seal adopted and published once
|
|
415
|
+
// (frames included), then stop. A retry's factory and hydration wait for both (its ending), so no old commit
|
|
416
|
+
// lands in a new attempt.
|
|
417
|
+
const frozen = this.documents.settled().then(() => this.#stopFollowing(attempt));
|
|
418
|
+
const closing = Promise.all([attempt.close(END), frozen]).then(([failures]) => {
|
|
419
|
+
attempt.detach();
|
|
420
|
+
attempt.releaseReferences();
|
|
421
|
+
return failures;
|
|
422
|
+
});
|
|
423
|
+
this.host.ending(this.identity, this.#reported(closing));
|
|
424
|
+
this.host.report({ kind: "object_failed", object: this.label, failure: cause });
|
|
425
|
+
this.#notify();
|
|
426
|
+
this.#idle();
|
|
427
|
+
}
|
|
428
|
+
/** A held state change must be stored by `deadline`: the timer is set for the earliest one. */
|
|
429
|
+
#heldUntil(deadline) {
|
|
430
|
+
if (this.#flush !== undefined && this.#flush.deadline <= deadline)
|
|
431
|
+
return;
|
|
432
|
+
if (this.#flush !== undefined)
|
|
433
|
+
clearTimeout(this.#flush.timer);
|
|
434
|
+
// A foreground timer: what is held is stored before the process may exit.
|
|
435
|
+
const timer = setTimeout(() => void this.#flushHeld(), Math.max(0, deadline - Date.now()));
|
|
436
|
+
this.#flush = { deadline, timer };
|
|
437
|
+
}
|
|
438
|
+
/** The timer fired: every held change past its deadline is stored, and the timer set for the next one. */
|
|
439
|
+
async #flushHeld() {
|
|
440
|
+
this.#flush = undefined;
|
|
441
|
+
if (this.#state.kind === "ended")
|
|
442
|
+
return;
|
|
443
|
+
const now = Date.now();
|
|
444
|
+
const jobs = [...this.#jobs.values()];
|
|
445
|
+
await Promise.all(jobs.map((records) => records.flushHeld(now)));
|
|
446
|
+
const next = Math.min(...jobs.map((records) => records.nextDeadline()));
|
|
447
|
+
if (Number.isFinite(next))
|
|
448
|
+
this.#heldUntil(next);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Adds `delta` to its running and finishing job runs (and `host.activity.jobs`). A new run keeps a lingering object;
|
|
452
|
+
* the last one settling on an object without references ends it as its last release would (`#idle`).
|
|
453
|
+
*/
|
|
454
|
+
countRuns(delta) {
|
|
455
|
+
this.#runs += delta;
|
|
456
|
+
this.host.count("jobs", delta);
|
|
457
|
+
// A run started while the object lingers keeps it, like a new reference.
|
|
458
|
+
if (delta > 0)
|
|
459
|
+
this.#stopLingering();
|
|
460
|
+
if (this.#runs === 0)
|
|
461
|
+
this.#idle();
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Throws `invalid/cycle` when waiting for `dependency` closes a chain of waits back to this object (Q5). Every other
|
|
465
|
+
* object on the chain fails broken with the same error, so no part of a cycle waits for a retry. Counts the objects
|
|
466
|
+
* it visits (`chord.cycle.visits`). Otherwise, a dependency whose activation is in this object's chain closes a
|
|
467
|
+
* cycle through other hosts (they fail through their dependency on this one).
|
|
468
|
+
*/
|
|
469
|
+
assertNoCycle(dependency, context) {
|
|
470
|
+
const visited = new Set();
|
|
471
|
+
const cycle = dependency.pathTo(this, visited);
|
|
472
|
+
context.telemetry.metrics?.counter("chord.cycle.visits").add(visited.size);
|
|
473
|
+
if (cycle === undefined) {
|
|
474
|
+
const across = dependency.activationId;
|
|
475
|
+
if (across === undefined || !this.chain.includes(across))
|
|
476
|
+
return;
|
|
477
|
+
throw this.host.cycle(this.chain, across, [this.label, dependency.label]);
|
|
478
|
+
}
|
|
479
|
+
const error = invalid("cycle", `dependency cycle: ${[this, ...cycle].map(({ label }) => label).join(" → ")}`);
|
|
480
|
+
for (const object of cycle) {
|
|
481
|
+
const state = object.#state;
|
|
482
|
+
if (object !== this && state.kind === "activating") {
|
|
483
|
+
state.attempt.abandon({ kind: "failed", cause: { kind: "broken", error } });
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
throw error;
|
|
487
|
+
}
|
|
488
|
+
/** Its parked attempt waits for `dependencies` (none once it leaves parking): the waits a cycle check follows. */
|
|
489
|
+
waitsFor(dependencies) {
|
|
490
|
+
this.#waitingFor = dependencies;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* A dependency of its current attempt changed (its state, or its first outcome): a parked attempt checks again; an
|
|
494
|
+
* attempt past its dependency check ignores it (R18 after live), and so does any other state.
|
|
495
|
+
*/
|
|
496
|
+
dependencyMoved() {
|
|
497
|
+
const state = this.#state;
|
|
498
|
+
if (state.kind === "activating")
|
|
499
|
+
state.attempt.dependencyMoved();
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Its attempt `attempt` is parked showing `shown` (`loading` or `failed { waiting }`): holders are told when that
|
|
503
|
+
* changed (a cause compared by value). `firstPass`: no blocker here is still without its first outcome, so this
|
|
504
|
+
* object has its first outcome now.
|
|
505
|
+
*/
|
|
506
|
+
parked(attempt, shown, firstPass) {
|
|
507
|
+
const state = this.#state;
|
|
508
|
+
if (state.kind !== "activating" || state.attempt !== attempt)
|
|
509
|
+
return;
|
|
510
|
+
const { swap } = state;
|
|
511
|
+
// A swap's new attempt parks (decision 4): no overlap of old and new code, holders see what it shows.
|
|
512
|
+
const parks = swap !== undefined && !swap.parked;
|
|
513
|
+
if (parks)
|
|
514
|
+
this.#swapParked(swap);
|
|
515
|
+
if (parks || !sameState(state.shown, shown)) {
|
|
516
|
+
this.#state = { kind: "activating", attempt, shown, ...(swap === undefined ? {} : { swap }) };
|
|
517
|
+
if (shown.kind === "failed")
|
|
518
|
+
this.#lastFailure = shown.cause.error;
|
|
519
|
+
this.#notify();
|
|
520
|
+
}
|
|
521
|
+
if (firstPass)
|
|
522
|
+
this.#settleFirstOutcome();
|
|
523
|
+
}
|
|
524
|
+
/** Its attempt `attempt` left parking for its own steps: it shows `loading` until its outcome. */
|
|
525
|
+
unparked(attempt) {
|
|
526
|
+
const state = this.#state;
|
|
527
|
+
if (state.kind !== "activating" || state.attempt !== attempt)
|
|
528
|
+
return;
|
|
529
|
+
if (!sameState(state.shown, LOADING))
|
|
530
|
+
this.parked(attempt, LOADING, false);
|
|
531
|
+
}
|
|
532
|
+
/** A swap's new attempt parked: the old attempt's contributions leave the tables (it is not live any more). */
|
|
533
|
+
#swapParked(swap) {
|
|
534
|
+
swap.parked = true;
|
|
535
|
+
this.#withdraw(swap.old);
|
|
536
|
+
swap.done.resolve();
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Ends the object (once): sealed now, its holders and running calls told `error` (`released` by default), torn down
|
|
540
|
+
* in the background with reason `end`, close failures reported.
|
|
541
|
+
*/
|
|
542
|
+
end(error = this.ended()) {
|
|
543
|
+
const teardown = this.#seal({ kind: "end", error });
|
|
544
|
+
if (teardown.kind !== "none")
|
|
545
|
+
this.host.ending(this.identity, this.#reported(this.#tearDown(teardown, END)));
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Ends the object for `host.close`: sealed now; returns its teardown (reason `close`), which the host runs once every
|
|
549
|
+
* object is sealed, so no reference it releases starts an ending in the background.
|
|
550
|
+
*/
|
|
551
|
+
stop() {
|
|
552
|
+
const teardown = this.#seal({ kind: "end", error: this.ended() });
|
|
553
|
+
return () => this.#tearDown(teardown, CLOSE);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Ends the object because a reload removed its type (slice 7b §4): as `end` (natives close with reason `end`,
|
|
557
|
+
* running calls' callers rejected `released`, handlers drained), but its holders' requests are not ended: they wait
|
|
558
|
+
* unbound with `cause` (`not_served`), references with their last values, until the next object of its identity
|
|
559
|
+
* binds them (`Removal`).
|
|
560
|
+
*/
|
|
561
|
+
remove(cause) {
|
|
562
|
+
const teardown = this.#seal({ kind: "removed", error: this.ended(), cause });
|
|
563
|
+
if (teardown.kind !== "none")
|
|
564
|
+
this.host.ending(this.identity, this.#reported(this.#tearDown(teardown, END)));
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* What a reload with `recorded` (the new factory's declarations) does to this object, whose type is still served:
|
|
568
|
+
* a live object swaps in place when neither its live attempt nor the new factory opens natives and no table of the
|
|
569
|
+
* new factory is newer than the store's, else it restarts; any other is retried.
|
|
570
|
+
*/
|
|
571
|
+
reloadFate(recorded) {
|
|
572
|
+
const state = this.#state;
|
|
573
|
+
if (state.kind !== "live")
|
|
574
|
+
return "retry";
|
|
575
|
+
if (state.attempt.opensNatives || recorded.natives > 0 || migratesTables(this, recorded))
|
|
576
|
+
return "restart";
|
|
577
|
+
return "swap";
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Takes `fate` with its new served type (after the reload's commit); returns the new attempt, whose first
|
|
581
|
+
* dependency check the reload's report waits for.
|
|
582
|
+
*/
|
|
583
|
+
reload(served, fate) {
|
|
584
|
+
// Its members per version stay: the previous version's are mapped once the new attempt goes live.
|
|
585
|
+
this.served = served;
|
|
586
|
+
const attempt = fate === "swap" ? this.#swap() : fate === "restart" ? this.#restart() : this.#retryReloaded();
|
|
587
|
+
attempt.startedByReload();
|
|
588
|
+
return attempt;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* A pure swap (slice 7b §5): a new attempt of the same object (its documents, line and job records, its instance id),
|
|
592
|
+
* its activation at once; the live attempt keeps its running calls, its routines aborted, its jobs handed over,
|
|
593
|
+
* and is sealed once its calls settled and the new attempt's requests bound (`#retire`). Calls arriving meanwhile
|
|
594
|
+
* wait at the gate.
|
|
595
|
+
*/
|
|
596
|
+
#swap() {
|
|
597
|
+
// A swap starts from a live object (`reloadFate`).
|
|
598
|
+
const old = this.#state.attempt;
|
|
599
|
+
const ending = this.host.endingOf(this.identity);
|
|
600
|
+
const attempt = new Attempt(this, this.#context);
|
|
601
|
+
const swap = { old, parked: false, done: Promise.withResolvers() };
|
|
602
|
+
this.#state = { kind: "activating", attempt, shown: LOADING, swap };
|
|
603
|
+
old.handOver();
|
|
604
|
+
this.#retiringAdd(old, this.#retire(swap));
|
|
605
|
+
this.#notify();
|
|
606
|
+
void this.#run(attempt, ending);
|
|
607
|
+
return attempt;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Keeps `retire` (a swapped-out attempt's) until it settled: a restart, an end and the host's close wait for it; a
|
|
611
|
+
* later swap does not (it holds no natives, its documents are the object's: Fable, Opus F1), so a second reload is
|
|
612
|
+
* never held up by the first one's old calls.
|
|
613
|
+
*/
|
|
614
|
+
#retiringAdd(old, retire) {
|
|
615
|
+
this.#retiring ??= new Map();
|
|
616
|
+
const retiring = this.#retiring;
|
|
617
|
+
retiring.set(old, retire);
|
|
618
|
+
void retire.finally(() => {
|
|
619
|
+
retiring.delete(old);
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
/** Its swapped-out attempts still retiring, as one wait; `undefined` when none is. */
|
|
623
|
+
#retiringNow() {
|
|
624
|
+
const retiring = this.#retiring;
|
|
625
|
+
if (retiring === undefined || retiring.size === 0)
|
|
626
|
+
return undefined;
|
|
627
|
+
return Promise.all(retiring.values()).then(() => { });
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Seals a swapped attempt once its running calls (and routine calls) settled, bounded by `closeTimeout`, and the swap
|
|
631
|
+
* ended (the new attempt live, parked, failed: its requests bound, so no request it shares with the old one ends in
|
|
632
|
+
* between, M§3.9, and its holders compared the old members with the new); a parked swap's references take their last
|
|
633
|
+
* values from it once the commits it admitted before the seal published; then its references are released. Its job
|
|
634
|
+
* invocations run on, on their old code.
|
|
635
|
+
*/
|
|
636
|
+
async #retire({ old, done }) {
|
|
637
|
+
await Promise.all([old.drainCalls(), done.promise]);
|
|
638
|
+
old.seal(this.#reloaded());
|
|
639
|
+
// A parked swap's old instance stops changing once its admitted commits published (its successor, live, took over
|
|
640
|
+
// its references before).
|
|
641
|
+
await this.documents.settled();
|
|
642
|
+
this.#stopFollowing(old);
|
|
643
|
+
const failures = await old.close(END);
|
|
644
|
+
old.detach();
|
|
645
|
+
old.releaseReferences();
|
|
646
|
+
for (const failure of failures)
|
|
647
|
+
this.host.report(failure);
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* A native restart (decision "A native restart drains first"): new calls park (it shows `loading`), its
|
|
651
|
+
* contributions leave, the live attempt's running calls drain (bounded by `closeTimeout`), then it is sealed (its
|
|
652
|
+
* in-memory job runs end `aborted { reload }`), its references take their last values once its admitted commits
|
|
653
|
+
* published, its natives close with reason `reload`; the new attempt, a new instance (D4), activates after that
|
|
654
|
+
* teardown.
|
|
655
|
+
*/
|
|
656
|
+
#restart() {
|
|
657
|
+
const old = this.#state.attempt;
|
|
658
|
+
this.#withdraw(old);
|
|
659
|
+
old.stopRoutines();
|
|
660
|
+
this.#instance = uuidv7();
|
|
661
|
+
const teardown = (async () => {
|
|
662
|
+
await Promise.all([old.drainCalls(), this.#retiringNow()]);
|
|
663
|
+
old.seal(this.#reloaded(), "reload");
|
|
664
|
+
// Drained and sealed: its references take their last values once the commits it admitted before published
|
|
665
|
+
// (a store write is not a running call's promise; Sol).
|
|
666
|
+
await this.documents.settled();
|
|
667
|
+
this.#stopFollowing(old);
|
|
668
|
+
const failures = await old.close(RELOAD);
|
|
669
|
+
old.detach();
|
|
670
|
+
old.releaseReferences();
|
|
671
|
+
return failures;
|
|
672
|
+
})();
|
|
673
|
+
this.host.ending(this.identity, this.#reported(teardown));
|
|
674
|
+
const attempt = this.#replace();
|
|
675
|
+
void this.#run(attempt, this.host.endingOf(this.identity));
|
|
676
|
+
return attempt;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* A reload retries an object that is not live (slice 7b §9, decision 1): a parked attempt is replaced in one
|
|
680
|
+
* handover (it opened nothing: the new attempt's requests bind before the old ones are released, M§3.9); an attempt
|
|
681
|
+
* in its own steps is sealed, its natives close with reason `reload`, and the new one activates after that teardown;
|
|
682
|
+
* a failed or waiting one gets an attempt now, its backoff skipped.
|
|
683
|
+
*/
|
|
684
|
+
#retryReloaded() {
|
|
685
|
+
const state = this.#state;
|
|
686
|
+
if (state.kind === "activating") {
|
|
687
|
+
const { attempt: old, swap } = state;
|
|
688
|
+
if (swap !== undefined && !swap.parked)
|
|
689
|
+
this.#swapParked(swap);
|
|
690
|
+
swap?.done.resolve();
|
|
691
|
+
const parked = old.isParked;
|
|
692
|
+
// A parked attempt's successor waits for no teardown of it (its references are released after it bound).
|
|
693
|
+
const ending = this.host.endingOf(this.identity);
|
|
694
|
+
old.seal(this.#reloaded(), "reload");
|
|
695
|
+
const attempt = this.#replace();
|
|
696
|
+
if (parked)
|
|
697
|
+
void this.#run(attempt, ending);
|
|
698
|
+
const after = parked ? attempt.checked : Promise.resolve();
|
|
699
|
+
const closing = after
|
|
700
|
+
.then(() => old.close(RELOAD))
|
|
701
|
+
.then((failures) => {
|
|
702
|
+
old.detach();
|
|
703
|
+
old.releaseReferences();
|
|
704
|
+
return failures;
|
|
705
|
+
});
|
|
706
|
+
this.host.ending(this.identity, this.#reported(closing));
|
|
707
|
+
if (!parked)
|
|
708
|
+
void this.#run(attempt, this.host.endingOf(this.identity));
|
|
709
|
+
return attempt;
|
|
710
|
+
}
|
|
711
|
+
this.host.backoff.skip(this.identity);
|
|
712
|
+
// Waiting or failed (`reloadFate`): an attempt starts.
|
|
713
|
+
return this.attempt();
|
|
714
|
+
}
|
|
715
|
+
/** A new attempt replacing the current one, holders told; its caller starts it (`#run`) after what it waits for. */
|
|
716
|
+
#replace() {
|
|
717
|
+
const attempt = new Attempt(this, this.#context);
|
|
718
|
+
this.#state = { kind: "activating", attempt, shown: LOADING };
|
|
719
|
+
this.#notify();
|
|
720
|
+
return attempt;
|
|
721
|
+
}
|
|
722
|
+
/** The `released` error of an attempt a reload replaced. */
|
|
723
|
+
#reloaded() {
|
|
724
|
+
return new ChordError({ code: "released", reason: "ended", message: `${this.label}: replaced by a reload` });
|
|
725
|
+
}
|
|
726
|
+
/** The `released` error of this object. */
|
|
727
|
+
ended() {
|
|
728
|
+
return new ChordError({ code: "released", reason: "ended", message: `${this.label}: ended` });
|
|
729
|
+
}
|
|
730
|
+
/** Runs `attempt`'s activation once `ending` (its predecessors' teardowns, if any) finished; takes its outcome. */
|
|
731
|
+
async #run(attempt, ending) {
|
|
732
|
+
const outcome = await attempt.activate(ending);
|
|
733
|
+
// The object may have ended after the activation's last step.
|
|
734
|
+
if (this.#state.kind !== "activating" || this.#state.attempt !== attempt)
|
|
735
|
+
return;
|
|
736
|
+
switch (outcome.kind) {
|
|
737
|
+
case "live":
|
|
738
|
+
return this.#wentLive(attempt);
|
|
739
|
+
case "failed":
|
|
740
|
+
return this.#failed(attempt, outcome.cause);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
#wentLive(attempt) {
|
|
744
|
+
if (this.#wakes !== undefined)
|
|
745
|
+
this.#wakes.during = undefined;
|
|
746
|
+
const swap = this.#swapOf(attempt);
|
|
747
|
+
// Before the new instance is shown: holders of a version its provider does not bind leave with their last values,
|
|
748
|
+
// which their references take from the instance shown so far.
|
|
749
|
+
const unbound = this.#unbindUnfit(attempt);
|
|
750
|
+
this.#state = { kind: "live", attempt };
|
|
751
|
+
this.#exposed = attempt;
|
|
752
|
+
this.#following = true;
|
|
753
|
+
const { contributions } = attempt;
|
|
754
|
+
// The old attempt's contributions leave in the batch the new ones enter (slice 7b §5), so no reader sees a gap.
|
|
755
|
+
const leaving = swap !== undefined && !swap.parked ? swap.old.contributions : NO_CONTRIBUTIONS;
|
|
756
|
+
// In the registries' tables before anyone sees it live (a getter released now reads them recomposed).
|
|
757
|
+
if (contributions.length > 0 || leaving.length > 0) {
|
|
758
|
+
this.host.batch.within(() => {
|
|
759
|
+
for (const contribution of leaving)
|
|
760
|
+
contribution.record.remove(contribution);
|
|
761
|
+
for (const contribution of contributions)
|
|
762
|
+
contribution.record.add(contribution);
|
|
763
|
+
}, this.#context);
|
|
764
|
+
}
|
|
765
|
+
this.#lastFailure = undefined;
|
|
766
|
+
this.host.wentLive(this);
|
|
767
|
+
// Its references move to the new instance (one frame each); holds get a fresh `bound`.
|
|
768
|
+
this.#notify();
|
|
769
|
+
this.#settleFirstOutcome();
|
|
770
|
+
swap?.done.resolve();
|
|
771
|
+
// A swap's routines start once the old attempt's routine calls finished (the handover, §14).
|
|
772
|
+
attempt.live(swap?.old);
|
|
773
|
+
this.#takeJobs(attempt);
|
|
774
|
+
// Its last holders may have left for their version: it ends as at their release.
|
|
775
|
+
if (unbound)
|
|
776
|
+
this.#idle();
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* After `attempt` went live: the jobs it does not declare block their runs (slice 7b §8); after a reload, the blocked
|
|
780
|
+
* runs of the jobs it declares are retried.
|
|
781
|
+
*/
|
|
782
|
+
#takeJobs(attempt) {
|
|
783
|
+
if (this.#jobs.size === 0)
|
|
784
|
+
return;
|
|
785
|
+
const reloaded = attempt.reloadStarted;
|
|
786
|
+
for (const [name, records] of this.#jobs) {
|
|
787
|
+
if (!attempt.declaresJob(name))
|
|
788
|
+
records.undeclare();
|
|
789
|
+
else if (reloaded)
|
|
790
|
+
void records.retryBlocked(this.#context);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Its holders whose version `attempt`'s provider (going live) does not bind (a reload dropped it, slice 7b §6), or
|
|
795
|
+
* of which it refuses a member (`contract_mismatch`), leave it: they wait unbound `version` (`failed { waiting }`),
|
|
796
|
+
* references with their last values, until a publication serves their version again. The object and its other
|
|
797
|
+
* holders stay.
|
|
798
|
+
*/
|
|
799
|
+
#unbindUnfit(attempt) {
|
|
800
|
+
let unfit;
|
|
801
|
+
for (const holder of this.#holders) {
|
|
802
|
+
const error = this.#unfit(holder, attempt);
|
|
803
|
+
if (error === undefined)
|
|
804
|
+
continue;
|
|
805
|
+
unfit ??= [];
|
|
806
|
+
unfit.push([holder, error]);
|
|
807
|
+
}
|
|
808
|
+
if (unfit === undefined)
|
|
809
|
+
return false;
|
|
810
|
+
for (const [holder] of unfit)
|
|
811
|
+
this.#holders.delete(holder);
|
|
812
|
+
this.host.unreferenced(this, unfit.map(([holder]) => holder), this.#context);
|
|
813
|
+
for (const [holder, error] of unfit)
|
|
814
|
+
this.#unbound(holder, error);
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
/** Whether a holder of `version` holds it. */
|
|
818
|
+
#heldAt(version) {
|
|
819
|
+
for (const holder of this.#holders)
|
|
820
|
+
if (holder.contract.version === version)
|
|
821
|
+
return true;
|
|
822
|
+
return false;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Why `holder` cannot bind to `attempt` (live): its version is not one the provider binds, or the provider refuses a
|
|
826
|
+
* member of it (`contract_mismatch`); `undefined` when it binds.
|
|
827
|
+
*/
|
|
828
|
+
#unfit(holder, attempt) {
|
|
829
|
+
const { contract, provider } = this.served;
|
|
830
|
+
const { version, fingerprint } = holder.contract;
|
|
831
|
+
if (version === contract.version && fingerprint === contract.fingerprint)
|
|
832
|
+
return undefined;
|
|
833
|
+
if (binds(provider, version, fingerprint))
|
|
834
|
+
return refusal(this.served, version, attempt.variant);
|
|
835
|
+
return new ChordError({ code: "contract_mismatch", message: `${contract.name} v${version} is not served here` });
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* `holder` (no longer held) waits unbound with `error` (`failed { waiting }`) until a publication fits it.
|
|
839
|
+
*/
|
|
840
|
+
#unbound(holder, error) {
|
|
841
|
+
const cause = { kind: "waiting", error };
|
|
842
|
+
holder.removed({ cause, host: this.host, params: this.checkedParams, context: this.#context });
|
|
843
|
+
}
|
|
844
|
+
/** The swap `attempt` (still the current one) ends: `undefined` when it is no swap's new attempt. */
|
|
845
|
+
#swapOf(attempt) {
|
|
846
|
+
const state = this.#state;
|
|
847
|
+
return state.kind === "activating" && state.attempt === attempt ? state.swap : undefined;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Records a failed attempt: reported, torn down in the background (reason `end`), its references released once its
|
|
851
|
+
* natives closed, its holders told. Transient: a backoff window, whose end is the failure's `retryAt`; broken: no
|
|
852
|
+
* automatic retry.
|
|
853
|
+
*/
|
|
854
|
+
#failed(attempt, cause) {
|
|
855
|
+
const swap = this.#swapOf(attempt);
|
|
856
|
+
if (swap !== undefined && !swap.parked)
|
|
857
|
+
this.#swapParked(swap);
|
|
858
|
+
swap?.done.resolve();
|
|
859
|
+
const wokenBy = this.#wakes?.during === attempt;
|
|
860
|
+
if (this.#wakes !== undefined)
|
|
861
|
+
this.#wakes.during = undefined;
|
|
862
|
+
if (cause.kind === "transient")
|
|
863
|
+
this.host.backoff.failed(this.identity);
|
|
864
|
+
else
|
|
865
|
+
this.host.backoff.delete(this.identity);
|
|
866
|
+
const failure = { kind: "failed", cause, retryAt: this.host.backoff.until(this.identity) };
|
|
867
|
+
this.#state = { kind: "failed", failure };
|
|
868
|
+
this.#lastFailure = cause.error;
|
|
869
|
+
attempt.seal(this.ended());
|
|
870
|
+
const closing = attempt.close(END).then((failures) => {
|
|
871
|
+
attempt.detach();
|
|
872
|
+
// Released once its natives closed (a close may use them, §6, §13).
|
|
873
|
+
attempt.releaseReferences();
|
|
874
|
+
return failures;
|
|
875
|
+
});
|
|
876
|
+
this.host.ending(this.identity, this.#reported(closing));
|
|
877
|
+
this.host.report({ kind: "activation_failed", object: this.label, failure: cause });
|
|
878
|
+
this.#notify();
|
|
879
|
+
this.#settleFirstOutcome();
|
|
880
|
+
// Job runs kept it while it activated; failed, they keep it no longer.
|
|
881
|
+
this.#idle();
|
|
882
|
+
// A wake signal arrived while it activated: it retries it now.
|
|
883
|
+
if (wokenBy)
|
|
884
|
+
this.retry();
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* A wake signal's new value (inside its batch): retries a failed object (after the batch: a factory may not run in
|
|
888
|
+
* one), remembered while it activates, ignored while live and when its own contributions' leaving made it.
|
|
889
|
+
*/
|
|
890
|
+
#wake() {
|
|
891
|
+
const state = this.#state;
|
|
892
|
+
// Called by its wakes only.
|
|
893
|
+
const wakes = this.#wakes;
|
|
894
|
+
if (state.kind === "activating") {
|
|
895
|
+
// While parked its dependencies decide (dependency model §3.8).
|
|
896
|
+
if (!state.attempt.isParked)
|
|
897
|
+
wakes.during = state.attempt;
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
if (state.kind !== "failed" || wakes.leaving)
|
|
901
|
+
return;
|
|
902
|
+
queueMicrotask(() => this.retry());
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* The live attempt `attempt` leaves the registries' tables (it fails or ends), inside a batch; a composition this
|
|
906
|
+
* leaving makes wakes no wake signal of this object.
|
|
907
|
+
*/
|
|
908
|
+
#withdraw(attempt) {
|
|
909
|
+
const { contributions } = attempt;
|
|
910
|
+
if (contributions.length === 0)
|
|
911
|
+
return;
|
|
912
|
+
const { batch } = this.host;
|
|
913
|
+
const wakes = this.#wakes;
|
|
914
|
+
batch.within(() => {
|
|
915
|
+
if (wakes !== undefined) {
|
|
916
|
+
wakes.leaving = true;
|
|
917
|
+
batch.flushing(() => {
|
|
918
|
+
wakes.leaving = false;
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
for (const contribution of contributions)
|
|
922
|
+
contribution.record.remove(contribution);
|
|
923
|
+
}, this.#context);
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* `attempt`, the instance shown, stopped changing (a live failure's admitted commits published, a restart's drain, a
|
|
927
|
+
* swapped or parked old instance retiring): its references take their last values from it, holds leave it, and the
|
|
928
|
+
* object lets it go (a reference made later never attached to it: it takes nothing from it).
|
|
929
|
+
*/
|
|
930
|
+
#stopFollowing(attempt) {
|
|
931
|
+
if (this.#exposed !== attempt || !this.#following)
|
|
932
|
+
return;
|
|
933
|
+
this.#following = false;
|
|
934
|
+
this.#notify();
|
|
935
|
+
// Its references took their values (`#notify` retargets them at once): a failed object keeps no ended instance.
|
|
936
|
+
this.#exposed = undefined;
|
|
937
|
+
}
|
|
938
|
+
/** Tells every holder that the state changed: references first follow what it shows now (`followed`). */
|
|
939
|
+
#notify() {
|
|
940
|
+
const holders = [...this.#holders];
|
|
941
|
+
// In one batch when some reference's members move (one frame each, a diamond over several sees one change); no
|
|
942
|
+
// commit at all for references that used none (activation churn).
|
|
943
|
+
const retarget = () => {
|
|
944
|
+
for (const holder of holders)
|
|
945
|
+
holder.retarget();
|
|
946
|
+
};
|
|
947
|
+
if (holders.some((holder) => holder.following))
|
|
948
|
+
this.host.batch.within(retarget, this.#context);
|
|
949
|
+
else
|
|
950
|
+
retarget();
|
|
951
|
+
for (const holder of holders)
|
|
952
|
+
holder.moved();
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Marks the object ended: forgotten by the host, waits rejected, references to it ended with `error` (and gone from
|
|
956
|
+
* its type's presence), its job runs ended (signals fired, waiters rejected), its transactions refused, its attempt
|
|
957
|
+
* sealed. Returns what is left to tear down; it releases nothing itself.
|
|
958
|
+
*/
|
|
959
|
+
#seal(ending) {
|
|
960
|
+
const { error } = ending;
|
|
961
|
+
const state = this.#state;
|
|
962
|
+
if (state.kind === "ended")
|
|
963
|
+
return { kind: "none" };
|
|
964
|
+
const endings = this.host.endingOf(this.identity);
|
|
965
|
+
// Its ending rejects the callers of its swapped-out attempts' calls too, at once.
|
|
966
|
+
if (this.#retiring !== undefined)
|
|
967
|
+
for (const old of this.#retiring.keys())
|
|
968
|
+
old.seal(error);
|
|
969
|
+
const retiring = this.#retiringNow();
|
|
970
|
+
// Its swapped-out attempts end before its teardown completes (they share its documents).
|
|
971
|
+
const previous = retiring === undefined ? endings : Promise.all([endings, retiring]).then(() => { });
|
|
972
|
+
this.#state = { kind: "ended", ended: { kind: "ended", error } };
|
|
973
|
+
for (const records of this.#jobs.values())
|
|
974
|
+
records.end(error);
|
|
975
|
+
if (this.#flush !== undefined)
|
|
976
|
+
clearTimeout(this.#flush.timer);
|
|
977
|
+
this.#flush = undefined;
|
|
978
|
+
this.documents.seal();
|
|
979
|
+
this.#stopLingering();
|
|
980
|
+
this.#wakes?.stop();
|
|
981
|
+
this.host.forget(this);
|
|
982
|
+
// An object of the start barrier's cohort that ends before its first outcome settles it as ended.
|
|
983
|
+
this.#settleFirstOutcome();
|
|
984
|
+
// Sealed: its instance stops changing; its references take their last values from it.
|
|
985
|
+
this.#following = false;
|
|
986
|
+
const holders = [...this.#holders];
|
|
987
|
+
this.#holders.clear();
|
|
988
|
+
this.host.unreferenced(this, holders, this.#context);
|
|
989
|
+
// Its type removed: its references wait with their last values, which they take from the instance shown (still
|
|
990
|
+
// here); otherwise they end with it.
|
|
991
|
+
const removal = ending.kind === "removed"
|
|
992
|
+
? { cause: ending.cause, host: this.host, params: this.checkedParams, context: this.#context }
|
|
993
|
+
: undefined;
|
|
994
|
+
for (const holder of holders) {
|
|
995
|
+
if (removal === undefined)
|
|
996
|
+
holder.end(error);
|
|
997
|
+
else
|
|
998
|
+
holder.removed(removal);
|
|
999
|
+
}
|
|
1000
|
+
this.#exposed = undefined;
|
|
1001
|
+
if (state.kind === "activating" && state.swap !== undefined) {
|
|
1002
|
+
if (!state.swap.parked)
|
|
1003
|
+
this.#withdraw(state.swap.old);
|
|
1004
|
+
state.swap.old.seal(error);
|
|
1005
|
+
state.swap.done.resolve();
|
|
1006
|
+
}
|
|
1007
|
+
// A failed attempt is closed (or closing) since it failed.
|
|
1008
|
+
if (state.kind === "waiting" || state.kind === "failed")
|
|
1009
|
+
return { kind: "end", previous };
|
|
1010
|
+
if (state.kind === "live")
|
|
1011
|
+
this.#withdraw(state.attempt);
|
|
1012
|
+
state.attempt.seal(error);
|
|
1013
|
+
return { kind: "close", attempt: state.attempt, previous };
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* The last holder of `version` left: the shown instance's shared mapping for it goes (Opus F2), so a long-lived
|
|
1017
|
+
* object keeps no mapped value nobody reads.
|
|
1018
|
+
*/
|
|
1019
|
+
#dropUnheld(version) {
|
|
1020
|
+
if (this.#heldAt(version))
|
|
1021
|
+
return;
|
|
1022
|
+
this.#exposed?.dropVersion(version);
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* A remote object or a local one with params ends once it has no references and no running or finishing job runs:
|
|
1026
|
+
* a live one once its type's `linger` passed without a new reference, any other at once.
|
|
1027
|
+
*/
|
|
1028
|
+
#idle() {
|
|
1029
|
+
const kind = this.#state.kind;
|
|
1030
|
+
// A run waiting for a live attempt keeps its object only while one is live or activating.
|
|
1031
|
+
const running = this.#runs > 0 && (kind === "live" || kind === "activating");
|
|
1032
|
+
const kept = this.#holders.size > 0 || running || (this.served.kind === "local" && this.served.hostLifetime);
|
|
1033
|
+
if (kept || this.#state.kind === "ended" || this.#lingering !== undefined)
|
|
1034
|
+
return;
|
|
1035
|
+
if (this.#state.kind !== "live" || this.served.linger === 0) {
|
|
1036
|
+
this.end();
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
// A new holder clears the timer (`hold`), so an expiry finds none.
|
|
1040
|
+
this.#lingering = setTimeout(() => {
|
|
1041
|
+
this.#stopLingering();
|
|
1042
|
+
this.end();
|
|
1043
|
+
}, this.served.linger);
|
|
1044
|
+
this.host.count("lingering", 1);
|
|
1045
|
+
}
|
|
1046
|
+
/** Its linger timer stops (a new holder, its expiry, its end): no longer counted as lingering. */
|
|
1047
|
+
#stopLingering() {
|
|
1048
|
+
if (this.#lingering === undefined)
|
|
1049
|
+
return;
|
|
1050
|
+
clearTimeout(this.#lingering);
|
|
1051
|
+
this.#lingering = undefined;
|
|
1052
|
+
this.host.count("lingering", -1);
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Once the previous teardowns finished (a failed attempt's closes may read the documents): drains and closes a
|
|
1056
|
+
* sealed attempt, then releases its references (after the closes, which may use them), then waits for an admitted
|
|
1057
|
+
* commit step to adopt and drops the documents and job runs. Resolves with the closes that threw.
|
|
1058
|
+
*/
|
|
1059
|
+
async #tearDown(teardown, reason) {
|
|
1060
|
+
if (teardown.kind === "none")
|
|
1061
|
+
return [];
|
|
1062
|
+
await teardown.previous;
|
|
1063
|
+
const failures = teardown.kind === "close" ? await teardown.attempt.close(reason) : [];
|
|
1064
|
+
if (teardown.kind === "close") {
|
|
1065
|
+
teardown.attempt.detach();
|
|
1066
|
+
teardown.attempt.releaseReferences();
|
|
1067
|
+
}
|
|
1068
|
+
await this.documents.settled();
|
|
1069
|
+
this.documents.end();
|
|
1070
|
+
this.host.store?.claims.release(this);
|
|
1071
|
+
for (const records of this.#jobs.values())
|
|
1072
|
+
records.drop();
|
|
1073
|
+
this.#jobs.clear();
|
|
1074
|
+
return failures;
|
|
1075
|
+
}
|
|
1076
|
+
/** Reports the close failures of a teardown nobody waits for. */
|
|
1077
|
+
async #reported(closing) {
|
|
1078
|
+
for (const failure of await closing)
|
|
1079
|
+
this.host.report(failure);
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* The live attempt; `not_ready` before the object went live and while it activates again, the cause while failed,
|
|
1083
|
+
* `released` once it ended.
|
|
1084
|
+
*/
|
|
1085
|
+
#live() {
|
|
1086
|
+
const state = this.#state;
|
|
1087
|
+
if (state.kind === "live")
|
|
1088
|
+
return state.attempt;
|
|
1089
|
+
if (state.kind === "ended")
|
|
1090
|
+
throw this.ended();
|
|
1091
|
+
if (state.kind === "failed")
|
|
1092
|
+
throw state.failure.cause.error;
|
|
1093
|
+
throw new ChordError({ code: "not_ready", message: `${this.label}: not live yet` });
|
|
1094
|
+
}
|
|
1095
|
+
/** The settlement of its first outcome (once): dependents parked on it check their first pass again. */
|
|
1096
|
+
#settleFirstOutcome() {
|
|
1097
|
+
if (this.#hasFirstOutcome)
|
|
1098
|
+
return;
|
|
1099
|
+
this.#hasFirstOutcome = true;
|
|
1100
|
+
this.#firstOutcome?.resolve();
|
|
1101
|
+
this.#firstOutcome = undefined;
|
|
1102
|
+
for (const holder of this.#holders)
|
|
1103
|
+
holder.dependent?.dependencyMoved();
|
|
1104
|
+
}
|
|
1105
|
+
/** The chain of waits from this activation to `target` (see `Target`), through its parked attempt's dependencies. */
|
|
1106
|
+
pathTo(target, visited) {
|
|
1107
|
+
if (this === target)
|
|
1108
|
+
return [this];
|
|
1109
|
+
visited.add(this);
|
|
1110
|
+
for (const dependency of this.#waitingFor) {
|
|
1111
|
+
const next = dependency.kind === "reference" ? dependency.binding.target : undefined;
|
|
1112
|
+
if (next === undefined || visited.has(next))
|
|
1113
|
+
continue;
|
|
1114
|
+
const rest = next.pathTo(target, visited);
|
|
1115
|
+
if (rest !== undefined)
|
|
1116
|
+
return [this, ...rest];
|
|
1117
|
+
}
|
|
1118
|
+
return undefined;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
/** Whether two states of a reference say the same: the same object, or failures with the same cause (by value). */
|
|
1122
|
+
function sameState(a, b) {
|
|
1123
|
+
if (a === b)
|
|
1124
|
+
return true;
|
|
1125
|
+
return a.kind === "failed" && b.kind === "failed" && a.retryAt === b.retryAt && sameCause(a.cause, b.cause);
|
|
1126
|
+
}
|
|
1127
|
+
//# sourceMappingURL=object.js.map
|