@earendil-works/chord 0.87.1 → 0.99.1

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.
Files changed (99) hide show
  1. package/README.md +80 -27
  2. package/dist/api.d.ts +6 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +8 -3
  5. package/dist/api.js.map +1 -1
  6. package/dist/bundler.d.ts.map +1 -1
  7. package/dist/context/index.d.ts.map +1 -1
  8. package/dist/context/index.js.map +1 -1
  9. package/dist/delta/apply-immutable-trusted.d.ts +4 -0
  10. package/dist/delta/apply-immutable-trusted.d.ts.map +1 -0
  11. package/dist/delta/apply-immutable-trusted.js +127 -0
  12. package/dist/delta/apply-immutable-trusted.js.map +1 -0
  13. package/dist/{state → delta}/diff.d.ts +1 -1
  14. package/dist/delta/diff.d.ts.map +1 -0
  15. package/dist/delta/diff.js +433 -0
  16. package/dist/delta/diff.js.map +1 -0
  17. package/dist/delta/draft.d.ts +5 -0
  18. package/dist/delta/draft.d.ts.map +1 -0
  19. package/dist/delta/draft.js +2 -0
  20. package/dist/delta/draft.js.map +1 -0
  21. package/dist/delta/index.d.ts +11 -21
  22. package/dist/delta/index.d.ts.map +1 -1
  23. package/dist/delta/index.js +43 -1341
  24. package/dist/delta/index.js.map +1 -1
  25. package/dist/delta/revision-validator.d.ts +7 -0
  26. package/dist/delta/revision-validator.d.ts.map +1 -0
  27. package/dist/delta/revision-validator.js +71 -0
  28. package/dist/delta/revision-validator.js.map +1 -0
  29. package/dist/delta/tracker.d.ts +26 -0
  30. package/dist/delta/tracker.d.ts.map +1 -0
  31. package/dist/delta/tracker.js +2069 -0
  32. package/dist/delta/tracker.js.map +1 -0
  33. package/dist/facets/host.d.ts.map +1 -1
  34. package/dist/facets/host.js.map +1 -1
  35. package/dist/facets/loader.d.ts.map +1 -1
  36. package/dist/facets/loader.js.map +1 -1
  37. package/dist/index.d.ts +3 -3
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/json.d.ts +6 -0
  42. package/dist/json.d.ts.map +1 -1
  43. package/dist/json.js +73 -6
  44. package/dist/json.js.map +1 -1
  45. package/dist/node/bundle-loader.d.ts.map +1 -1
  46. package/dist/node/bundle-loader.js.map +1 -1
  47. package/dist/node/bundle.d.ts.map +1 -1
  48. package/dist/node/bundle.js.map +1 -1
  49. package/dist/node/manifest.d.ts.map +1 -1
  50. package/dist/node/package.d.ts.map +1 -1
  51. package/dist/node/package.js.map +1 -1
  52. package/dist/node.d.ts.map +1 -1
  53. package/dist/services/consumer.d.ts.map +1 -1
  54. package/dist/services/consumer.js +49 -1
  55. package/dist/services/consumer.js.map +1 -1
  56. package/dist/services/errors.d.ts.map +1 -1
  57. package/dist/services/errors.js.map +1 -1
  58. package/dist/services/handle.d.ts.map +1 -1
  59. package/dist/services/handle.js +3 -1
  60. package/dist/services/handle.js.map +1 -1
  61. package/dist/services/instances.d.ts +1 -0
  62. package/dist/services/instances.d.ts.map +1 -1
  63. package/dist/services/instances.js +3 -0
  64. package/dist/services/instances.js.map +1 -1
  65. package/dist/services/loopback.d.ts.map +1 -1
  66. package/dist/services/loopback.js.map +1 -1
  67. package/dist/services/provider.d.ts.map +1 -1
  68. package/dist/services/provider.js +48 -29
  69. package/dist/services/provider.js.map +1 -1
  70. package/dist/services/state-codec.d.ts.map +1 -1
  71. package/dist/services/state-codec.js +18 -0
  72. package/dist/services/state-codec.js.map +1 -1
  73. package/dist/services/state-internals.d.ts +5 -2
  74. package/dist/services/state-internals.d.ts.map +1 -1
  75. package/dist/services/state-internals.js.map +1 -1
  76. package/dist/services/state.d.ts +8 -3
  77. package/dist/services/state.d.ts.map +1 -1
  78. package/dist/services/state.js +288 -88
  79. package/dist/services/state.js.map +1 -1
  80. package/dist/services/wire.d.ts +3 -0
  81. package/dist/services/wire.d.ts.map +1 -1
  82. package/dist/services/wire.js +13 -0
  83. package/dist/services/wire.js.map +1 -1
  84. package/dist/types.d.ts +74 -8
  85. package/dist/types.d.ts.map +1 -1
  86. package/dist/types.js.map +1 -1
  87. package/package.json +3 -3
  88. package/src/delta/README.md +143 -360
  89. package/dist/state/diff.d.ts.map +0 -1
  90. package/dist/state/diff.js +0 -259
  91. package/dist/state/diff.js.map +0 -1
  92. package/dist/state/draft.d.ts +0 -13
  93. package/dist/state/draft.d.ts.map +0 -1
  94. package/dist/state/draft.js +0 -540
  95. package/dist/state/draft.js.map +0 -1
  96. package/dist/state/value.d.ts +0 -9
  97. package/dist/state/value.d.ts.map +0 -1
  98. package/dist/state/value.js +0 -175
  99. package/dist/state/value.js.map +0 -1
@@ -159,6 +159,7 @@ export class RemoteServiceProvider {
159
159
  buffer: [],
160
160
  snapshotSequences: new Map(),
161
161
  active: false,
162
+ draining: false,
162
163
  terminated: false,
163
164
  closed: false,
164
165
  };
@@ -171,22 +172,7 @@ export class RemoteServiceProvider {
171
172
  if (subscriber.closed || subscriber.active)
172
173
  return;
173
174
  subscriber.active = true;
174
- const errors = [];
175
- try {
176
- for (const entry of subscriber.buffer.splice(0)) {
177
- try {
178
- listener(entry.update, entry.context);
179
- }
180
- catch (error) {
181
- errors.push(error);
182
- }
183
- }
184
- }
185
- finally {
186
- if (subscriber.terminated)
187
- subscriber.closed = true;
188
- }
189
- throwCollectedErrors(errors, "Failed to activate remote service subscription");
175
+ throwCollectedErrors(drainSubscriber(subscriber), "Failed to activate remote service subscription");
190
176
  },
191
177
  close: () => {
192
178
  if (subscriber.closed)
@@ -229,7 +215,7 @@ export class RemoteServiceProvider {
229
215
  }
230
216
  }
231
217
  for (const subscriber of registration.subscribers) {
232
- if (subscriber.active) {
218
+ if (subscriber.active && !subscriber.draining) {
233
219
  subscriber.closed = true;
234
220
  subscriber.buffer.length = 0;
235
221
  }
@@ -326,11 +312,12 @@ export class RemoteServiceProvider {
326
312
  members.push({ name, kind: "method" });
327
313
  }
328
314
  else {
315
+ const snapshot = member.state.snapshot();
329
316
  members.push({
330
317
  name,
331
318
  kind: "state",
332
- sequence: member.state.sequence,
333
- ops: [["r", member.state.value]],
319
+ sequence: snapshot.sequence,
320
+ ops: [["r", snapshot.value]],
334
321
  });
335
322
  }
336
323
  }
@@ -344,21 +331,24 @@ export class RemoteServiceProvider {
344
331
  return;
345
332
  const deliveryContext = context ?? serviceDeliveryContext();
346
333
  const errors = [];
347
- for (const subscriber of registration.subscribers) {
334
+ const subscribers = [...registration.subscribers];
335
+ // Queue for everyone before invoking user code, including reentrant publications.
336
+ for (const subscriber of subscribers) {
348
337
  if (subscriber.closed || updateCoveredBySnapshot(subscriber.snapshotSequences, update))
349
338
  continue;
350
- const entry = { update, context: deliveryContext };
351
- if (!subscriber.active) {
352
- subscriber.buffer.push(entry);
353
- continue;
354
- }
355
- try {
356
- subscriber.listener(entry.update, entry.context);
339
+ if (subscriber.buffer.length === 100) {
340
+ const snapshot = this.#snapshot(registration);
341
+ subscriber.buffer.length = 0;
342
+ subscriber.snapshotSequences.clear();
343
+ recordSnapshotSequences(subscriber.snapshotSequences, snapshot.instances);
344
+ subscriber.buffer.push({ update: { type: "reset", snapshot }, context: deliveryContext });
357
345
  }
358
- catch (error) {
359
- errors.push(error);
346
+ else {
347
+ subscriber.buffer.push({ update, context: deliveryContext });
360
348
  }
361
349
  }
350
+ for (const subscriber of subscribers)
351
+ errors.push(...drainSubscriber(subscriber));
362
352
  throwCollectedErrors(errors, `Failed to publish remote service ${registration.serviceId} update`);
363
353
  }
364
354
  #assertRemotable(service) {
@@ -375,6 +365,31 @@ export class RemoteServiceProvider {
375
365
  throw new Error("Remote service provider is disposed");
376
366
  }
377
367
  }
368
+ function drainSubscriber(subscriber) {
369
+ if (!subscriber.active || subscriber.closed || subscriber.draining)
370
+ return [];
371
+ const errors = [];
372
+ subscriber.draining = true;
373
+ try {
374
+ while (!subscriber.closed) {
375
+ const entry = subscriber.buffer.shift();
376
+ if (entry === undefined)
377
+ break;
378
+ try {
379
+ subscriber.listener(entry.update, entry.context);
380
+ }
381
+ catch (error) {
382
+ errors.push(error);
383
+ }
384
+ }
385
+ }
386
+ finally {
387
+ subscriber.draining = false;
388
+ if (subscriber.terminated)
389
+ subscriber.closed = true;
390
+ }
391
+ return errors;
392
+ }
378
393
  function recordSnapshotSequences(sequences, instances) {
379
394
  for (const instance of instances) {
380
395
  for (const member of instance.members) {
@@ -395,6 +410,10 @@ function updateCoveredBySnapshot(sequences, update) {
395
410
  sequences.delete(key);
396
411
  return false;
397
412
  }
413
+ case "reset":
414
+ sequences.clear();
415
+ recordSnapshotSequences(sequences, update.snapshot.instances);
416
+ return false;
398
417
  case "replaced":
399
418
  sequences.clear();
400
419
  recordSnapshotSequences(sequences, [update.snapshot]);
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/services/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tContext,\n\tJsonValue,\n\tRemoteServiceContract,\n\tService,\n\tServiceCall,\n\tServiceCatalogueEntry,\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceMemberSnapshot,\n\tServiceMode,\n\tServiceProviderUpdate,\n\tServiceSubscription,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\nimport { RemoteServiceError } from \"./errors.ts\";\nimport { serviceDeliveryContext } from \"./state.ts\";\nimport { getReplicatedStateInternals, type ReplicatedStateInternals } from \"./state-internals.ts\";\nimport { decodeServiceControlCall } from \"./wire.ts\";\n\ntype RemoteMethod = (...args: unknown[]) => unknown;\n\ntype InstanceMember =\n\t| { readonly kind: \"method\"; readonly method: RemoteMethod }\n\t| { readonly kind: \"state\"; readonly state: ReplicatedStateInternals };\n\ntype ServiceMemberKind = InstanceMember[\"kind\"];\n\ninterface ClassifiedRemoteServiceImplementation {\n\treadonly implementation: object;\n\treadonly members: Map<string, InstanceMember>;\n}\n\ninterface ProviderInstance {\n\treadonly address?: ServiceInstanceAddress;\n\treadonly implementation: object;\n\treadonly members: ReadonlyMap<string, InstanceMember>;\n\treadonly removeMemberListeners: readonly (() => void)[];\n\tactive: boolean;\n}\n\ninterface ProviderSubscriber {\n\treadonly listener: (update: ServiceProviderUpdate, context: Context) => void;\n\treadonly buffer: { readonly update: ServiceProviderUpdate; readonly context: Context }[];\n\treadonly snapshotSequences: Map<string, number>;\n\tactive: boolean;\n\tterminated: boolean;\n\tclosed: boolean;\n}\n\ninterface ServiceProviderDefinition {\n\treadonly service: { readonly id: string; readonly local?: boolean };\n\treadonly mode: ServiceMode;\n}\n\ninterface ServiceRegistration {\n\treadonly serviceId: string;\n\treadonly mode: ServiceMode;\n\tsingleton?: ProviderInstance;\n\tsingletonShape?: ReadonlyMap<string, ServiceMemberKind>;\n\treadonly instances: Map<string, ProviderInstance>;\n\treadonly generations: Map<string, number>;\n\treadonly subscribers: Set<ProviderSubscriber>;\n}\n\nexport type ServiceUpdatePublisher = (\n\tsubscriptionId: string,\n\tupdate: ServiceProviderUpdate,\n\tcontext: Context,\n) => void | Promise<void>;\n\n/** Hosts one provider for one remote consumer and owns that consumer's subscriptions. */\nexport interface RemoteServiceEndpoint {\n\tinvoke(call: ServiceCall, publish: ServiceUpdatePublisher, context: Context): Promise<JsonValue | undefined>;\n\tdispose(): void;\n}\n\nexport class RemoteServiceProvider {\n\treadonly #catalogue: readonly ServiceCatalogueEntry[];\n\treadonly #registrations = new Map<string, ServiceRegistration>();\n\t#disposed = false;\n\n\tconstructor(entries: readonly (ServiceProviderDefinition | { readonly id: string })[]) {\n\t\tconst definitions = entries.map(\n\t\t\t(entry): ServiceProviderDefinition => (\"service\" in entry ? entry : { service: entry, mode: \"singleton\" }),\n\t\t);\n\t\tfor (const { service } of definitions) {\n\t\t\tif (\"local\" in service && service.local === true) {\n\t\t\t\tthrow new TypeError(`Local service ${service.id} cannot be published remotely`);\n\t\t\t}\n\t\t}\n\t\tconst ids = definitions.map(({ service }) => service.id);\n\t\tif (new Set(ids).size !== ids.length) throw new TypeError(\"Remote service catalogue contains duplicate IDs\");\n\t\tthis.#catalogue = Object.freeze(\n\t\t\tdefinitions.map(({ service, mode }) => Object.freeze({ serviceId: service.id, mode })),\n\t\t);\n\t\tfor (const { service, mode } of definitions) {\n\t\t\tthis.#registrations.set(service.id, {\n\t\t\t\tserviceId: service.id,\n\t\t\t\tmode,\n\t\t\t\tinstances: new Map(),\n\t\t\t\tgenerations: new Map(),\n\t\t\t\tsubscribers: new Set(),\n\t\t\t});\n\t\t}\n\t}\n\n\tget catalogue(): readonly ServiceCatalogueEntry[] {\n\t\treturn this.#catalogue;\n\t}\n\n\tprovide<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tif (registration.singleton !== undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_mode_mismatch\", `Remote service ${service.id} already has a provider`);\n\t\t}\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst shape = serviceMemberShape(classified.members);\n\t\tthis.#assertSingletonShape(registration, shape);\n\t\tregistration.singleton = this.#createInstance(registration, classified, undefined);\n\t\tregistration.singletonShape = shape;\n\t}\n\n\t/** Disconnect one singleton while preserving active subscriptions and remote facades. */\n\twithdraw<T>(service: Service<T>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst previous = registration.singleton;\n\t\tif (previous === undefined) return;\n\t\tprevious.active = false;\n\t\tfor (const remove of previous.removeMemberListeners) remove();\n\t\tdelete registration.singleton;\n\t\tthis.#emit(registration, { type: \"unavailable\" });\n\t}\n\n\t/** Check a singleton replacement without changing the active provider. */\n\tvalidateReplacement<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tthis.#assertSingletonShape(registration, serviceMemberShape(classified.members));\n\t}\n\n\t/** Replace one singleton without making its stable remote facade unavailable. */\n\treplace<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst shape = serviceMemberShape(classified.members);\n\t\tthis.#assertSingletonShape(registration, shape);\n\t\tconst replacement = this.#createInstance(registration, classified, undefined);\n\t\tconst previous = registration.singleton;\n\t\tif (previous !== undefined) {\n\t\t\tprevious.active = false;\n\t\t\tfor (const remove of previous.removeMemberListeners) remove();\n\t\t}\n\t\tregistration.singleton = replacement;\n\t\tregistration.singletonShape = shape;\n\t\tthis.#emit(registration, { type: \"replaced\", snapshot: this.#snapshotInstance(replacement) });\n\t}\n\n\tuse<T>(service: Service<T>): T {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registrations.get(service.id);\n\t\tif (registration?.mode !== \"singleton\" || registration.singleton === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Remote service ${service.id} has no local provider`);\n\t\t}\n\t\treturn registration.singleton.implementation as T;\n\t}\n\n\tspawn<T>(service: Service<T>, key: string, implementation: NoInfer<RemoteServiceContract<T>>): () => void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tif (key.length === 0) throw new TypeError(\"Remote service instance key must not be empty\");\n\t\tconst registration = this.#registration(service.id, \"keyed\");\n\t\tif (registration.instances.has(key)) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t`Remote service ${service.id} already has a live instance with key ${key}`,\n\t\t\t);\n\t\t}\n\t\tconst generation = (registration.generations.get(key) ?? 0) + 1;\n\t\tregistration.generations.set(key, generation);\n\t\tconst address = { key, generation } satisfies ServiceInstanceAddress;\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst instance = this.#createInstance(registration, classified, address);\n\t\tregistration.instances.set(key, instance);\n\t\tthis.#emit(registration, { type: \"spawned\", instance: this.#snapshotInstance(instance) });\n\t\tlet closed = false;\n\t\treturn () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (registration.instances.get(key) !== instance) return;\n\t\t\tinstance.active = false;\n\t\t\tfor (const remove of instance.removeMemberListeners) remove();\n\t\t\tregistration.instances.delete(key);\n\t\t\tthis.#emit(registration, { type: \"closed\", instance: address });\n\t\t};\n\t}\n\n\tasync invoke(call: ServiceCall, context: Context): Promise<JsonValue | undefined> {\n\t\tthis.#assertActive();\n\t\tthis.#assertAllowed(call.serviceId);\n\t\tconst registration = this.#registrations.get(call.serviceId);\n\t\tif (registration === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Unknown remote service ${call.serviceId}`);\n\t\t}\n\t\tconst instance = this.#resolveInstance(registration, call.instance);\n\t\tconst member = instance.members.get(call.member);\n\t\tif (member === undefined) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_not_found\",\n\t\t\t\t`Unknown remote service member ${call.serviceId}.${call.member}`,\n\t\t\t);\n\t\t}\n\t\tif (member.kind !== \"method\") {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_mismatch\",\n\t\t\t\t`Remote service member ${call.serviceId}.${call.member} is not a method`,\n\t\t\t);\n\t\t}\n\t\tconst result: unknown = await Reflect.apply(member.method, instance.implementation, [...call.args, context]);\n\t\treturn result as JsonValue | undefined;\n\t}\n\n\tsubscribe(\n\t\tserviceId: string,\n\t\tmode: ServiceMode,\n\t\tlistener: (update: ServiceProviderUpdate, context: Context) => void,\n\t): ServiceSubscription {\n\t\tthis.#assertActive();\n\t\tthis.#assertAllowed(serviceId);\n\t\tconst registration = this.#registration(serviceId, mode);\n\t\tif (registration.mode === \"singleton\" && registration.singleton === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Remote service ${serviceId} has no provider`);\n\t\t}\n\t\tconst subscriber: ProviderSubscriber = {\n\t\t\tlistener,\n\t\t\tbuffer: [],\n\t\t\tsnapshotSequences: new Map(),\n\t\t\tactive: false,\n\t\t\tterminated: false,\n\t\t\tclosed: false,\n\t\t};\n\t\tregistration.subscribers.add(subscriber);\n\t\tconst snapshot = this.#snapshot(registration);\n\t\trecordSnapshotSequences(subscriber.snapshotSequences, snapshot.instances);\n\t\treturn {\n\t\t\tsnapshot,\n\t\t\tactivate: () => {\n\t\t\t\tif (subscriber.closed || subscriber.active) return;\n\t\t\t\tsubscriber.active = true;\n\t\t\t\tconst errors: unknown[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tfor (const entry of subscriber.buffer.splice(0)) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlistener(entry.update, entry.context);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tif (subscriber.terminated) subscriber.closed = true;\n\t\t\t\t}\n\t\t\t\tthrowCollectedErrors(errors, \"Failed to activate remote service subscription\");\n\t\t\t},\n\t\t\tclose: () => {\n\t\t\t\tif (subscriber.closed) return;\n\t\t\t\tsubscriber.closed = true;\n\t\t\t\tsubscriber.buffer.length = 0;\n\t\t\t\tregistration.subscribers.delete(subscriber);\n\t\t\t},\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tconst errors: unknown[] = [];\n\t\tfor (const registration of this.#registrations.values()) {\n\t\t\tconst singleton = registration.singleton;\n\t\t\tif (singleton !== undefined) {\n\t\t\t\tsingleton.active = false;\n\t\t\t\tfor (const remove of singleton.removeMemberListeners) remove();\n\t\t\t\tdelete registration.singleton;\n\t\t\t\ttry {\n\t\t\t\t\tthis.#emit(registration, { type: \"unavailable\" });\n\t\t\t\t} catch (error) {\n\t\t\t\t\terrors.push(error);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const [key, instance] of [...registration.instances]) {\n\t\t\t\tinstance.active = false;\n\t\t\t\tfor (const remove of instance.removeMemberListeners) remove();\n\t\t\t\tregistration.instances.delete(key);\n\t\t\t\ttry {\n\t\t\t\t\tthis.#emit(registration, { type: \"closed\", instance: instance.address! });\n\t\t\t\t} catch (error) {\n\t\t\t\t\terrors.push(error);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const subscriber of registration.subscribers) {\n\t\t\t\tif (subscriber.active) {\n\t\t\t\t\tsubscriber.closed = true;\n\t\t\t\t\tsubscriber.buffer.length = 0;\n\t\t\t\t} else {\n\t\t\t\t\tsubscriber.terminated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tregistration.subscribers.clear();\n\t\t}\n\t\tthis.#registrations.clear();\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose remote service provider\");\n\t}\n\n\t#registration(serviceId: string, mode: ServiceMode): ServiceRegistration {\n\t\tconst registration = this.#registrations.get(serviceId);\n\t\tif (registration === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Unknown remote service ${serviceId}`);\n\t\t}\n\t\tif (registration.mode !== mode) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t`Remote service ${serviceId} is ${registration.mode}, not ${mode}`,\n\t\t\t);\n\t\t}\n\t\treturn registration;\n\t}\n\n\t#createInstance(\n\t\tregistration: ServiceRegistration,\n\t\tclassified: ClassifiedRemoteServiceImplementation,\n\t\taddress: ServiceInstanceAddress | undefined,\n\t): ProviderInstance {\n\t\tconst removeMemberListeners: (() => void)[] = [];\n\t\tconst instance: ProviderInstance = {\n\t\t\t...(address === undefined ? {} : { address }),\n\t\t\timplementation: classified.implementation,\n\t\t\tmembers: classified.members,\n\t\t\tremoveMemberListeners,\n\t\t\tactive: true,\n\t\t};\n\t\tfor (const [name, member] of classified.members) {\n\t\t\tif (member.kind !== \"state\") continue;\n\t\t\tremoveMemberListeners.push(\n\t\t\t\tmember.state.subscribe((ops, sequence, context) => {\n\t\t\t\t\tif (!instance.active) return;\n\t\t\t\t\tthis.#emit(\n\t\t\t\t\t\tregistration,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"state\",\n\t\t\t\t\t\t\t...(address === undefined ? {} : { instance: address }),\n\t\t\t\t\t\t\tmember: name,\n\t\t\t\t\t\t\tsequence,\n\t\t\t\t\t\t\tops,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t#assertSingletonShape(registration: ServiceRegistration, replacement: ReadonlyMap<string, ServiceMemberKind>): void {\n\t\tconst current = registration.singletonShape;\n\t\tif (current === undefined || sameServiceMemberShape(current, replacement)) return;\n\t\tthrow new RemoteServiceError(\n\t\t\t\"service_member_mismatch\",\n\t\t\t`Remote service ${registration.serviceId} replacement must preserve its member shape`,\n\t\t);\n\t}\n\n\t#resolveInstance(registration: ServiceRegistration, address: ServiceInstanceAddress | undefined): ProviderInstance {\n\t\tif (registration.mode === \"singleton\") {\n\t\t\tif (address !== undefined) {\n\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t\t`Remote service ${registration.serviceId} is singleton`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (registration.singleton === undefined) {\n\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\"service_not_found\",\n\t\t\t\t\t`Remote service ${registration.serviceId} has no provider`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn registration.singleton;\n\t\t}\n\t\tif (address === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_mode_mismatch\", `Remote service ${registration.serviceId} is keyed`);\n\t\t}\n\t\tconst instance = registration.instances.get(address.key);\n\t\tif (instance === undefined) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_instance_not_found\",\n\t\t\t\t`Remote service ${registration.serviceId} has no instance ${address.key}`,\n\t\t\t);\n\t\t}\n\t\tif (instance.address?.generation !== address.generation) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_stale_instance\",\n\t\t\t\t`Remote service ${registration.serviceId} instance ${address.key} is stale`,\n\t\t\t);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t#snapshot(registration: ServiceRegistration): ServiceSubscriptionSnapshot {\n\t\tconst instances =\n\t\t\tregistration.mode === \"singleton\"\n\t\t\t\t? registration.singleton\n\t\t\t\t\t? [this.#snapshotInstance(registration.singleton)]\n\t\t\t\t\t: []\n\t\t\t\t: [...registration.instances.values()]\n\t\t\t\t\t\t.sort((left, right) => left.address!.key.localeCompare(right.address!.key))\n\t\t\t\t\t\t.map((instance) => this.#snapshotInstance(instance));\n\t\treturn { serviceId: registration.serviceId, mode: registration.mode, instances };\n\t}\n\n\t#snapshotInstance(instance: ProviderInstance): ServiceInstanceSnapshot {\n\t\tconst members: ServiceMemberSnapshot[] = [];\n\t\tfor (const [name, member] of instance.members) {\n\t\t\tif (member.kind === \"method\") {\n\t\t\t\tmembers.push({ name, kind: \"method\" });\n\t\t\t} else {\n\t\t\t\tmembers.push({\n\t\t\t\t\tname,\n\t\t\t\t\tkind: \"state\",\n\t\t\t\t\tsequence: member.state.sequence,\n\t\t\t\t\tops: [[\"r\", member.state.value as JsonValue]],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\t...(instance.address === undefined ? {} : { instance: instance.address }),\n\t\t\tmembers,\n\t\t};\n\t}\n\n\t#emit(registration: ServiceRegistration, update: ServiceProviderUpdate, context?: Context): void {\n\t\tif (registration.subscribers.size === 0) return;\n\t\tconst deliveryContext = context ?? serviceDeliveryContext();\n\t\tconst errors: unknown[] = [];\n\t\tfor (const subscriber of registration.subscribers) {\n\t\t\tif (subscriber.closed || updateCoveredBySnapshot(subscriber.snapshotSequences, update)) continue;\n\t\t\tconst entry = { update, context: deliveryContext };\n\t\t\tif (!subscriber.active) {\n\t\t\t\tsubscriber.buffer.push(entry);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsubscriber.listener(entry.update, entry.context);\n\t\t\t} catch (error) {\n\t\t\t\terrors.push(error);\n\t\t\t}\n\t\t}\n\t\tthrowCollectedErrors(errors, `Failed to publish remote service ${registration.serviceId} update`);\n\t}\n\n\t#assertRemotable(service: { readonly id: string; readonly local: boolean }): void {\n\t\tif (service.local) throw new RemoteServiceError(\"service_not_allowed\", `Service ${service.id} is process-local`);\n\t}\n\n\t#assertAllowed(serviceId: string): void {\n\t\tif (!this.#registrations.has(serviceId)) {\n\t\t\tthrow new RemoteServiceError(\"service_not_allowed\", `Remote service ${serviceId} is not allowlisted`);\n\t\t}\n\t}\n\n\t#assertActive(): void {\n\t\tif (this.#disposed) throw new Error(\"Remote service provider is disposed\");\n\t}\n}\n\nfunction recordSnapshotSequences(sequences: Map<string, number>, instances: readonly ServiceInstanceSnapshot[]): void {\n\tfor (const instance of instances) {\n\t\tfor (const member of instance.members) {\n\t\t\tif (member.kind === \"state\") sequences.set(stateMemberKey(instance.instance, member.name), member.sequence);\n\t\t}\n\t}\n}\n\nfunction updateCoveredBySnapshot(sequences: Map<string, number>, update: ServiceProviderUpdate): boolean {\n\tswitch (update.type) {\n\t\tcase \"state\": {\n\t\t\tconst key = stateMemberKey(update.instance, update.member);\n\t\t\tconst sequence = sequences.get(key);\n\t\t\tif (sequence === undefined) return false;\n\t\t\tif (update.sequence <= sequence) return true;\n\t\t\tsequences.delete(key);\n\t\t\treturn false;\n\t\t}\n\t\tcase \"replaced\":\n\t\t\tsequences.clear();\n\t\t\trecordSnapshotSequences(sequences, [update.snapshot]);\n\t\t\treturn false;\n\t\tcase \"spawned\":\n\t\t\trecordSnapshotSequences(sequences, [update.instance]);\n\t\t\treturn false;\n\t\tcase \"unavailable\":\n\t\t\tsequences.clear();\n\t\t\treturn false;\n\t\tcase \"closed\": {\n\t\t\tconst prefix = `${JSON.stringify([update.instance.key, update.instance.generation]).slice(0, -1)},`;\n\t\t\tfor (const key of sequences.keys()) {\n\t\t\t\tif (key.startsWith(prefix)) sequences.delete(key);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nfunction stateMemberKey(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn JSON.stringify(instance === undefined ? [member] : [instance.key, instance.generation, member]);\n}\n\nexport function createRemoteServiceEndpoint(provider: RemoteServiceProvider): RemoteServiceEndpoint {\n\tconst subscriptions = new Map<string, ServiceSubscription>();\n\tlet disposed = false;\n\n\treturn {\n\t\tasync invoke(call, publish, context) {\n\t\t\tif (disposed) throw new Error(\"Remote service endpoint is disposed\");\n\t\t\tconst control = decodeServiceControlCall(call);\n\t\t\tif (control?.type === \"catalogue\") return provider.catalogue as unknown as JsonValue;\n\t\t\tif (control?.type === \"subscribe\") {\n\t\t\t\tif (subscriptions.has(control.subscriptionId)) {\n\t\t\t\t\tthrow new Error(\"Service subscription ID is already active\");\n\t\t\t\t}\n\t\t\t\tconst subscription = provider.subscribe(control.serviceId, control.mode, (update, updateContext) => {\n\t\t\t\t\tvoid Promise.resolve(publish(control.subscriptionId, update, updateContext)).catch(() => {});\n\t\t\t\t});\n\t\t\t\tsubscriptions.set(control.subscriptionId, subscription);\n\t\t\t\tsubscription.activate();\n\t\t\t\treturn subscription.snapshot as unknown as JsonValue;\n\t\t\t}\n\t\t\tif (control?.type === \"unsubscribe\") {\n\t\t\t\tconst subscription = subscriptions.get(control.subscriptionId);\n\t\t\t\tif (subscription === undefined) throw new Error(\"Service subscription was not found\");\n\t\t\t\tsubscription.close();\n\t\t\t\tsubscriptions.delete(control.subscriptionId);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn provider.invoke(call, context);\n\t\t},\n\t\tdispose() {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tfor (const subscription of subscriptions.values()) subscription.close();\n\t\t\tsubscriptions.clear();\n\t\t},\n\t};\n}\n\nexport function validateRemoteServiceImplementation(serviceId: string, implementation: unknown): void {\n\tvoid classifyRemoteServiceImplementation(serviceId, implementation);\n}\n\nfunction classifyRemoteServiceImplementation(\n\tserviceId: string,\n\timplementation: unknown,\n): ClassifiedRemoteServiceImplementation {\n\tif (typeof implementation !== \"object\" || implementation === null || Array.isArray(implementation)) {\n\t\tthrow new TypeError(`Remote service ${serviceId} implementation must be an object`);\n\t}\n\tconst members = new Map<string, InstanceMember>();\n\tfor (const name of Object.keys(implementation).sort()) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(implementation, name);\n\t\tif (descriptor === undefined || !(\"value\" in descriptor)) {\n\t\t\tthrow new TypeError(`Remote service member ${serviceId}.${name} must be a data property`);\n\t\t}\n\t\tif (typeof descriptor.value === \"function\") {\n\t\t\tmembers.set(name, { kind: \"method\", method: descriptor.value as RemoteMethod });\n\t\t\tcontinue;\n\t\t}\n\t\tconst state = getReplicatedStateInternals(descriptor.value);\n\t\tif (state !== undefined) {\n\t\t\tmembers.set(name, { kind: \"state\", state });\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new TypeError(`Remote service member ${serviceId}.${name} is not remotely exposable`);\n\t}\n\tif (members.size === 0) throw new TypeError(`Remote service ${serviceId} has no members`);\n\treturn { implementation, members };\n}\n\nfunction throwCollectedErrors(errors: readonly unknown[], message: string): void {\n\tif (errors.length === 1) throw errors[0];\n\tif (errors.length > 1) throw new AggregateError(errors, message);\n}\n\nfunction serviceMemberShape(members: ReadonlyMap<string, InstanceMember>): ReadonlyMap<string, ServiceMemberKind> {\n\treturn new Map([...members].map(([name, member]) => [name, member.kind]));\n}\n\nfunction sameServiceMemberShape(\n\tleft: ReadonlyMap<string, ServiceMemberKind>,\n\tright: ReadonlyMap<string, ServiceMemberKind>,\n): boolean {\n\treturn left.size === right.size && [...left].every(([name, kind]) => right.get(name) === kind);\n}\n"]}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/services/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tContext,\n\tJsonValue,\n\tRemoteServiceContract,\n\tService,\n\tServiceCall,\n\tServiceCatalogueEntry,\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceMemberSnapshot,\n\tServiceMode,\n\tServiceProviderUpdate,\n\tServiceSubscription,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\nimport { RemoteServiceError } from \"./errors.ts\";\nimport { serviceDeliveryContext } from \"./state.ts\";\nimport { getReplicatedStateInternals, type ReplicatedStateInternals } from \"./state-internals.ts\";\nimport { decodeServiceControlCall } from \"./wire.ts\";\n\ntype RemoteMethod = (...args: unknown[]) => unknown;\n\ntype InstanceMember =\n\t| { readonly kind: \"method\"; readonly method: RemoteMethod }\n\t| { readonly kind: \"state\"; readonly state: ReplicatedStateInternals };\n\ntype ServiceMemberKind = InstanceMember[\"kind\"];\n\ninterface ClassifiedRemoteServiceImplementation {\n\treadonly implementation: object;\n\treadonly members: Map<string, InstanceMember>;\n}\n\ninterface ProviderInstance {\n\treadonly address?: ServiceInstanceAddress;\n\treadonly implementation: object;\n\treadonly members: ReadonlyMap<string, InstanceMember>;\n\treadonly removeMemberListeners: readonly (() => void)[];\n\tactive: boolean;\n}\n\ninterface ProviderSubscriber {\n\treadonly listener: (update: ServiceProviderUpdate, context: Context) => void;\n\treadonly buffer: { readonly update: ServiceProviderUpdate; readonly context: Context }[];\n\treadonly snapshotSequences: Map<string, number>;\n\tactive: boolean;\n\tdraining: boolean;\n\tterminated: boolean;\n\tclosed: boolean;\n}\n\ninterface ServiceProviderDefinition {\n\treadonly service: { readonly id: string; readonly local?: boolean };\n\treadonly mode: ServiceMode;\n}\n\ninterface ServiceRegistration {\n\treadonly serviceId: string;\n\treadonly mode: ServiceMode;\n\tsingleton?: ProviderInstance;\n\tsingletonShape?: ReadonlyMap<string, ServiceMemberKind>;\n\treadonly instances: Map<string, ProviderInstance>;\n\treadonly generations: Map<string, number>;\n\treadonly subscribers: Set<ProviderSubscriber>;\n}\n\nexport type ServiceUpdatePublisher = (\n\tsubscriptionId: string,\n\tupdate: ServiceProviderUpdate,\n\tcontext: Context,\n) => void | Promise<void>;\n\n/** Hosts one provider for one remote consumer and owns that consumer's subscriptions. */\nexport interface RemoteServiceEndpoint {\n\tinvoke(call: ServiceCall, publish: ServiceUpdatePublisher, context: Context): Promise<JsonValue | undefined>;\n\tdispose(): void;\n}\n\nexport class RemoteServiceProvider {\n\treadonly #catalogue: readonly ServiceCatalogueEntry[];\n\treadonly #registrations = new Map<string, ServiceRegistration>();\n\t#disposed = false;\n\n\tconstructor(entries: readonly (ServiceProviderDefinition | { readonly id: string })[]) {\n\t\tconst definitions = entries.map(\n\t\t\t(entry): ServiceProviderDefinition => (\"service\" in entry ? entry : { service: entry, mode: \"singleton\" }),\n\t\t);\n\t\tfor (const { service } of definitions) {\n\t\t\tif (\"local\" in service && service.local === true) {\n\t\t\t\tthrow new TypeError(`Local service ${service.id} cannot be published remotely`);\n\t\t\t}\n\t\t}\n\t\tconst ids = definitions.map(({ service }) => service.id);\n\t\tif (new Set(ids).size !== ids.length) throw new TypeError(\"Remote service catalogue contains duplicate IDs\");\n\t\tthis.#catalogue = Object.freeze(\n\t\t\tdefinitions.map(({ service, mode }) => Object.freeze({ serviceId: service.id, mode })),\n\t\t);\n\t\tfor (const { service, mode } of definitions) {\n\t\t\tthis.#registrations.set(service.id, {\n\t\t\t\tserviceId: service.id,\n\t\t\t\tmode,\n\t\t\t\tinstances: new Map(),\n\t\t\t\tgenerations: new Map(),\n\t\t\t\tsubscribers: new Set(),\n\t\t\t});\n\t\t}\n\t}\n\n\tget catalogue(): readonly ServiceCatalogueEntry[] {\n\t\treturn this.#catalogue;\n\t}\n\n\tprovide<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tif (registration.singleton !== undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_mode_mismatch\", `Remote service ${service.id} already has a provider`);\n\t\t}\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst shape = serviceMemberShape(classified.members);\n\t\tthis.#assertSingletonShape(registration, shape);\n\t\tregistration.singleton = this.#createInstance(registration, classified, undefined);\n\t\tregistration.singletonShape = shape;\n\t}\n\n\t/** Disconnect one singleton while preserving active subscriptions and remote facades. */\n\twithdraw<T>(service: Service<T>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst previous = registration.singleton;\n\t\tif (previous === undefined) return;\n\t\tprevious.active = false;\n\t\tfor (const remove of previous.removeMemberListeners) remove();\n\t\tdelete registration.singleton;\n\t\tthis.#emit(registration, { type: \"unavailable\" });\n\t}\n\n\t/** Check a singleton replacement without changing the active provider. */\n\tvalidateReplacement<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tthis.#assertSingletonShape(registration, serviceMemberShape(classified.members));\n\t}\n\n\t/** Replace one singleton without making its stable remote facade unavailable. */\n\treplace<T>(service: Service<T>, implementation: NoInfer<RemoteServiceContract<T>>): void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registration(service.id, \"singleton\");\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst shape = serviceMemberShape(classified.members);\n\t\tthis.#assertSingletonShape(registration, shape);\n\t\tconst replacement = this.#createInstance(registration, classified, undefined);\n\t\tconst previous = registration.singleton;\n\t\tif (previous !== undefined) {\n\t\t\tprevious.active = false;\n\t\t\tfor (const remove of previous.removeMemberListeners) remove();\n\t\t}\n\t\tregistration.singleton = replacement;\n\t\tregistration.singletonShape = shape;\n\t\tthis.#emit(registration, { type: \"replaced\", snapshot: this.#snapshotInstance(replacement) });\n\t}\n\n\tuse<T>(service: Service<T>): T {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tconst registration = this.#registrations.get(service.id);\n\t\tif (registration?.mode !== \"singleton\" || registration.singleton === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Remote service ${service.id} has no local provider`);\n\t\t}\n\t\treturn registration.singleton.implementation as T;\n\t}\n\n\tspawn<T>(service: Service<T>, key: string, implementation: NoInfer<RemoteServiceContract<T>>): () => void {\n\t\tthis.#assertActive();\n\t\tthis.#assertRemotable(service);\n\t\tthis.#assertAllowed(service.id);\n\t\tif (key.length === 0) throw new TypeError(\"Remote service instance key must not be empty\");\n\t\tconst registration = this.#registration(service.id, \"keyed\");\n\t\tif (registration.instances.has(key)) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t`Remote service ${service.id} already has a live instance with key ${key}`,\n\t\t\t);\n\t\t}\n\t\tconst generation = (registration.generations.get(key) ?? 0) + 1;\n\t\tregistration.generations.set(key, generation);\n\t\tconst address = { key, generation } satisfies ServiceInstanceAddress;\n\t\tconst classified = classifyRemoteServiceImplementation(registration.serviceId, implementation);\n\t\tconst instance = this.#createInstance(registration, classified, address);\n\t\tregistration.instances.set(key, instance);\n\t\tthis.#emit(registration, { type: \"spawned\", instance: this.#snapshotInstance(instance) });\n\t\tlet closed = false;\n\t\treturn () => {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tif (registration.instances.get(key) !== instance) return;\n\t\t\tinstance.active = false;\n\t\t\tfor (const remove of instance.removeMemberListeners) remove();\n\t\t\tregistration.instances.delete(key);\n\t\t\tthis.#emit(registration, { type: \"closed\", instance: address });\n\t\t};\n\t}\n\n\tasync invoke(call: ServiceCall, context: Context): Promise<JsonValue | undefined> {\n\t\tthis.#assertActive();\n\t\tthis.#assertAllowed(call.serviceId);\n\t\tconst registration = this.#registrations.get(call.serviceId);\n\t\tif (registration === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Unknown remote service ${call.serviceId}`);\n\t\t}\n\t\tconst instance = this.#resolveInstance(registration, call.instance);\n\t\tconst member = instance.members.get(call.member);\n\t\tif (member === undefined) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_not_found\",\n\t\t\t\t`Unknown remote service member ${call.serviceId}.${call.member}`,\n\t\t\t);\n\t\t}\n\t\tif (member.kind !== \"method\") {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_member_mismatch\",\n\t\t\t\t`Remote service member ${call.serviceId}.${call.member} is not a method`,\n\t\t\t);\n\t\t}\n\t\tconst result: unknown = await Reflect.apply(member.method, instance.implementation, [...call.args, context]);\n\t\treturn result as JsonValue | undefined;\n\t}\n\n\tsubscribe(\n\t\tserviceId: string,\n\t\tmode: ServiceMode,\n\t\tlistener: (update: ServiceProviderUpdate, context: Context) => void,\n\t): ServiceSubscription {\n\t\tthis.#assertActive();\n\t\tthis.#assertAllowed(serviceId);\n\t\tconst registration = this.#registration(serviceId, mode);\n\t\tif (registration.mode === \"singleton\" && registration.singleton === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Remote service ${serviceId} has no provider`);\n\t\t}\n\t\tconst subscriber: ProviderSubscriber = {\n\t\t\tlistener,\n\t\t\tbuffer: [],\n\t\t\tsnapshotSequences: new Map(),\n\t\t\tactive: false,\n\t\t\tdraining: false,\n\t\t\tterminated: false,\n\t\t\tclosed: false,\n\t\t};\n\t\tregistration.subscribers.add(subscriber);\n\t\tconst snapshot = this.#snapshot(registration);\n\t\trecordSnapshotSequences(subscriber.snapshotSequences, snapshot.instances);\n\t\treturn {\n\t\t\tsnapshot,\n\t\t\tactivate: () => {\n\t\t\t\tif (subscriber.closed || subscriber.active) return;\n\t\t\t\tsubscriber.active = true;\n\t\t\t\tthrowCollectedErrors(drainSubscriber(subscriber), \"Failed to activate remote service subscription\");\n\t\t\t},\n\t\t\tclose: () => {\n\t\t\t\tif (subscriber.closed) return;\n\t\t\t\tsubscriber.closed = true;\n\t\t\t\tsubscriber.buffer.length = 0;\n\t\t\t\tregistration.subscribers.delete(subscriber);\n\t\t\t},\n\t\t};\n\t}\n\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tconst errors: unknown[] = [];\n\t\tfor (const registration of this.#registrations.values()) {\n\t\t\tconst singleton = registration.singleton;\n\t\t\tif (singleton !== undefined) {\n\t\t\t\tsingleton.active = false;\n\t\t\t\tfor (const remove of singleton.removeMemberListeners) remove();\n\t\t\t\tdelete registration.singleton;\n\t\t\t\ttry {\n\t\t\t\t\tthis.#emit(registration, { type: \"unavailable\" });\n\t\t\t\t} catch (error) {\n\t\t\t\t\terrors.push(error);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const [key, instance] of [...registration.instances]) {\n\t\t\t\tinstance.active = false;\n\t\t\t\tfor (const remove of instance.removeMemberListeners) remove();\n\t\t\t\tregistration.instances.delete(key);\n\t\t\t\ttry {\n\t\t\t\t\tthis.#emit(registration, { type: \"closed\", instance: instance.address! });\n\t\t\t\t} catch (error) {\n\t\t\t\t\terrors.push(error);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const subscriber of registration.subscribers) {\n\t\t\t\tif (subscriber.active && !subscriber.draining) {\n\t\t\t\t\tsubscriber.closed = true;\n\t\t\t\t\tsubscriber.buffer.length = 0;\n\t\t\t\t} else {\n\t\t\t\t\tsubscriber.terminated = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tregistration.subscribers.clear();\n\t\t}\n\t\tthis.#registrations.clear();\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose remote service provider\");\n\t}\n\n\t#registration(serviceId: string, mode: ServiceMode): ServiceRegistration {\n\t\tconst registration = this.#registrations.get(serviceId);\n\t\tif (registration === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_not_found\", `Unknown remote service ${serviceId}`);\n\t\t}\n\t\tif (registration.mode !== mode) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t`Remote service ${serviceId} is ${registration.mode}, not ${mode}`,\n\t\t\t);\n\t\t}\n\t\treturn registration;\n\t}\n\n\t#createInstance(\n\t\tregistration: ServiceRegistration,\n\t\tclassified: ClassifiedRemoteServiceImplementation,\n\t\taddress: ServiceInstanceAddress | undefined,\n\t): ProviderInstance {\n\t\tconst removeMemberListeners: (() => void)[] = [];\n\t\tconst instance: ProviderInstance = {\n\t\t\t...(address === undefined ? {} : { address }),\n\t\t\timplementation: classified.implementation,\n\t\t\tmembers: classified.members,\n\t\t\tremoveMemberListeners,\n\t\t\tactive: true,\n\t\t};\n\t\tfor (const [name, member] of classified.members) {\n\t\t\tif (member.kind !== \"state\") continue;\n\t\t\tremoveMemberListeners.push(\n\t\t\t\tmember.state.subscribe((ops, sequence, context) => {\n\t\t\t\t\tif (!instance.active) return;\n\t\t\t\t\tthis.#emit(\n\t\t\t\t\t\tregistration,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"state\",\n\t\t\t\t\t\t\t...(address === undefined ? {} : { instance: address }),\n\t\t\t\t\t\t\tmember: name,\n\t\t\t\t\t\t\tsequence,\n\t\t\t\t\t\t\tops,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t#assertSingletonShape(registration: ServiceRegistration, replacement: ReadonlyMap<string, ServiceMemberKind>): void {\n\t\tconst current = registration.singletonShape;\n\t\tif (current === undefined || sameServiceMemberShape(current, replacement)) return;\n\t\tthrow new RemoteServiceError(\n\t\t\t\"service_member_mismatch\",\n\t\t\t`Remote service ${registration.serviceId} replacement must preserve its member shape`,\n\t\t);\n\t}\n\n\t#resolveInstance(registration: ServiceRegistration, address: ServiceInstanceAddress | undefined): ProviderInstance {\n\t\tif (registration.mode === \"singleton\") {\n\t\t\tif (address !== undefined) {\n\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\"service_mode_mismatch\",\n\t\t\t\t\t`Remote service ${registration.serviceId} is singleton`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (registration.singleton === undefined) {\n\t\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\t\"service_not_found\",\n\t\t\t\t\t`Remote service ${registration.serviceId} has no provider`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn registration.singleton;\n\t\t}\n\t\tif (address === undefined) {\n\t\t\tthrow new RemoteServiceError(\"service_mode_mismatch\", `Remote service ${registration.serviceId} is keyed`);\n\t\t}\n\t\tconst instance = registration.instances.get(address.key);\n\t\tif (instance === undefined) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_instance_not_found\",\n\t\t\t\t`Remote service ${registration.serviceId} has no instance ${address.key}`,\n\t\t\t);\n\t\t}\n\t\tif (instance.address?.generation !== address.generation) {\n\t\t\tthrow new RemoteServiceError(\n\t\t\t\t\"service_stale_instance\",\n\t\t\t\t`Remote service ${registration.serviceId} instance ${address.key} is stale`,\n\t\t\t);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t#snapshot(registration: ServiceRegistration): ServiceSubscriptionSnapshot {\n\t\tconst instances =\n\t\t\tregistration.mode === \"singleton\"\n\t\t\t\t? registration.singleton\n\t\t\t\t\t? [this.#snapshotInstance(registration.singleton)]\n\t\t\t\t\t: []\n\t\t\t\t: [...registration.instances.values()]\n\t\t\t\t\t\t.sort((left, right) => left.address!.key.localeCompare(right.address!.key))\n\t\t\t\t\t\t.map((instance) => this.#snapshotInstance(instance));\n\t\treturn { serviceId: registration.serviceId, mode: registration.mode, instances };\n\t}\n\n\t#snapshotInstance(instance: ProviderInstance): ServiceInstanceSnapshot {\n\t\tconst members: ServiceMemberSnapshot[] = [];\n\t\tfor (const [name, member] of instance.members) {\n\t\t\tif (member.kind === \"method\") {\n\t\t\t\tmembers.push({ name, kind: \"method\" });\n\t\t\t} else {\n\t\t\t\tconst snapshot = member.state.snapshot();\n\t\t\t\tmembers.push({\n\t\t\t\t\tname,\n\t\t\t\t\tkind: \"state\",\n\t\t\t\t\tsequence: snapshot.sequence,\n\t\t\t\t\tops: [[\"r\", snapshot.value as JsonValue]],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\t...(instance.address === undefined ? {} : { instance: instance.address }),\n\t\t\tmembers,\n\t\t};\n\t}\n\n\t#emit(registration: ServiceRegistration, update: ServiceProviderUpdate, context?: Context): void {\n\t\tif (registration.subscribers.size === 0) return;\n\t\tconst deliveryContext = context ?? serviceDeliveryContext();\n\t\tconst errors: unknown[] = [];\n\t\tconst subscribers = [...registration.subscribers];\n\t\t// Queue for everyone before invoking user code, including reentrant publications.\n\t\tfor (const subscriber of subscribers) {\n\t\t\tif (subscriber.closed || updateCoveredBySnapshot(subscriber.snapshotSequences, update)) continue;\n\t\t\tif (subscriber.buffer.length === 100) {\n\t\t\t\tconst snapshot = this.#snapshot(registration);\n\t\t\t\tsubscriber.buffer.length = 0;\n\t\t\t\tsubscriber.snapshotSequences.clear();\n\t\t\t\trecordSnapshotSequences(subscriber.snapshotSequences, snapshot.instances);\n\t\t\t\tsubscriber.buffer.push({ update: { type: \"reset\", snapshot }, context: deliveryContext });\n\t\t\t} else {\n\t\t\t\tsubscriber.buffer.push({ update, context: deliveryContext });\n\t\t\t}\n\t\t}\n\t\tfor (const subscriber of subscribers) errors.push(...drainSubscriber(subscriber));\n\t\tthrowCollectedErrors(errors, `Failed to publish remote service ${registration.serviceId} update`);\n\t}\n\n\t#assertRemotable(service: { readonly id: string; readonly local: boolean }): void {\n\t\tif (service.local) throw new RemoteServiceError(\"service_not_allowed\", `Service ${service.id} is process-local`);\n\t}\n\n\t#assertAllowed(serviceId: string): void {\n\t\tif (!this.#registrations.has(serviceId)) {\n\t\t\tthrow new RemoteServiceError(\"service_not_allowed\", `Remote service ${serviceId} is not allowlisted`);\n\t\t}\n\t}\n\n\t#assertActive(): void {\n\t\tif (this.#disposed) throw new Error(\"Remote service provider is disposed\");\n\t}\n}\n\nfunction drainSubscriber(subscriber: ProviderSubscriber): unknown[] {\n\tif (!subscriber.active || subscriber.closed || subscriber.draining) return [];\n\tconst errors: unknown[] = [];\n\tsubscriber.draining = true;\n\ttry {\n\t\twhile (!subscriber.closed) {\n\t\t\tconst entry = subscriber.buffer.shift();\n\t\t\tif (entry === undefined) break;\n\t\t\ttry {\n\t\t\t\tsubscriber.listener(entry.update, entry.context);\n\t\t\t} catch (error) {\n\t\t\t\terrors.push(error);\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tsubscriber.draining = false;\n\t\tif (subscriber.terminated) subscriber.closed = true;\n\t}\n\treturn errors;\n}\n\nfunction recordSnapshotSequences(sequences: Map<string, number>, instances: readonly ServiceInstanceSnapshot[]): void {\n\tfor (const instance of instances) {\n\t\tfor (const member of instance.members) {\n\t\t\tif (member.kind === \"state\") sequences.set(stateMemberKey(instance.instance, member.name), member.sequence);\n\t\t}\n\t}\n}\n\nfunction updateCoveredBySnapshot(sequences: Map<string, number>, update: ServiceProviderUpdate): boolean {\n\tswitch (update.type) {\n\t\tcase \"state\": {\n\t\t\tconst key = stateMemberKey(update.instance, update.member);\n\t\t\tconst sequence = sequences.get(key);\n\t\t\tif (sequence === undefined) return false;\n\t\t\tif (update.sequence <= sequence) return true;\n\t\t\tsequences.delete(key);\n\t\t\treturn false;\n\t\t}\n\t\tcase \"reset\":\n\t\t\tsequences.clear();\n\t\t\trecordSnapshotSequences(sequences, update.snapshot.instances);\n\t\t\treturn false;\n\t\tcase \"replaced\":\n\t\t\tsequences.clear();\n\t\t\trecordSnapshotSequences(sequences, [update.snapshot]);\n\t\t\treturn false;\n\t\tcase \"spawned\":\n\t\t\trecordSnapshotSequences(sequences, [update.instance]);\n\t\t\treturn false;\n\t\tcase \"unavailable\":\n\t\t\tsequences.clear();\n\t\t\treturn false;\n\t\tcase \"closed\": {\n\t\t\tconst prefix = `${JSON.stringify([update.instance.key, update.instance.generation]).slice(0, -1)},`;\n\t\t\tfor (const key of sequences.keys()) {\n\t\t\t\tif (key.startsWith(prefix)) sequences.delete(key);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nfunction stateMemberKey(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn JSON.stringify(instance === undefined ? [member] : [instance.key, instance.generation, member]);\n}\n\nexport function createRemoteServiceEndpoint(provider: RemoteServiceProvider): RemoteServiceEndpoint {\n\tconst subscriptions = new Map<string, ServiceSubscription>();\n\tlet disposed = false;\n\n\treturn {\n\t\tasync invoke(call, publish, context) {\n\t\t\tif (disposed) throw new Error(\"Remote service endpoint is disposed\");\n\t\t\tconst control = decodeServiceControlCall(call);\n\t\t\tif (control?.type === \"catalogue\") return provider.catalogue as unknown as JsonValue;\n\t\t\tif (control?.type === \"subscribe\") {\n\t\t\t\tif (subscriptions.has(control.subscriptionId)) {\n\t\t\t\t\tthrow new Error(\"Service subscription ID is already active\");\n\t\t\t\t}\n\t\t\t\tconst subscription = provider.subscribe(control.serviceId, control.mode, (update, updateContext) => {\n\t\t\t\t\tvoid Promise.resolve(publish(control.subscriptionId, update, updateContext)).catch(() => {});\n\t\t\t\t});\n\t\t\t\tsubscriptions.set(control.subscriptionId, subscription);\n\t\t\t\tsubscription.activate();\n\t\t\t\treturn subscription.snapshot as unknown as JsonValue;\n\t\t\t}\n\t\t\tif (control?.type === \"unsubscribe\") {\n\t\t\t\tconst subscription = subscriptions.get(control.subscriptionId);\n\t\t\t\tif (subscription === undefined) throw new Error(\"Service subscription was not found\");\n\t\t\t\tsubscription.close();\n\t\t\t\tsubscriptions.delete(control.subscriptionId);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn provider.invoke(call, context);\n\t\t},\n\t\tdispose() {\n\t\t\tif (disposed) return;\n\t\t\tdisposed = true;\n\t\t\tfor (const subscription of subscriptions.values()) subscription.close();\n\t\t\tsubscriptions.clear();\n\t\t},\n\t};\n}\n\nexport function validateRemoteServiceImplementation(serviceId: string, implementation: unknown): void {\n\tvoid classifyRemoteServiceImplementation(serviceId, implementation);\n}\n\nfunction classifyRemoteServiceImplementation(\n\tserviceId: string,\n\timplementation: unknown,\n): ClassifiedRemoteServiceImplementation {\n\tif (typeof implementation !== \"object\" || implementation === null || Array.isArray(implementation)) {\n\t\tthrow new TypeError(`Remote service ${serviceId} implementation must be an object`);\n\t}\n\tconst members = new Map<string, InstanceMember>();\n\tfor (const name of Object.keys(implementation).sort()) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(implementation, name);\n\t\tif (descriptor === undefined || !(\"value\" in descriptor)) {\n\t\t\tthrow new TypeError(`Remote service member ${serviceId}.${name} must be a data property`);\n\t\t}\n\t\tif (typeof descriptor.value === \"function\") {\n\t\t\tmembers.set(name, { kind: \"method\", method: descriptor.value as RemoteMethod });\n\t\t\tcontinue;\n\t\t}\n\t\tconst state = getReplicatedStateInternals(descriptor.value);\n\t\tif (state !== undefined) {\n\t\t\tmembers.set(name, { kind: \"state\", state });\n\t\t\tcontinue;\n\t\t}\n\t\tthrow new TypeError(`Remote service member ${serviceId}.${name} is not remotely exposable`);\n\t}\n\tif (members.size === 0) throw new TypeError(`Remote service ${serviceId} has no members`);\n\treturn { implementation, members };\n}\n\nfunction throwCollectedErrors(errors: readonly unknown[], message: string): void {\n\tif (errors.length === 1) throw errors[0];\n\tif (errors.length > 1) throw new AggregateError(errors, message);\n}\n\nfunction serviceMemberShape(members: ReadonlyMap<string, InstanceMember>): ReadonlyMap<string, ServiceMemberKind> {\n\treturn new Map([...members].map(([name, member]) => [name, member.kind]));\n}\n\nfunction sameServiceMemberShape(\n\tleft: ReadonlyMap<string, ServiceMemberKind>,\n\tright: ReadonlyMap<string, ServiceMemberKind>,\n): boolean {\n\treturn left.size === right.size && [...left].every(([name, kind]) => right.get(name) === kind);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"state-codec.d.ts","sourceRoot":"","sources":["../../src/services/state-codec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,qBAAqB,EACrB,2BAA2B,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAE5F,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IACnC,cAAc,CAAC,QAAQ,EAAE,2BAA2B,GAAG,+BAA+B,CAAC;IACvF,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,yBAAyB,CAAC;CACvE;AAED,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IACnC,cAAc,CAAC,QAAQ,EAAE,+BAA+B,GAAG,2BAA2B,CAAC;IACvF,YAAY,CAAC,MAAM,EAAE,yBAAyB,GAAG,qBAAqB,CAAC;CACvE;AAwCD,wBAAgB,yBAAyB,IAAI,mBAAmB,CA4B/D;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CA4B/D","sourcesContent":["import { type Decoder, decoder, type Encoder, encoder } from \"../delta/index.ts\";\nimport type {\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceProviderUpdate,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\nimport type { WireServiceProviderUpdate, WireServiceSubscriptionSnapshot } from \"./wire.ts\";\n\n/** Stateful operation encoders for every replicated state in one service subscription. */\nexport interface ServiceStateEncoder {\n\tencodeSnapshot(snapshot: ServiceSubscriptionSnapshot): WireServiceSubscriptionSnapshot;\n\tencodeUpdate(update: ServiceProviderUpdate): WireServiceProviderUpdate;\n}\n\n/** Stateful operation decoders for every replicated state in one service subscription. */\nexport interface ServiceStateDecoder {\n\tdecodeSnapshot(snapshot: WireServiceSubscriptionSnapshot): ServiceSubscriptionSnapshot;\n\tdecodeUpdate(update: WireServiceProviderUpdate): ServiceProviderUpdate;\n}\n\ninterface CodecEntry<C> {\n\treadonly instance: ServiceInstanceAddress | undefined;\n\treadonly codec: C;\n}\n\nclass StateCodecRegistry<C> {\n\treadonly #create: () => C;\n\treadonly #entries = new Map<string, CodecEntry<C>>();\n\n\tconstructor(create: () => C) {\n\t\tthis.#create = create;\n\t}\n\n\treset(): void {\n\t\tthis.#entries.clear();\n\t}\n\n\tadd(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst key = stateKey(instance, member);\n\t\tif (this.#entries.has(key)) throw new Error(`Duplicate service state ${describeState(instance, member)}`);\n\t\tconst codec = this.#create();\n\t\tthis.#entries.set(key, { instance, codec });\n\t\treturn codec;\n\t}\n\n\tget(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst codec = this.#entries.get(stateKey(instance, member))?.codec;\n\t\tif (codec === undefined) throw new Error(`Unknown service state ${describeState(instance, member)}`);\n\t\treturn codec;\n\t}\n\n\tremoveInstance(instance: ServiceInstanceAddress): void {\n\t\tfor (const [key, entry] of this.#entries) {\n\t\t\tif (sameAddress(entry.instance, instance)) this.#entries.delete(key);\n\t\t}\n\t}\n}\n\nexport function createServiceStateEncoder(): ServiceStateEncoder {\n\tconst codecs = new StateCodecRegistry<Encoder>(encoder);\n\treturn {\n\t\tencodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => encodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tencodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).encode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: encodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: encodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createServiceStateDecoder(): ServiceStateDecoder {\n\tconst codecs = new StateCodecRegistry<Decoder>(decoder);\n\treturn {\n\t\tdecodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => decodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tdecodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).decode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: decodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: decodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction encodeInstance(\n\tinstance: ServiceInstanceSnapshot,\n\tcodecs: StateCodecRegistry<Encoder>,\n): WireServiceSubscriptionSnapshot[\"instances\"][number] {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).encode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction decodeInstance(\n\tinstance: WireServiceSubscriptionSnapshot[\"instances\"][number],\n\tcodecs: StateCodecRegistry<Decoder>,\n): ServiceInstanceSnapshot {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).decode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction stateKey(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn JSON.stringify([instance?.key ?? null, instance?.generation ?? null, member]);\n}\n\nfunction sameAddress(left: ServiceInstanceAddress | undefined, right: ServiceInstanceAddress): boolean {\n\treturn left?.key === right.key && left.generation === right.generation;\n}\n\nfunction describeState(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn instance === undefined ? member : `${instance.key}@${instance.generation}.${member}`;\n}\n"]}
1
+ {"version":3,"file":"state-codec.d.ts","sourceRoot":"","sources":["../../src/services/state-codec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,qBAAqB,EACrB,2BAA2B,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAE5F,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IACnC,cAAc,CAAC,QAAQ,EAAE,2BAA2B,GAAG,+BAA+B,CAAC;IACvF,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,yBAAyB,CAAC;CACvE;AAED,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IACnC,cAAc,CAAC,QAAQ,EAAE,+BAA+B,GAAG,2BAA2B,CAAC;IACvF,YAAY,CAAC,MAAM,EAAE,yBAAyB,GAAG,qBAAqB,CAAC;CACvE;AAwCD,wBAAgB,yBAAyB,IAAI,mBAAmB,CAqC/D;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CAqC/D"}
@@ -41,6 +41,15 @@ export function createServiceStateEncoder() {
41
41
  },
42
42
  encodeUpdate(update) {
43
43
  switch (update.type) {
44
+ case "reset":
45
+ codecs.reset();
46
+ return {
47
+ ...update,
48
+ snapshot: {
49
+ ...update.snapshot,
50
+ instances: update.snapshot.instances.map((instance) => encodeInstance(instance, codecs)),
51
+ },
52
+ };
44
53
  case "state":
45
54
  return { ...update, ops: codecs.get(update.instance, update.member).encode(update.ops) };
46
55
  case "replaced":
@@ -70,6 +79,15 @@ export function createServiceStateDecoder() {
70
79
  },
71
80
  decodeUpdate(update) {
72
81
  switch (update.type) {
82
+ case "reset":
83
+ codecs.reset();
84
+ return {
85
+ ...update,
86
+ snapshot: {
87
+ ...update.snapshot,
88
+ instances: update.snapshot.instances.map((instance) => decodeInstance(instance, codecs)),
89
+ },
90
+ };
73
91
  case "state":
74
92
  return { ...update, ops: codecs.get(update.instance, update.member).decode(update.ops) };
75
93
  case "replaced":
@@ -1 +1 @@
1
- {"version":3,"file":"state-codec.js","sourceRoot":"","sources":["../../src/services/state-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,OAAO,EAAgB,OAAO,EAAE,MAAM,mBAAmB,CAAC;AA0BjF,MAAM,kBAAkB;IACd,OAAO,CAAU;IACjB,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;IAErD,YAAY,MAAe,EAAE;QAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAAA,CACtB;IAED,KAAK,GAAS;QACb,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IAAA,CACtB;IAED,GAAG,CAAC,QAA4C,EAAE,MAAc,EAAK;QACpE,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1G,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5C,OAAO,KAAK,CAAC;IAAA,CACb;IAED,GAAG,CAAC,QAA4C,EAAE,MAAc,EAAK;QACpE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC;QACnE,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACrG,OAAO,KAAK,CAAC;IAAA,CACb;IAED,cAAc,CAAC,QAAgC,EAAQ;QACtD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtE,CAAC;IAAA,CACD;CACD;AAED,MAAM,UAAU,yBAAyB,GAAwB;IAChE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAU,OAAO,CAAC,CAAC;IACxD,OAAO;QACN,cAAc,CAAC,QAAQ,EAAE;YACxB,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO;gBACN,GAAG,QAAQ;gBACX,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aACjF,CAAC;QAAA,CACF;QACD,YAAY,CAAC,MAAM,EAAE;YACpB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,OAAO;oBACX,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1F,KAAK,UAAU;oBACd,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzE,KAAK,SAAS;oBACb,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzE,KAAK,aAAa;oBACjB,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,MAAM,CAAC;gBACf,KAAK,QAAQ;oBACZ,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACvC,OAAO,MAAM,CAAC;YAChB,CAAC;QAAA,CACD;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,yBAAyB,GAAwB;IAChE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAU,OAAO,CAAC,CAAC;IACxD,OAAO;QACN,cAAc,CAAC,QAAQ,EAAE;YACxB,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO;gBACN,GAAG,QAAQ;gBACX,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;aACjF,CAAC;QAAA,CACF;QACD,YAAY,CAAC,MAAM,EAAE;YACpB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,OAAO;oBACX,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1F,KAAK,UAAU;oBACd,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzE,KAAK,SAAS;oBACb,OAAO,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzE,KAAK,aAAa;oBACjB,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,OAAO,MAAM,CAAC;gBACf,KAAK,QAAQ;oBACZ,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACvC,OAAO,MAAM,CAAC;YAChB,CAAC;QAAA,CACD;KACD,CAAC;AAAA,CACF;AAED,SAAS,cAAc,CACtB,QAAiC,EACjC,MAAmC,EACoB;IACvD,OAAO;QACN,GAAG,QAAQ;QACX,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACxC,MAAM,CAAC,IAAI,KAAK,OAAO;YACtB,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACnF,CAAC,CAAC,MAAM,CACT;KACD,CAAC;AAAA,CACF;AAED,SAAS,cAAc,CACtB,QAA8D,EAC9D,MAAmC,EACT;IAC1B,OAAO;QACN,GAAG,QAAQ;QACX,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACxC,MAAM,CAAC,IAAI,KAAK,OAAO;YACtB,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACnF,CAAC,CAAC,MAAM,CACT;KACD,CAAC;AAAA,CACF;AAED,SAAS,QAAQ,CAAC,QAA4C,EAAE,MAAc,EAAU;IACvF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,GAAG,IAAI,IAAI,EAAE,QAAQ,EAAE,UAAU,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,CACrF;AAED,SAAS,WAAW,CAAC,IAAwC,EAAE,KAA6B,EAAW;IACtG,OAAO,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC;AAAA,CACvE;AAED,SAAS,aAAa,CAAC,QAA4C,EAAE,MAAc,EAAU;IAC5F,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,IAAI,QAAQ,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC;AAAA,CAC5F","sourcesContent":["import { type Decoder, decoder, type Encoder, encoder } from \"../delta/index.ts\";\nimport type {\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceProviderUpdate,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\nimport type { WireServiceProviderUpdate, WireServiceSubscriptionSnapshot } from \"./wire.ts\";\n\n/** Stateful operation encoders for every replicated state in one service subscription. */\nexport interface ServiceStateEncoder {\n\tencodeSnapshot(snapshot: ServiceSubscriptionSnapshot): WireServiceSubscriptionSnapshot;\n\tencodeUpdate(update: ServiceProviderUpdate): WireServiceProviderUpdate;\n}\n\n/** Stateful operation decoders for every replicated state in one service subscription. */\nexport interface ServiceStateDecoder {\n\tdecodeSnapshot(snapshot: WireServiceSubscriptionSnapshot): ServiceSubscriptionSnapshot;\n\tdecodeUpdate(update: WireServiceProviderUpdate): ServiceProviderUpdate;\n}\n\ninterface CodecEntry<C> {\n\treadonly instance: ServiceInstanceAddress | undefined;\n\treadonly codec: C;\n}\n\nclass StateCodecRegistry<C> {\n\treadonly #create: () => C;\n\treadonly #entries = new Map<string, CodecEntry<C>>();\n\n\tconstructor(create: () => C) {\n\t\tthis.#create = create;\n\t}\n\n\treset(): void {\n\t\tthis.#entries.clear();\n\t}\n\n\tadd(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst key = stateKey(instance, member);\n\t\tif (this.#entries.has(key)) throw new Error(`Duplicate service state ${describeState(instance, member)}`);\n\t\tconst codec = this.#create();\n\t\tthis.#entries.set(key, { instance, codec });\n\t\treturn codec;\n\t}\n\n\tget(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst codec = this.#entries.get(stateKey(instance, member))?.codec;\n\t\tif (codec === undefined) throw new Error(`Unknown service state ${describeState(instance, member)}`);\n\t\treturn codec;\n\t}\n\n\tremoveInstance(instance: ServiceInstanceAddress): void {\n\t\tfor (const [key, entry] of this.#entries) {\n\t\t\tif (sameAddress(entry.instance, instance)) this.#entries.delete(key);\n\t\t}\n\t}\n}\n\nexport function createServiceStateEncoder(): ServiceStateEncoder {\n\tconst codecs = new StateCodecRegistry<Encoder>(encoder);\n\treturn {\n\t\tencodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => encodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tencodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).encode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: encodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: encodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createServiceStateDecoder(): ServiceStateDecoder {\n\tconst codecs = new StateCodecRegistry<Decoder>(decoder);\n\treturn {\n\t\tdecodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => decodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tdecodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).decode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: decodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: decodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction encodeInstance(\n\tinstance: ServiceInstanceSnapshot,\n\tcodecs: StateCodecRegistry<Encoder>,\n): WireServiceSubscriptionSnapshot[\"instances\"][number] {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).encode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction decodeInstance(\n\tinstance: WireServiceSubscriptionSnapshot[\"instances\"][number],\n\tcodecs: StateCodecRegistry<Decoder>,\n): ServiceInstanceSnapshot {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).decode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction stateKey(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn JSON.stringify([instance?.key ?? null, instance?.generation ?? null, member]);\n}\n\nfunction sameAddress(left: ServiceInstanceAddress | undefined, right: ServiceInstanceAddress): boolean {\n\treturn left?.key === right.key && left.generation === right.generation;\n}\n\nfunction describeState(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn instance === undefined ? member : `${instance.key}@${instance.generation}.${member}`;\n}\n"]}
1
+ {"version":3,"file":"state-codec.js","sourceRoot":"","sources":["../../src/services/state-codec.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Decoder, decoder, type Encoder, encoder } from \"../delta/index.ts\";\nimport type {\n\tServiceInstanceAddress,\n\tServiceInstanceSnapshot,\n\tServiceProviderUpdate,\n\tServiceSubscriptionSnapshot,\n} from \"../types.ts\";\nimport type { WireServiceProviderUpdate, WireServiceSubscriptionSnapshot } from \"./wire.ts\";\n\n/** Stateful operation encoders for every replicated state in one service subscription. */\nexport interface ServiceStateEncoder {\n\tencodeSnapshot(snapshot: ServiceSubscriptionSnapshot): WireServiceSubscriptionSnapshot;\n\tencodeUpdate(update: ServiceProviderUpdate): WireServiceProviderUpdate;\n}\n\n/** Stateful operation decoders for every replicated state in one service subscription. */\nexport interface ServiceStateDecoder {\n\tdecodeSnapshot(snapshot: WireServiceSubscriptionSnapshot): ServiceSubscriptionSnapshot;\n\tdecodeUpdate(update: WireServiceProviderUpdate): ServiceProviderUpdate;\n}\n\ninterface CodecEntry<C> {\n\treadonly instance: ServiceInstanceAddress | undefined;\n\treadonly codec: C;\n}\n\nclass StateCodecRegistry<C> {\n\treadonly #create: () => C;\n\treadonly #entries = new Map<string, CodecEntry<C>>();\n\n\tconstructor(create: () => C) {\n\t\tthis.#create = create;\n\t}\n\n\treset(): void {\n\t\tthis.#entries.clear();\n\t}\n\n\tadd(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst key = stateKey(instance, member);\n\t\tif (this.#entries.has(key)) throw new Error(`Duplicate service state ${describeState(instance, member)}`);\n\t\tconst codec = this.#create();\n\t\tthis.#entries.set(key, { instance, codec });\n\t\treturn codec;\n\t}\n\n\tget(instance: ServiceInstanceAddress | undefined, member: string): C {\n\t\tconst codec = this.#entries.get(stateKey(instance, member))?.codec;\n\t\tif (codec === undefined) throw new Error(`Unknown service state ${describeState(instance, member)}`);\n\t\treturn codec;\n\t}\n\n\tremoveInstance(instance: ServiceInstanceAddress): void {\n\t\tfor (const [key, entry] of this.#entries) {\n\t\t\tif (sameAddress(entry.instance, instance)) this.#entries.delete(key);\n\t\t}\n\t}\n}\n\nexport function createServiceStateEncoder(): ServiceStateEncoder {\n\tconst codecs = new StateCodecRegistry<Encoder>(encoder);\n\treturn {\n\t\tencodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => encodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tencodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"reset\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...update,\n\t\t\t\t\t\tsnapshot: {\n\t\t\t\t\t\t\t...update.snapshot,\n\t\t\t\t\t\t\tinstances: update.snapshot.instances.map((instance) => encodeInstance(instance, codecs)),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).encode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: encodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: encodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createServiceStateDecoder(): ServiceStateDecoder {\n\tconst codecs = new StateCodecRegistry<Decoder>(decoder);\n\treturn {\n\t\tdecodeSnapshot(snapshot) {\n\t\t\tcodecs.reset();\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tinstances: snapshot.instances.map((instance) => decodeInstance(instance, codecs)),\n\t\t\t};\n\t\t},\n\t\tdecodeUpdate(update) {\n\t\t\tswitch (update.type) {\n\t\t\t\tcase \"reset\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...update,\n\t\t\t\t\t\tsnapshot: {\n\t\t\t\t\t\t\t...update.snapshot,\n\t\t\t\t\t\t\tinstances: update.snapshot.instances.map((instance) => decodeInstance(instance, codecs)),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\tcase \"state\":\n\t\t\t\t\treturn { ...update, ops: codecs.get(update.instance, update.member).decode(update.ops) };\n\t\t\t\tcase \"replaced\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn { ...update, snapshot: decodeInstance(update.snapshot, codecs) };\n\t\t\t\tcase \"spawned\":\n\t\t\t\t\treturn { ...update, instance: decodeInstance(update.instance, codecs) };\n\t\t\t\tcase \"unavailable\":\n\t\t\t\t\tcodecs.reset();\n\t\t\t\t\treturn update;\n\t\t\t\tcase \"closed\":\n\t\t\t\t\tcodecs.removeInstance(update.instance);\n\t\t\t\t\treturn update;\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction encodeInstance(\n\tinstance: ServiceInstanceSnapshot,\n\tcodecs: StateCodecRegistry<Encoder>,\n): WireServiceSubscriptionSnapshot[\"instances\"][number] {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).encode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction decodeInstance(\n\tinstance: WireServiceSubscriptionSnapshot[\"instances\"][number],\n\tcodecs: StateCodecRegistry<Decoder>,\n): ServiceInstanceSnapshot {\n\treturn {\n\t\t...instance,\n\t\tmembers: instance.members.map((member) =>\n\t\t\tmember.kind === \"state\"\n\t\t\t\t? { ...member, ops: codecs.add(instance.instance, member.name).decode(member.ops) }\n\t\t\t\t: member,\n\t\t),\n\t};\n}\n\nfunction stateKey(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn JSON.stringify([instance?.key ?? null, instance?.generation ?? null, member]);\n}\n\nfunction sameAddress(left: ServiceInstanceAddress | undefined, right: ServiceInstanceAddress): boolean {\n\treturn left?.key === right.key && left.generation === right.generation;\n}\n\nfunction describeState(instance: ServiceInstanceAddress | undefined, member: string): string {\n\treturn instance === undefined ? member : `${instance.key}@${instance.generation}.${member}`;\n}\n"]}
@@ -1,8 +1,11 @@
1
1
  import type { Op } from "../delta/index.ts";
2
2
  import type { Context } from "../types.ts";
3
3
  export interface ReplicatedStateInternals {
4
- readonly sequence: number;
5
- readonly value: unknown;
4
+ /** Atomically capture the immutable value and its matching publication sequence. */
5
+ snapshot(): {
6
+ readonly value: unknown;
7
+ readonly sequence: number;
8
+ };
6
9
  subscribe(listener: (ops: readonly Op[], sequence: number, context: Context) => void): () => void;
7
10
  }
8
11
  export declare function registerReplicatedStateInternals(value: object, internals: ReplicatedStateInternals): void;
@@ -1 +1 @@
1
- {"version":3,"file":"state-internals.d.ts","sourceRoot":"","sources":["../../src/services/state-internals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClG;AAID,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,wBAAwB,GAAG,IAAI,CAEzG;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,GAAG,SAAS,CAGhG","sourcesContent":["import type { Op } from \"../delta/index.ts\";\nimport type { Context } from \"../types.ts\";\n\nexport interface ReplicatedStateInternals {\n\treadonly sequence: number;\n\treadonly value: unknown;\n\tsubscribe(listener: (ops: readonly Op[], sequence: number, context: Context) => void): () => void;\n}\n\nconst sources = new WeakMap<object, ReplicatedStateInternals>();\n\nexport function registerReplicatedStateInternals(value: object, internals: ReplicatedStateInternals): void {\n\tsources.set(value, internals);\n}\n\nexport function getReplicatedStateInternals(value: unknown): ReplicatedStateInternals | undefined {\n\tif (typeof value !== \"object\" || value === null) return undefined;\n\treturn sources.get(value);\n}\n"]}
1
+ {"version":3,"file":"state-internals.d.ts","sourceRoot":"","sources":["../../src/services/state-internals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,wBAAwB;IACxC,oFAAoF;IACpF,QAAQ,IAAI;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClG;AAID,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,wBAAwB,GAAG,IAAI,CAEzG;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,GAAG,SAAS,CAGhG"}
@@ -1 +1 @@
1
- {"version":3,"file":"state-internals.js","sourceRoot":"","sources":["../../src/services/state-internals.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,GAAG,IAAI,OAAO,EAAoC,CAAC;AAEhE,MAAM,UAAU,gCAAgC,CAAC,KAAa,EAAE,SAAmC,EAAQ;IAC1G,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAAA,CAC9B;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAc,EAAwC;IACjG,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAAA,CAC1B","sourcesContent":["import type { Op } from \"../delta/index.ts\";\nimport type { Context } from \"../types.ts\";\n\nexport interface ReplicatedStateInternals {\n\treadonly sequence: number;\n\treadonly value: unknown;\n\tsubscribe(listener: (ops: readonly Op[], sequence: number, context: Context) => void): () => void;\n}\n\nconst sources = new WeakMap<object, ReplicatedStateInternals>();\n\nexport function registerReplicatedStateInternals(value: object, internals: ReplicatedStateInternals): void {\n\tsources.set(value, internals);\n}\n\nexport function getReplicatedStateInternals(value: unknown): ReplicatedStateInternals | undefined {\n\tif (typeof value !== \"object\" || value === null) return undefined;\n\treturn sources.get(value);\n}\n"]}
1
+ {"version":3,"file":"state-internals.js","sourceRoot":"","sources":["../../src/services/state-internals.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,GAAG,IAAI,OAAO,EAAoC,CAAC;AAEhE,MAAM,UAAU,gCAAgC,CAAC,KAAa,EAAE,SAAmC;IAClG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAc;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import type { Op } from \"../delta/index.ts\";\nimport type { Context } from \"../types.ts\";\n\nexport interface ReplicatedStateInternals {\n\t/** Atomically capture the immutable value and its matching publication sequence. */\n\tsnapshot(): { readonly value: unknown; readonly sequence: number };\n\tsubscribe(listener: (ops: readonly Op[], sequence: number, context: Context) => void): () => void;\n}\n\nconst sources = new WeakMap<object, ReplicatedStateInternals>();\n\nexport function registerReplicatedStateInternals(value: object, internals: ReplicatedStateInternals): void {\n\tsources.set(value, internals);\n}\n\nexport function getReplicatedStateInternals(value: unknown): ReplicatedStateInternals | undefined {\n\tif (typeof value !== \"object\" || value === null) return undefined;\n\treturn sources.get(value);\n}\n"]}
@@ -1,23 +1,28 @@
1
1
  import { type Op } from "../delta/index.ts";
2
- import type { Context, JsonValue, MutableReplicatedState, ReplicatedState, ReplicatedStateDelivery } from "../types.ts";
2
+ import type { AttachedReplicatedState, Context, JsonValue, MutableReplicatedState, ReplicatedState, ReplicatedStateDelivery, ReplicatedStateSource, ReplicatedStateSourceOptions } from "../types.ts";
3
+ /** The void signature also accepts synchronous callbacks that return an ignored value. */
4
+ type StateListener<T> = (value: T, context: Context, delivery: ReplicatedStateDelivery) => void;
3
5
  export declare class MutableReplicatedStateImpl<T extends object> implements MutableReplicatedState<T> {
4
6
  #private;
5
7
  constructor(initial: T);
6
8
  get value(): T;
7
9
  change(context: Context, mutate: Parameters<MutableReplicatedState<T>["change"]>[1]): void;
8
10
  replace(context: Context, value: T): void;
9
- subscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void;
11
+ subscribe(listener: StateListener<T>): () => void;
10
12
  }
13
+ /** Attach a publication-only replicated state to one authoritative immutable source stream. */
14
+ export declare function attachReplicatedStateSource<T>(source: ReplicatedStateSource<T>, options?: ReplicatedStateSourceOptions): AttachedReplicatedState<T>;
11
15
  /** A cold read-only state used by service consumers until a complete snapshot arrives. */
12
16
  export declare class ReplicatedStateReplica<T extends JsonValue = JsonValue> implements ReplicatedState<T> {
13
17
  #private;
14
18
  constructor(reportError: (error: Error) => void);
15
19
  get value(): T | undefined;
16
- subscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void;
20
+ subscribe(listener: StateListener<T>): () => void;
17
21
  hydrate(sequence: number, ops: readonly Op[], context: Context): void;
18
22
  update(sequence: number, ops: readonly Op[], context: Context): void;
19
23
  clear(): void;
20
24
  }
21
25
  /** @internal Context for synthetic service deliveries without a caller. */
22
26
  export declare function serviceDeliveryContext(): Context;
27
+ export {};
23
28
  //# sourceMappingURL=state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/services/state.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAIpE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAUxH,qBAAa,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAE,YAAW,sBAAsB,CAAC,CAAC,CAAC;;IAU7F,YAAY,OAAO,EAAE,CAAC,EAerB;IAED,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAYzF;IAED,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAGxC;IAED,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CAWvG;CAwCD;AAED,0FAA0F;AAC1F,qBAAa,sBAAsB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;;IAOjG,YAAY,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAE9C;IAED,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAED,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CASvG;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAYpE;IAED,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAkBnE;IAED,KAAK,IAAI,IAAI,CAGZ;CAmBD;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD","sourcesContent":["import { BACKGROUND_CONTEXT } from \"../context/index.ts\";\nimport { applyImmutable, isBase, type Op } from \"../delta/index.ts\";\nimport { diffRevisions } from \"../state/diff.ts\";\nimport { produceWithMetadata } from \"../state/draft.ts\";\nimport { JsonRevisionStore } from \"../state/value.ts\";\nimport type { Context, JsonValue, MutableReplicatedState, ReplicatedState, ReplicatedStateDelivery } from \"../types.ts\";\nimport { registerReplicatedStateInternals } from \"./state-internals.ts\";\n\ntype Publication<T> = {\n\tvalue: T;\n\tops: readonly Op[];\n\tsequence: number;\n\tcontext: Context;\n};\n\nexport class MutableReplicatedStateImpl<T extends object> implements MutableReplicatedState<T> {\n\treadonly #listeners = new Map<(value: T, context: Context, delivery: ReplicatedStateDelivery) => void, number>();\n\treadonly #sourceListeners = new Set<(ops: readonly Op[], sequence: number, context: Context) => void>();\n\treadonly #store = new JsonRevisionStore();\n\treadonly #publications: Publication<T>[] = [];\n\t#value: T;\n\t#sequence = 0;\n\t#changing = false;\n\t#delivering = false;\n\n\tconstructor(initial: T) {\n\t\tthis.#value = this.#store.import(initial);\n\t\tconst thisSource = this;\n\t\tregisterReplicatedStateInternals(this, {\n\t\t\tget sequence() {\n\t\t\t\treturn thisSource.#sequence;\n\t\t\t},\n\t\t\tget value() {\n\t\t\t\treturn thisSource.#value;\n\t\t\t},\n\t\t\tsubscribe: (listener) => {\n\t\t\t\tthisSource.#sourceListeners.add(listener);\n\t\t\t\treturn () => thisSource.#sourceListeners.delete(listener);\n\t\t\t},\n\t\t});\n\t}\n\n\tget value(): T {\n\t\treturn this.#value;\n\t}\n\n\tchange(context: Context, mutate: Parameters<MutableReplicatedState<T>[\"change\"]>[1]): void {\n\t\tif (this.#changing) throw new Error(\"Replicated state cannot be changed reentrantly from a change callback\");\n\t\tthis.#changing = true;\n\t\tlet next: T;\n\t\ttry {\n\t\t\tconst produced = produceWithMetadata(this.#value, mutate);\n\t\t\tif (produced.value === this.#value) return;\n\t\t\tnext = this.#store.commit(produced.value, produced.owned);\n\t\t} finally {\n\t\t\tthis.#changing = false;\n\t\t}\n\t\tthis.#commit(next, context);\n\t}\n\n\treplace(context: Context, value: T): void {\n\t\tif (this.#changing) throw new Error(\"Replicated state cannot be replaced from a change callback\");\n\t\tthis.#commit(this.#store.import(value), context);\n\t}\n\n\tsubscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void {\n\t\tconst sequence = this.#sequence;\n\t\tconst value = this.#value;\n\t\tthis.#listeners.set(listener, sequence);\n\t\ttry {\n\t\t\tlistener(value, serviceDeliveryContext(), { kind: \"hydrate\", sequence });\n\t\t} catch (error) {\n\t\t\tthis.#listeners.delete(listener);\n\t\t\tthrow error;\n\t\t}\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\t#commit(next: T, context: Context): void {\n\t\tconst ops = diffRevisions(this.#value as unknown as JsonValue, next as unknown as JsonValue);\n\t\tif (ops.length === 0) return;\n\t\tthis.#value = next;\n\t\tthis.#sequence += 1;\n\t\tthis.#publications.push({ value: next, ops, sequence: this.#sequence, context });\n\t\tif (this.#delivering) return;\n\t\tthis.#delivering = true;\n\t\tconst errors: unknown[] = [];\n\t\ttry {\n\t\t\tfor (\n\t\t\t\tlet publication = this.#publications.shift();\n\t\t\t\tpublication !== undefined;\n\t\t\t\tpublication = this.#publications.shift()\n\t\t\t) {\n\t\t\t\tfor (const listener of [...this.#sourceListeners]) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlistener(publication.ops, publication.sequence, publication.context);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst delivery = { kind: \"update\", sequence: publication.sequence } as const;\n\t\t\t\tfor (const [listener, hydratedSequence] of [...this.#listeners]) {\n\t\t\t\t\tif (publication.sequence <= hydratedSequence) continue;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlistener(publication.value, publication.context, delivery);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\terrors.push(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#delivering = false;\n\t\t}\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Replicated state listeners failed\");\n\t}\n}\n\n/** A cold read-only state used by service consumers until a complete snapshot arrives. */\nexport class ReplicatedStateReplica<T extends JsonValue = JsonValue> implements ReplicatedState<T> {\n\treadonly #listeners = new Set<(value: T, context: Context, delivery: ReplicatedStateDelivery) => void>();\n\treadonly #reportError: (error: Error) => void;\n\treadonly #store = new JsonRevisionStore();\n\t#value: T | undefined;\n\t#sequence: number | undefined;\n\n\tconstructor(reportError: (error: Error) => void) {\n\t\tthis.#reportError = reportError;\n\t}\n\n\tget value(): T | undefined {\n\t\treturn this.#value;\n\t}\n\n\tsubscribe(listener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void): () => void {\n\t\tthis.#listeners.add(listener);\n\t\tif (this.#value !== undefined) {\n\t\t\tthis.#deliver(listener, this.#value, serviceDeliveryContext(), {\n\t\t\t\tkind: \"hydrate\",\n\t\t\t\tsequence: this.#sequence!,\n\t\t\t});\n\t\t}\n\t\treturn () => this.#listeners.delete(listener);\n\t}\n\n\thydrate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tlet next: T;\n\t\ttry {\n\t\t\tif (!isBase(ops)) throw new Error(\"Replicated state snapshot is not a base operation batch\");\n\t\t\tnext = this.#store.adopt(applyImmutable<T>(undefined, ops));\n\t\t} catch (error) {\n\t\t\tthis.clear();\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#sequence = sequence;\n\t\tthis.#value = next;\n\t\tthis.#deliverAll(context, { kind: \"hydrate\", sequence });\n\t}\n\n\tupdate(sequence: number, ops: readonly Op[], context: Context): void {\n\t\tif (this.#sequence === undefined || this.#value === undefined) {\n\t\t\tthrow new Error(\"Replicated state received an update before hydration\");\n\t\t}\n\t\tif (sequence !== this.#sequence + 1) {\n\t\t\tthis.clear();\n\t\t\tthrow new Error(\"Replicated state update sequence has a gap\");\n\t\t}\n\t\tlet next: T;\n\t\ttry {\n\t\t\tnext = this.#store.adopt(applyImmutable(this.#value, ops));\n\t\t} catch (error) {\n\t\t\tthis.clear();\n\t\t\tthrow error;\n\t\t}\n\t\tthis.#sequence = sequence;\n\t\tthis.#value = next;\n\t\tthis.#deliverAll(context, { kind: \"update\", sequence });\n\t}\n\n\tclear(): void {\n\t\tthis.#value = undefined;\n\t\tthis.#sequence = undefined;\n\t}\n\n\t#deliverAll(context: Context, delivery: ReplicatedStateDelivery): void {\n\t\tif (this.#value === undefined) return;\n\t\tfor (const listener of this.#listeners) this.#deliver(listener, this.#value, context, delivery);\n\t}\n\n\t#deliver(\n\t\tlistener: (value: T, context: Context, delivery: ReplicatedStateDelivery) => void,\n\t\tvalue: T,\n\t\tcontext: Context,\n\t\tdelivery: ReplicatedStateDelivery,\n\t): void {\n\t\ttry {\n\t\t\tlistener(value, context, delivery);\n\t\t} catch (error) {\n\t\t\tthis.#reportError(toError(error));\n\t\t}\n\t}\n}\n\n/** @internal Context for synthetic service deliveries without a caller. */\nexport function serviceDeliveryContext(): Context {\n\t// TODO: Add delivery-scoped cancellation or metadata if deliveries gain an owned lifecycle.\n\treturn BACKGROUND_CONTEXT;\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n"]}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/services/state.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,EAAE,EAAsC,MAAM,mBAAmB,CAAC;AAExG,OAAO,KAAK,EACX,uBAAuB,EACvB,OAAO,EACP,SAAS,EACT,sBAAsB,EACtB,eAAe,EACf,uBAAuB,EACvB,qBAAqB,EAGrB,4BAA4B,EAC5B,MAAM,aAAa,CAAC;AAGrB,0FAA0F;AAC1F,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;AAqKhG,qBAAa,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAE,YAAW,sBAAsB,CAAC,CAAC,CAAC;;IAK7F,YAAY,OAAO,EAAE,CAAC,EAOrB;IAED,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CA2BzF;IAED,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CASxC;IAED,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAEhD;CACD;AA8ED,+FAA+F;AAC/F,wBAAgB,2BAA2B,CAAC,CAAC,EAC5C,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,EAChC,OAAO,GAAE,4BAAiC,GACxC,uBAAuB,CAAC,CAAC,CAAC,CAc5B;AAED,0FAA0F;AAC1F,qBAAa,sBAAsB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;;IAOjG,YAAY,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAE9C;IAED,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAED,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAehD;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAYpE;IAED,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAkBnE;IAED,KAAK,IAAI,IAAI,CAIZ;CAUD;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD"}