@spine-event-engine/delivery-server 2.0.0-snapshot.10

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 (73) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +106 -0
  3. package/REFERENCE.md +75 -0
  4. package/dist/admin/admin-service.d.ts +47 -0
  5. package/dist/admin/admin-service.d.ts.map +1 -0
  6. package/dist/admin/admin-service.js +188 -0
  7. package/dist/admin/admin-service.js.map +1 -0
  8. package/dist/bin/spine-delivery-server.d.ts +3 -0
  9. package/dist/bin/spine-delivery-server.d.ts.map +1 -0
  10. package/dist/bin/spine-delivery-server.js +54 -0
  11. package/dist/bin/spine-delivery-server.js.map +1 -0
  12. package/dist/core/in-memory-delivery-core.d.ts +56 -0
  13. package/dist/core/in-memory-delivery-core.d.ts.map +1 -0
  14. package/dist/core/in-memory-delivery-core.js +44 -0
  15. package/dist/core/in-memory-delivery-core.js.map +1 -0
  16. package/dist/core/in-memory-delivery-state.d.ts +86 -0
  17. package/dist/core/in-memory-delivery-state.d.ts.map +1 -0
  18. package/dist/core/in-memory-delivery-state.js +214 -0
  19. package/dist/core/in-memory-delivery-state.js.map +1 -0
  20. package/dist/core/inbox-service.d.ts +20 -0
  21. package/dist/core/inbox-service.d.ts.map +1 -0
  22. package/dist/core/inbox-service.js +212 -0
  23. package/dist/core/inbox-service.js.map +1 -0
  24. package/dist/core/limits.d.ts +64 -0
  25. package/dist/core/limits.d.ts.map +1 -0
  26. package/dist/core/limits.js +73 -0
  27. package/dist/core/limits.js.map +1 -0
  28. package/dist/core/mutation-admission.d.ts +18 -0
  29. package/dist/core/mutation-admission.d.ts.map +1 -0
  30. package/dist/core/mutation-admission.js +78 -0
  31. package/dist/core/mutation-admission.js.map +1 -0
  32. package/dist/core/shard-service.d.ts +22 -0
  33. package/dist/core/shard-service.d.ts.map +1 -0
  34. package/dist/core/shard-service.js +189 -0
  35. package/dist/core/shard-service.js.map +1 -0
  36. package/dist/core/wire-values.d.ts +22 -0
  37. package/dist/core/wire-values.d.ts.map +1 -0
  38. package/dist/core/wire-values.js +66 -0
  39. package/dist/core/wire-values.js.map +1 -0
  40. package/dist/health/health-service.d.ts +9 -0
  41. package/dist/health/health-service.d.ts.map +1 -0
  42. package/dist/health/health-service.js +47 -0
  43. package/dist/health/health-service.js.map +1 -0
  44. package/dist/index.d.ts +3 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +16 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/server/assembly.d.ts +41 -0
  49. package/dist/server/assembly.d.ts.map +1 -0
  50. package/dist/server/assembly.js +49 -0
  51. package/dist/server/assembly.js.map +1 -0
  52. package/dist/server/config.d.ts +57 -0
  53. package/dist/server/config.d.ts.map +1 -0
  54. package/dist/server/config.js +52 -0
  55. package/dist/server/config.js.map +1 -0
  56. package/dist/server/delivery-server-log.d.ts +11 -0
  57. package/dist/server/delivery-server-log.d.ts.map +1 -0
  58. package/dist/server/delivery-server-log.js +44 -0
  59. package/dist/server/delivery-server-log.js.map +1 -0
  60. package/dist/server/delivery-server.d.ts +103 -0
  61. package/dist/server/delivery-server.d.ts.map +1 -0
  62. package/dist/server/delivery-server.js +201 -0
  63. package/dist/server/delivery-server.js.map +1 -0
  64. package/dist/server/shutdown.d.ts +36 -0
  65. package/dist/server/shutdown.d.ts.map +1 -0
  66. package/dist/server/shutdown.js +25 -0
  67. package/dist/server/shutdown.js.map +1 -0
  68. package/dist/testing/index.d.ts +5 -0
  69. package/dist/testing/index.d.ts.map +1 -0
  70. package/dist/testing/index.js +18 -0
  71. package/dist/testing/index.js.map +1 -0
  72. package/dist/tsconfig.tsbuildinfo +1 -0
  73. package/package.json +41 -0
@@ -0,0 +1,189 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { create } from "@bufbuild/protobuf";
15
+ import { Code, ConnectError } from "@connectrpc/connect";
16
+ import { ExpiredSessionSchema, ExpiredSessionsReleasedSchema, LiquorPickUpOutcomeSchema as PickUpOutcomeSchema, ShardAlreadyPickedUpSchema as AlreadyPickedUpSchema, ShardPickedUpSchema, ShardService, } from "@spine-event-engine/proto/delivery-server";
17
+ import { InMemoryDeliveryState } from "./in-memory-delivery-state.js";
18
+ import { MAX_DELIVERY_RESPONSE_SHARDS, MAX_DELIVERY_WORKER_BYTES } from "./limits.js";
19
+ import { MutationAdmission } from "./mutation-admission.js";
20
+ import { DeliveryShards, DeliveryWorkers } from "./wire-values.js";
21
+ /**
22
+ * Provides Shard RPC handler implementations.
23
+ */
24
+ export const ShardHandlers = Object.freeze({
25
+ create: (state, admission, now, processingTimeoutMs, onTransition) => ({
26
+ pickShard: async (request, context) => {
27
+ const shard = ShardInputs.requireShard(request.shard);
28
+ const worker = DeliveryWorkers.copy(ShardInputs.requireWorker(request.worker));
29
+ const pendingOnly = ShardInputs.pendingOnly(context.requestHeader);
30
+ return admission.run(context.signal, () => {
31
+ const pickedAt = ShardTime.current(now);
32
+ const current = state.session(shard);
33
+ const stale = current !== undefined &&
34
+ processingTimeoutMs > 0 &&
35
+ pickedAt - ShardInputs.requireWhenPicked(current) > processingTimeoutMs;
36
+ const refreshed = current !== undefined &&
37
+ !stale &&
38
+ ShardInputs.revalidating(context.requestHeader) &&
39
+ ShardInputs.sameWorker(current.worker, worker);
40
+ if (current === undefined || stale || refreshed) {
41
+ if (pendingOnly && !state.hasPending(shard))
42
+ throw ShardErrors.noPendingWork();
43
+ state.setSession(shard, worker, pickedAt);
44
+ if (ShardInputs.revalidating(context.requestHeader))
45
+ context.responseHeader.set("x-spine-delivery-revalidation", refreshed ? "refreshed" : "picked");
46
+ if (pendingOnly)
47
+ context.responseHeader.set("x-spine-delivery-outcome", "pending-acknowledged");
48
+ onTransition?.(shard);
49
+ return create(PickUpOutcomeSchema, {
50
+ value: {
51
+ case: "pickedUp",
52
+ value: create(ShardPickedUpSchema, {
53
+ shard: DeliveryShards.copy(shard),
54
+ worker: DeliveryWorkers.copy(worker),
55
+ whenPicked: ShardTime.timestamp(pickedAt),
56
+ }),
57
+ },
58
+ });
59
+ }
60
+ if (pendingOnly)
61
+ context.responseHeader.set("x-spine-delivery-outcome", "pending-acknowledged");
62
+ if (ShardInputs.revalidating(context.requestHeader))
63
+ context.responseHeader.set("x-spine-delivery-revalidation", "lost");
64
+ return create(PickUpOutcomeSchema, {
65
+ value: {
66
+ case: "alreadyPickedUp",
67
+ value: create(AlreadyPickedUpSchema, {
68
+ worker: DeliveryWorkers.copy(ShardInputs.requireWorker(current.worker)),
69
+ whenPicked: ShardTime.timestamp(ShardInputs.requireWhenPicked(current)),
70
+ }),
71
+ },
72
+ });
73
+ });
74
+ },
75
+ releaseSession: async (request, context) => {
76
+ const shard = ShardInputs.requireShard(request.shard);
77
+ const worker = ShardInputs.requireWorker(request.worker);
78
+ await admission.run(context.signal, () => {
79
+ const current = state.session(shard);
80
+ if (current !== undefined && ShardInputs.sameWorker(current.worker, worker)) {
81
+ state.release(shard);
82
+ onTransition?.(shard);
83
+ }
84
+ });
85
+ return {};
86
+ },
87
+ releaseSessions: async (request, context) => {
88
+ if (request.inactivityPeriod === undefined)
89
+ throw ShardErrors.invalid("Inactivity period is missing.");
90
+ if (!ShardInputs.validDuration(request.inactivityPeriod))
91
+ throw ShardErrors.invalid("Inactivity period is invalid.");
92
+ const period = Number(request.inactivityPeriod.seconds) * 1_000 +
93
+ Math.trunc(request.inactivityPeriod.nanos / 1_000_000);
94
+ if (!Number.isFinite(period) || period < 0)
95
+ throw ShardErrors.invalid("Inactivity period is invalid.");
96
+ return admission.run(context.signal, () => {
97
+ const releasedAt = ShardTime.current(now);
98
+ const released = [];
99
+ for (const record of state.shards.values()) {
100
+ if (released.length === MAX_DELIVERY_RESPONSE_SHARDS)
101
+ break;
102
+ const session = state.session(record.shard);
103
+ if (session !== undefined &&
104
+ releasedAt - ShardInputs.requireWhenPicked(session) >= period) {
105
+ state.release(record.shard);
106
+ onTransition?.(record.shard);
107
+ released.push(create(ExpiredSessionSchema, {
108
+ shard: DeliveryShards.copy(session.shard),
109
+ worker: DeliveryWorkers.copy(ShardInputs.requireWorker(session.worker)),
110
+ whenPicked: ShardTime.timestamp(ShardInputs.requireWhenPicked(session)),
111
+ whenReleased: ShardTime.timestamp(releasedAt),
112
+ }));
113
+ }
114
+ }
115
+ return create(ExpiredSessionsReleasedSchema, { shard: released });
116
+ });
117
+ },
118
+ }),
119
+ });
120
+ /**
121
+ * Validates Shard requests and converts their inputs.
122
+ */
123
+ const ShardInputs = Object.freeze({
124
+ requireWhenPicked: (record) => {
125
+ if (record.whenLastPicked === undefined)
126
+ throw new TypeError("Delivery shard session is invalid.");
127
+ return record.whenLastPicked;
128
+ },
129
+ requireWorker: (worker) => {
130
+ if (worker?.nodeId === undefined ||
131
+ worker.value.trim().length === 0 ||
132
+ worker.nodeId.value.trim().length === 0 ||
133
+ ShardInputs.utf8Bytes(worker.value) + ShardInputs.utf8Bytes(worker.nodeId.value) >
134
+ MAX_DELIVERY_WORKER_BYTES) {
135
+ throw ShardErrors.invalid("Delivery worker is invalid.");
136
+ }
137
+ return worker;
138
+ },
139
+ sameWorker: (first, second) => first?.nodeId?.value === second.nodeId?.value && first?.value === second.value,
140
+ revalidating: (headers) => headers?.get("x-spine-delivery-revalidate") === "true",
141
+ requireShard: (shard) => {
142
+ if (shard === undefined ||
143
+ !Number.isInteger(shard.index) ||
144
+ shard.index < 0 ||
145
+ !Number.isInteger(shard.ofTotal) ||
146
+ shard.ofTotal < 1 ||
147
+ shard.index >= shard.ofTotal) {
148
+ throw ShardErrors.invalid("Delivery shard is invalid.");
149
+ }
150
+ return shard;
151
+ },
152
+ pendingOnly: (headers) => {
153
+ const mode = headers?.get("x-spine-delivery-pickup-mode");
154
+ if (mode === null || mode === undefined)
155
+ return false;
156
+ if (mode === "pending")
157
+ return true;
158
+ throw ShardErrors.invalid("Delivery pickup mode is invalid.");
159
+ },
160
+ validDuration: (value) => value.seconds >= 0n &&
161
+ value.seconds <= 315576000000n &&
162
+ Number.isInteger(value.nanos) &&
163
+ value.nanos >= 0 &&
164
+ value.nanos < 1_000_000_000,
165
+ utf8Bytes: (value) => new TextEncoder().encode(value).byteLength,
166
+ });
167
+ /**
168
+ * Validates Shard clocks and converts protobuf timestamps.
169
+ */
170
+ const ShardTime = Object.freeze({
171
+ timestamp: (milliseconds) => {
172
+ const seconds = Math.floor(milliseconds / 1_000);
173
+ return { seconds: BigInt(seconds), nanos: (milliseconds - seconds * 1_000) * 1_000_000 };
174
+ },
175
+ current: (now) => {
176
+ const value = now();
177
+ if (!Number.isInteger(value) || value < -62_135_596_800_000 || value > 253_402_300_799_999)
178
+ throw new RangeError("Delivery clock returned an invalid millisecond value.");
179
+ return value;
180
+ },
181
+ });
182
+ /**
183
+ * Creates Shard RPC errors.
184
+ */
185
+ const ShardErrors = Object.freeze({
186
+ invalid: (message) => new ConnectError(message, Code.InvalidArgument),
187
+ noPendingWork: () => new ConnectError("Delivery shard has no pending work.", Code.FailedPrecondition, new Headers([["x-spine-delivery-outcome", "no-pending-work"]])),
188
+ });
189
+ //# sourceMappingURL=shard-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shard-service.js","sourceRoot":"","sources":["../../src/core/shard-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type InboxMessage, type ShardIndex, type WorkerId } from "@spine-event-engine/proto/delivery";
2
+ /**
3
+ * Provides canonical detached delivery message values.
4
+ */
5
+ export declare const DeliveryMessages: Readonly<{
6
+ key(message: InboxMessage): string;
7
+ copy(message: InboxMessage): InboxMessage;
8
+ }>;
9
+ /**
10
+ * Provides canonical detached delivery shard values.
11
+ */
12
+ export declare const DeliveryShards: Readonly<{
13
+ key(shard: ShardIndex): string;
14
+ copy(shard: ShardIndex): ShardIndex;
15
+ }>;
16
+ /**
17
+ * Provides canonical detached delivery worker values.
18
+ */
19
+ export declare const DeliveryWorkers: Readonly<{
20
+ copy(worker: WorkerId): WorkerId;
21
+ }>;
22
+ //# sourceMappingURL=wire-values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-values.d.ts","sourceRoot":"","sources":["../../src/core/wire-values.ts"],"names":[],"mappings":"AAeA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC;IACtC,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAAC;CAC3C,CAkBC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC;IACpC,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAC;CACrC,CAgBC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC;IAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,CASzE,CAAC"}
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { clone } from "@bufbuild/protobuf";
15
+ import { InboxMessageSchema, ShardIndexSchema, WorkerIdSchema, } from "@spine-event-engine/proto/delivery";
16
+ /**
17
+ * Provides canonical detached delivery message values.
18
+ */
19
+ export const DeliveryMessages = Object.freeze({
20
+ // prettier-ignore
21
+ /**
22
+ * Returns the stable key for a message identity.
23
+ */
24
+ key(message) {
25
+ if (message.id?.index === undefined)
26
+ throw new TypeError("Delivery message identity is missing.");
27
+ return `${DeliveryShards.key(message.id.index)}:${message.id.uuid}`;
28
+ },
29
+ /**
30
+ * Returns a detached message clone.
31
+ */
32
+ copy(message) {
33
+ return clone(InboxMessageSchema, message);
34
+ },
35
+ });
36
+ /**
37
+ * Provides canonical detached delivery shard values.
38
+ */
39
+ export const DeliveryShards = Object.freeze({
40
+ // prettier-ignore
41
+ /**
42
+ * Returns the stable key for a shard.
43
+ */
44
+ key(shard) {
45
+ return `${String(shard.index)}/${String(shard.ofTotal)}`;
46
+ },
47
+ /**
48
+ * Returns a detached shard clone.
49
+ */
50
+ copy(shard) {
51
+ return clone(ShardIndexSchema, shard);
52
+ },
53
+ });
54
+ /**
55
+ * Provides canonical detached delivery worker values.
56
+ */
57
+ export const DeliveryWorkers = Object.freeze({
58
+ // prettier-ignore
59
+ /**
60
+ * Returns a detached worker clone.
61
+ */
62
+ copy(worker) {
63
+ return clone(WorkerIdSchema, worker);
64
+ },
65
+ });
66
+ //# sourceMappingURL=wire-values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-values.js","sourceRoot":"","sources":["../../src/core/wire-values.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GAIf,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAGxB,MAAM,CAAC,MAAM,CAAC;IACjB,kBAAkB;IAElB;;OAEG;IACH,GAAG,CAAC,OAAqB;QACvB,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;YACjC,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC/D,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACtE,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAqB;QACxB,OAAO,KAAK,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAGtB,MAAM,CAAC,MAAM,CAAC;IACjB,kBAAkB;IAElB;;OAEG;IACH,GAAG,CAAC,KAAiB;QACnB,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,KAAiB;QACpB,OAAO,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;CACF,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAmD,MAAM,CAAC,MAAM,CAAC;IAC3F,kBAAkB;IAElB;;OAEG;IACH,IAAI,CAAC,MAAgB;QACnB,OAAO,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ServiceImpl } from "@connectrpc/connect";
2
+ import { Health } from "@spine-event-engine/proto/delivery-server";
3
+ /**
4
+ * Provides Delivery health handler implementations.
5
+ */
6
+ export declare const HealthHandlers: Readonly<{
7
+ create(serving: () => boolean): ServiceImpl<typeof Health>;
8
+ }>;
9
+ //# sourceMappingURL=health-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-service.d.ts","sourceRoot":"","sources":["../../src/health/health-service.ts"],"names":[],"mappings":"AAcA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EACL,MAAM,EAEP,MAAM,2CAA2C,CAAC;AAUnD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC;IACpC,MAAM,CAAC,OAAO,EAAE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,MAAM,CAAC,CAAC;CAC5D,CAsBC,CAAC"}
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { Code, ConnectError } from "@connectrpc/connect";
15
+ import { Health, HealthCheckResponse_ServingStatus as ServingStatus, } from "@spine-event-engine/proto/delivery-server";
16
+ const known = new Set([
17
+ "",
18
+ "grpc.health.v1.Health",
19
+ "spine.delivery.InboxService",
20
+ "spine.delivery.ShardService",
21
+ "spine.delivery.AdminService",
22
+ ]);
23
+ /**
24
+ * Provides Delivery health handler implementations.
25
+ */
26
+ export const HealthHandlers = Object.freeze({
27
+ // prettier-ignore
28
+ /**
29
+ * Creates health handlers.
30
+ *
31
+ * @param serving Reports whether the server accepts traffic.
32
+ * @returns Provides Connect health handlers.
33
+ */
34
+ create(serving) {
35
+ return {
36
+ check: (request) => ({
37
+ status: serving() && known.has(request.service)
38
+ ? ServingStatus.SERVING
39
+ : ServingStatus.NOT_SERVING,
40
+ }),
41
+ watch: () => {
42
+ throw new ConnectError("Delivery health watch is not implemented.", Code.Unimplemented);
43
+ },
44
+ };
45
+ },
46
+ });
47
+ //# sourceMappingURL=health-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-service.js","sourceRoot":"","sources":["../../src/health/health-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EACL,MAAM,EACN,iCAAiC,IAAI,aAAa,GACnD,MAAM,2CAA2C,CAAC;AAEnD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC;IACpB,EAAE;IACF,uBAAuB;IACvB,6BAA6B;IAC7B,6BAA6B;IAC7B,6BAA6B;CAC9B,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAEtB,MAAM,CAAC,MAAM,CAAC;IACjB,kBAAkB;IAElB;;;;;OAKG;IACH,MAAM,CAAC,OAAsB;QAC3B,OAAO;YACL,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACnB,MAAM,EACJ,OAAO,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;oBACrC,CAAC,CAAC,aAAa,CAAC,OAAO;oBACvB,CAAC,CAAC,aAAa,CAAC,WAAW;aAChC,CAAC;YACF,KAAK,EAAE,GAAG,EAAE;gBACV,MAAM,IAAI,YAAY,CAAC,2CAA2C,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1F,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { InMemoryDelivery, type DeliveryCore, type DeliveryCoreOptions, } from "./core/in-memory-delivery-core.js";
2
+ export { DeliveryServer, type DeliveryServerOptions } from "./server/delivery-server.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ export { InMemoryDelivery, } from "./core/in-memory-delivery-core.js";
15
+ export { DeliveryServer } from "./server/delivery-server.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,gBAAgB,GAGjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,cAAc,EAA8B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { ServiceImpl } from "@connectrpc/connect";
2
+ import { AdminService, InboxService, ShardService } from "@spine-event-engine/proto/delivery-server";
3
+ import type { DeliveryConfiguration } from "./config.js";
4
+ /**
5
+ * Groups handlers and shutdown boundaries that share delivery runtime state.
6
+ */
7
+ export interface DeliveryAssembly {
8
+ /**
9
+ * Provides Inbox handlers backed by the shared delivery state.
10
+ */
11
+ readonly inbox: ServiceImpl<typeof InboxService>;
12
+ /**
13
+ * Provides Shard handlers backed by the shared delivery state.
14
+ */
15
+ readonly shards: ServiceImpl<typeof ShardService>;
16
+ /**
17
+ * Provides Admin handlers backed by the shared delivery state.
18
+ */
19
+ readonly admin: ServiceImpl<typeof AdminService>;
20
+ /**
21
+ * Closes the shared mutation-admission boundary.
22
+ */
23
+ closeAdmission(): void;
24
+ /**
25
+ * Closes the shared Admin publisher.
26
+ */
27
+ closeAdmin(): void;
28
+ }
29
+ /**
30
+ * Provides assembly construction for the delivery RPC handlers.
31
+ */
32
+ export declare const DeliveryAssembly: Readonly<{
33
+ /**
34
+ * Creates delivery handlers with one shared state and admission boundary.
35
+ *
36
+ * @param configuration Configures the shared state and shard timeout.
37
+ * @returns The assembled delivery handlers and shutdown boundaries.
38
+ */
39
+ create: (configuration?: Pick<DeliveryConfiguration, "processingTimeoutMs" | "maxRetainedMessages" | "maxRetainedBytes" | "maxTrackedShards">) => DeliveryAssembly;
40
+ }>;
41
+ //# sourceMappingURL=assembly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assembly.d.ts","sourceRoot":"","sources":["../../src/server/assembly.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACb,MAAM,2CAA2C,CAAC;AAQnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAG/B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;IAEjD;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;IAElD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;IAEjD;;OAEG;IACH,cAAc,IAAI,IAAI,CAAC;IAEvB;;OAEG;IACH,UAAU,IAAI,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC;IAGtC;;;;;OAKG;IACH,MAAM,EAAE,CACN,aAAa,CAAC,EAAE,IAAI,CAClB,qBAAqB,EACrB,qBAAqB,GAAG,qBAAqB,GAAG,kBAAkB,GAAG,kBAAkB,CACxF,KACE,gBAAgB,CAAC;CACvB,CAmCC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { AdminService, InboxService, ShardService, } from "@spine-event-engine/proto/delivery-server";
15
+ import { AdminPublisher } from "../admin/admin-service.js";
16
+ import { InMemoryDeliveryState } from "../core/in-memory-delivery-state.js";
17
+ import { InboxHandlers } from "../core/inbox-service.js";
18
+ import { MutationAdmission } from "../core/mutation-admission.js";
19
+ import { ShardHandlers } from "../core/shard-service.js";
20
+ import { DEFAULT_DELIVERY_STATE_LIMITS } from "../core/limits.js";
21
+ /**
22
+ * Provides assembly construction for the delivery RPC handlers.
23
+ */
24
+ export const DeliveryAssembly = Object.freeze({
25
+ create: (configuration = {
26
+ processingTimeoutMs: 0,
27
+ ...DEFAULT_DELIVERY_STATE_LIMITS,
28
+ }) => {
29
+ const state = new InMemoryDeliveryState(configuration);
30
+ const admission = new MutationAdmission();
31
+ const admin = AdminPublisher.create(state);
32
+ return Object.freeze({
33
+ inbox: InboxHandlers.create(state, admission, (shard, delta) => {
34
+ admin.recordMessageTransition(shard, delta);
35
+ }),
36
+ shards: ShardHandlers.create(state, admission, Date.now, configuration.processingTimeoutMs, (shard) => {
37
+ admin.publish(shard);
38
+ }),
39
+ admin: admin.service,
40
+ closeAdmission: () => {
41
+ admission.close();
42
+ },
43
+ closeAdmin: () => {
44
+ admin.close();
45
+ },
46
+ });
47
+ },
48
+ });
49
+ //# sourceMappingURL=assembly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assembly.js","sourceRoot":"","sources":["../../src/server/assembly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAmClE;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAexB,MAAM,CAAC,MAAM,CAAC;IACjB,MAAM,EAAE,CACN,gBAGI;QACF,mBAAmB,EAAE,CAAC;QACtB,GAAG,6BAA6B;KACjC,EACiB,EAAE;QACpB,MAAM,KAAK,GAAG,IAAI,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC7D,KAAK,CAAC,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9C,CAAC,CAAC;YACF,MAAM,EAAE,aAAa,CAAC,MAAM,CAC1B,KAAK,EACL,SAAS,EACT,IAAI,CAAC,GAAG,EACR,aAAa,CAAC,mBAAmB,EACjC,CAAC,KAAK,EAAE,EAAE;gBACR,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CACF;YACD,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,cAAc,EAAE,GAAG,EAAE;gBACnB,SAAS,CAAC,KAAK,EAAE,CAAC;YACpB,CAAC;YACD,UAAU,EAAE,GAAG,EAAE;gBACf,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type DeliveryStateLimits } from "../core/limits.js";
2
+ import type { DeliveryServerOptions } from "./delivery-server.js";
3
+ /**
4
+ * Describes the resolved delivery listener and retained-state configuration.
5
+ */
6
+ export interface DeliveryConfiguration extends DeliveryStateLimits {
7
+ /**
8
+ * Holds the validated listener host.
9
+ */
10
+ readonly host: string;
11
+ /**
12
+ * Holds the validated listener port.
13
+ */
14
+ readonly port: number;
15
+ /**
16
+ * Holds the maximum inbound RPC message size in bytes.
17
+ */
18
+ readonly maxInboundMessageBytes: number;
19
+ /**
20
+ * Holds the automatic Shard processing timeout in milliseconds.
21
+ */
22
+ readonly processingTimeoutMs: number;
23
+ }
24
+ /**
25
+ * Provides delivery listener configuration resolution.
26
+ */
27
+ export declare const DeliveryConfig: Readonly<{
28
+ /**
29
+ * Resolves delivery configuration from explicit options, environment, and defaults.
30
+ *
31
+ * @param options Holds explicit delivery server options.
32
+ * @returns The frozen validated delivery configuration.
33
+ */
34
+ resolve: (options?: DeliveryServerOptions) => DeliveryConfiguration;
35
+ /**
36
+ * Resolves and validates a bounded numeric option.
37
+ *
38
+ * @param explicit Holds the explicit numeric override.
39
+ * @param environment Names the environment variable.
40
+ * @param fallback Holds the default value.
41
+ * @param minimum Holds the inclusive lower bound.
42
+ * @param maximum Holds the inclusive upper bound.
43
+ * @param name Describes the value in validation errors.
44
+ * @returns The resolved validated numeric value.
45
+ */
46
+ number: (explicit: number | undefined, environment: string, fallback: number, minimum: number, maximum: number, name: string) => number;
47
+ /**
48
+ * Parses an environment numeric option or returns its default.
49
+ *
50
+ * @param value Holds the environment value.
51
+ * @param fallback Holds the default value.
52
+ * @param name Describes the value in validation errors.
53
+ * @returns The parsed environment value or default.
54
+ */
55
+ environmentNumber: (value: string | undefined, fallback: number, name: string) => number;
56
+ }>;
57
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAcA,OAAO,EAML,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAGhE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAExC;;OAEG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC;IAGpC;;;;;OAKG;IACH,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,qBAAqB,KAAK,qBAAqB,CAAC;IAEpE;;;;;;;;;;OAUG;IACH,MAAM,EAAE,CACN,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,KACT,MAAM,CAAC;IAEZ;;;;;;;OAOG;IACH,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1F,CA2EC,CAAC"}
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright 2026, CodeMatters. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * https://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
10
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
+ * or implied. See the License for the specific language governing permissions and limitations under
12
+ * the License.
13
+ */
14
+ import { DEFAULT_DELIVERY_STATE_LIMITS, MAX_DELIVERY_LIMIT, MAX_DELIVERY_RESPONSE_SHARDS, MAX_DELIVERY_RPC_BYTES, DeliveryLimits, } from "../core/limits.js";
15
+ /**
16
+ * Provides delivery listener configuration resolution.
17
+ */
18
+ export const DeliveryConfig = Object.freeze({
19
+ resolve: (options = {}) => {
20
+ const host = options.host ?? process.env.HOST ?? "127.0.0.1";
21
+ if (typeof host !== "string" || host.trim().length === 0)
22
+ throw new RangeError("Delivery server host is invalid.");
23
+ return Object.freeze({
24
+ host,
25
+ port: DeliveryConfig.number(options.port, "PORT", 8484, 0, 65_535, "port"),
26
+ maxInboundMessageBytes: DeliveryConfig.number(options.maxInboundMessageBytes, "MAX_INBOUND_MESSAGE_SIZE", MAX_DELIVERY_RPC_BYTES, 1, MAX_DELIVERY_LIMIT, "inbound message size"),
27
+ processingTimeoutMs: DeliveryConfig.number(options.processingTimeoutSeconds, "SHARD_PROCESSING_TIMEOUT", 0, 0, MAX_DELIVERY_LIMIT, "processing timeout") * 1_000,
28
+ ...DeliveryLimits.resolve({
29
+ maxRetainedMessages: DeliveryConfig.number(options.maxRetainedMessages, "MAX_RETAINED_MESSAGES", DEFAULT_DELIVERY_STATE_LIMITS.maxRetainedMessages, 1, MAX_DELIVERY_LIMIT, "retained message limit"),
30
+ maxRetainedBytes: DeliveryConfig.number(options.maxRetainedBytes, "MAX_RETAINED_BYTES", DEFAULT_DELIVERY_STATE_LIMITS.maxRetainedBytes, 1, MAX_DELIVERY_LIMIT, "retained byte limit"),
31
+ maxTrackedShards: DeliveryConfig.number(options.maxTrackedShards, "MAX_TRACKED_SHARDS", DEFAULT_DELIVERY_STATE_LIMITS.maxTrackedShards, 1, MAX_DELIVERY_RESPONSE_SHARDS, "tracked shard limit"),
32
+ }),
33
+ });
34
+ },
35
+ number: (explicit, environment, fallback, minimum, maximum, name) => {
36
+ const value = explicit ?? DeliveryConfig.environmentNumber(process.env[environment], fallback, name);
37
+ if (!Number.isInteger(value) || value < minimum || value > maximum)
38
+ throw new RangeError(`Delivery server ${name} is invalid.`);
39
+ return value;
40
+ },
41
+ environmentNumber: (value, fallback, name) => {
42
+ if (value === undefined || value === "")
43
+ return fallback;
44
+ if (!/^(?:0|[1-9][0-9]*)$/.test(value))
45
+ throw new RangeError(`Delivery server ${name} is invalid.`);
46
+ const number = Number(value);
47
+ if (!Number.isSafeInteger(number))
48
+ throw new RangeError(`Delivery server ${name} is invalid.`);
49
+ return number;
50
+ },
51
+ });
52
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { ILogLayer } from "loglayer";
2
+ /**
3
+ * Records a contained delivery-listener error without changing listener failure semantics.
4
+ *
5
+ * @param logger Receives the contained record when supplied.
6
+ */
7
+ export declare const deliveryServerLog: Readonly<{
8
+ error(logger: ILogLayer | undefined): void;
9
+ isPromiseLike(value: unknown): value is PromiseLike<unknown>;
10
+ }>;
11
+ //# sourceMappingURL=delivery-server-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-server-log.d.ts","sourceRoot":"","sources":["../../src/server/delivery-server-log.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC;IACvC,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3C,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;CAC9D,CAyBC,CAAC"}