@spine-event-engine/delivery-client 2.0.0-snapshot.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +133 -0
- package/REFERENCE.md +89 -0
- package/dist/client/client.d.ts +143 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +459 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/shard-observation.d.ts +35 -0
- package/dist/client/shard-observation.d.ts.map +1 -0
- package/dist/client/shard-observation.js +178 -0
- package/dist/client/shard-observation.js.map +1 -0
- package/dist/client/types.d.ts +229 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +128 -0
- package/dist/client/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/remote/adapters.d.ts +102 -0
- package/dist/remote/adapters.d.ts.map +1 -0
- package/dist/remote/adapters.js +405 -0
- package/dist/remote/adapters.js.map +1 -0
- package/dist/remote/remote-delivery.d.ts +65 -0
- package/dist/remote/remote-delivery.d.ts.map +1 -0
- package/dist/remote/remote-delivery.js +176 -0
- package/dist/remote/remote-delivery.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/wire/codec.d.ts +107 -0
- package/dist/wire/codec.d.ts.map +1 -0
- package/dist/wire/codec.js +776 -0
- package/dist/wire/codec.js.map +1 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Client for the Spine Delivery server
|
|
2
|
+
|
|
3
|
+
Use this Node client when an application node must coordinate delivery work with
|
|
4
|
+
a Delivery server on a trusted network. Start with the local server while
|
|
5
|
+
developing; use the same client to connect separate application nodes to a
|
|
6
|
+
remote Delivery server.
|
|
7
|
+
|
|
8
|
+
The [reference](REFERENCE.md) records the complete protocol, retry, and limit
|
|
9
|
+
contract, including API detail for coding agents.
|
|
10
|
+
|
|
11
|
+
## 💡 Why use it?
|
|
12
|
+
|
|
13
|
+
- ✅ Connects a Node process to a local or remote Delivery server.
|
|
14
|
+
- ✅ Reads inbox work and current shard assignments.
|
|
15
|
+
- ✅ Observes later shard changes without polling.
|
|
16
|
+
- ✅ Adapts remote inbox and shard services to `DeliveryBuilder`.
|
|
17
|
+
|
|
18
|
+
## 🚀 Connect and read
|
|
19
|
+
|
|
20
|
+
Connect to an absolute HTTP(S) origin whose path is `/`. The client manages this
|
|
21
|
+
connection and `close()` ends its active reads and streams.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// docs-snippet-path: packages/delivery-client/src/client/client.ts
|
|
25
|
+
import { DeliveryClient } from "@spine-event-engine/delivery-client";
|
|
26
|
+
|
|
27
|
+
const client = DeliveryClient.connectTo("http://127.0.0.1:8484", { pageSize: 100 });
|
|
28
|
+
const shards = await client.shardSnapshot();
|
|
29
|
+
client.close();
|
|
30
|
+
void shards;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Read operations can use the configured bounded retry policy. Mutations never
|
|
34
|
+
retry automatically: a lost mutation response means the remote outcome is
|
|
35
|
+
unknown and must be reconciled before any later action.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// docs-snippet-path: packages/delivery-client/src/client/client.ts
|
|
39
|
+
import { DeliveryOutcomeUnknownError } from "@spine-event-engine/delivery-client";
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// await client.writeOne(message);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof DeliveryOutcomeUnknownError) {
|
|
45
|
+
// Read the fact named by error.reconciliation; do not repeat the mutation.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 👀 Observe shards
|
|
51
|
+
|
|
52
|
+
Use a snapshot to establish current facts and an observation stream for later
|
|
53
|
+
hints. Cancel the stream when it is no longer needed.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// docs-snippet-path: packages/delivery-client/src/client/client.ts
|
|
57
|
+
import { DeliveryClient } from "@spine-event-engine/delivery-client";
|
|
58
|
+
|
|
59
|
+
declare const client: DeliveryClient;
|
|
60
|
+
const updates = client.observeShardUpdates({ timeoutMs: 5_000 });
|
|
61
|
+
for await (const update of updates) {
|
|
62
|
+
console.log(update.shard, update.status);
|
|
63
|
+
updates.cancel();
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Here `timeoutMs` bounds setup through the first acknowledgement only; it never
|
|
68
|
+
ends an acknowledged observation stream.
|
|
69
|
+
|
|
70
|
+
`RemoteInbox` and `RemoteWorkRegistry` adapt a client to a server
|
|
71
|
+
`DeliveryBuilder`. The authoritative delivery state is the remote Inbox row and
|
|
72
|
+
the current shard lease; the client keeps no local removal record. A delivered
|
|
73
|
+
row is the deduplication fact, but a handler effect and its acknowledgement are
|
|
74
|
+
not one transaction. If an acknowledgement is lost, delivery can happen again
|
|
75
|
+
after restart, so make downstream effects idempotent.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// docs-snippet-path: packages/delivery-client/src/remote/adapters.ts
|
|
79
|
+
import {
|
|
80
|
+
DeliveryClient,
|
|
81
|
+
RemoteInbox,
|
|
82
|
+
RemoteWorkRegistry,
|
|
83
|
+
} from "@spine-event-engine/delivery-client";
|
|
84
|
+
import { DeliveryBuilder } from "@spine-event-engine/server";
|
|
85
|
+
|
|
86
|
+
const client = DeliveryClient.connectTo("http://127.0.0.1:8484");
|
|
87
|
+
const delivery = new DeliveryBuilder()
|
|
88
|
+
.withNode("orders-worker")
|
|
89
|
+
.withInbox(new RemoteInbox(client))
|
|
90
|
+
.withWorkRegistry(new RemoteWorkRegistry(client))
|
|
91
|
+
.build();
|
|
92
|
+
client.close();
|
|
93
|
+
void delivery;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
For server assembly, pass one `RemoteDelivery` to the environment instead of
|
|
97
|
+
manually wiring adapters. Each attached environment gets a bounded Admin
|
|
98
|
+
snapshot and later shard-update hints; after a stream loss or bounded-buffer
|
|
99
|
+
overflow it takes a fresh snapshot before resuming updates. Inbox rows and the
|
|
100
|
+
exclusive shard session remain authoritative, so notifications are best-effort
|
|
101
|
+
wake-ups. `open()` runs before the first attachment/listener admission. A
|
|
102
|
+
failed bounded readiness check closes its fresh client and can be retried.
|
|
103
|
+
|
|
104
|
+
When identically configured application nodes share a Delivery server, every
|
|
105
|
+
node observes and attempts each reported shard. The remote registry admits one
|
|
106
|
+
owner for a shard at a time; updates are only hints recovered through a bounded
|
|
107
|
+
snapshot, and the facility makes no ordering promise across different shards.
|
|
108
|
+
The winning owner repeats finite Inbox drains until no deliverable rows remain,
|
|
109
|
+
including rows that arrive while a drain is active, before it releases the
|
|
110
|
+
shard. A pre-commit ownership probe fences known stale owners, but it is not a
|
|
111
|
+
linearizable distributed transaction with Entity storage.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// docs-snippet-path: packages/delivery-client/src/remote/remote-delivery.ts
|
|
115
|
+
import { RemoteDelivery } from "@spine-event-engine/delivery-client";
|
|
116
|
+
|
|
117
|
+
const delivery = RemoteDelivery.connectTo({ endpoint: "https://delivery.example.test" });
|
|
118
|
+
void delivery;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## ⚠️ Design for redelivery
|
|
122
|
+
|
|
123
|
+
Read operations may use the configured bounded retry policy. Mutations do not
|
|
124
|
+
retry automatically: if a response is lost, first read the named fact and
|
|
125
|
+
decide what happened. The protocol is unauthenticated and offers no durable
|
|
126
|
+
client state, exactly-once effects, or renewable fencing. It does not persist
|
|
127
|
+
attempt history or quarantine records.
|
|
128
|
+
|
|
129
|
+
## 🔗 Learn more
|
|
130
|
+
|
|
131
|
+
- [Delivery server](../delivery-server/README.md)
|
|
132
|
+
- [Server delivery APIs](../server/README.md#delivery-and-environment)
|
|
133
|
+
- [Detailed delivery reference](REFERENCE.md)
|
package/REFERENCE.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @spine-event-engine/delivery-client reference
|
|
2
|
+
|
|
3
|
+
This reference gives the exact public Node Delivery client contract. Read the
|
|
4
|
+
[package guide](README.md) first for the local-to-remote delivery path.
|
|
5
|
+
|
|
6
|
+
## Construction and lifecycle
|
|
7
|
+
|
|
8
|
+
`DeliveryClient.connectTo(origin, options?)` accepts an absolute HTTP(S) origin
|
|
9
|
+
with pathname `/`, validates options before opening a Connect HTTP/2
|
|
10
|
+
session, and returns a client. `usingTransport(transport, options?)` is the
|
|
11
|
+
advanced form for a Connect transport supplied by the caller; closing that client does not
|
|
12
|
+
close the supplied transport. `close()` is synchronous and idempotent. It
|
|
13
|
+
aborts active reads and observation streams and closes its session once.
|
|
14
|
+
|
|
15
|
+
Options default to page size 100, no read retry, no retry backoff, no observation
|
|
16
|
+
reconnect, no reconnect backoff, observation buffer 100, and operation timeout
|
|
17
|
+
30000 ms. Page size is 1–1000; retry/reconnect counts are 0–5; backoffs are
|
|
18
|
+
0–10000 ms; observation buffers are 1–1000; finite-operation and observation-setup timeouts are
|
|
19
|
+
1–120000 ms.
|
|
20
|
+
|
|
21
|
+
Worker `nodeId` and `value` must be non-blank and together at most 128 UTF-8
|
|
22
|
+
bytes. Decoded payloads must be Command or Event envelopes. The client rejects
|
|
23
|
+
payloads above 1 MiB, RPC request/response bodies above 4 MiB, batches above
|
|
24
|
+
100, and pages above 1000.
|
|
25
|
+
|
|
26
|
+
## Operations and unknown outcomes
|
|
27
|
+
|
|
28
|
+
`findOne`, `readPage`, `newestPending`, and `shardSnapshot` are safe reads and
|
|
29
|
+
can use bounded retries. `writeOne`, `writeMany`, `removeOne`, `removeMany`,
|
|
30
|
+
`pickUp`, `release`, and `releaseExpired` are single-attempt mutations. A lost
|
|
31
|
+
mutation response raises `DeliveryOutcomeUnknownError`; inspect its
|
|
32
|
+
`reconciliation` instruction, read the remote fact, and do not blindly repeat
|
|
33
|
+
the mutation.
|
|
34
|
+
|
|
35
|
+
`readPage` uses the frozen timestamp-only continuation. If a full timestamp
|
|
36
|
+
boundary cannot continue without loss, it throws `DeliveryPagingError`.
|
|
37
|
+
Protocol-invalid data throws `DeliveryProtocolError`.
|
|
38
|
+
|
|
39
|
+
## Observation and topology
|
|
40
|
+
|
|
41
|
+
`observeShardUpdates()` requires one acknowledgement, has a bounded queue, and
|
|
42
|
+
reconnects only within configured limits. A slow consumer can receive
|
|
43
|
+
`ShardObservationOverflowError`; an unrecoverable stream ends with
|
|
44
|
+
`DeliveryShardObservationError`. Its setup timeout never limits an acknowledged active stream. Observation is a hint: reconcile a known
|
|
45
|
+
mutation with `shardSnapshot()` before a later action.
|
|
46
|
+
|
|
47
|
+
The remote protocol has no renewable lease fence or separate per-pickup-time
|
|
48
|
+
fence. Release is conditional on the supplied worker matching the current
|
|
49
|
+
owner, so a stale worker cannot release a newer worker's session. A `PICKED`
|
|
50
|
+
observation does not clear uncertainty; only `NOT_PICKED` invalidates a stale
|
|
51
|
+
local session and permits a new pickup. Do not release a stale session.
|
|
52
|
+
|
|
53
|
+
`RemoteInbox` and `RemoteWorkRegistry` satisfy the server delivery-builder
|
|
54
|
+
ports. `RemoteInbox` rereads the exact pending remote row before acknowledgement
|
|
55
|
+
and calls the authoritative removal operation directly. It creates no local
|
|
56
|
+
attempt history, receipt, fingerprint, or quarantine record. Shard ownership excludes concurrent
|
|
57
|
+
delivery and delivered rows are the deduplication fact. Handler effects and the
|
|
58
|
+
delivered transition are not transactional: a lost acknowledgement can
|
|
59
|
+
redeliver after restart, so downstream handling must be idempotent. This
|
|
60
|
+
package does not add authentication, authorization, durability, exactly-once
|
|
61
|
+
effects, or a production topology.
|
|
62
|
+
|
|
63
|
+
## Remote delivery in an environment
|
|
64
|
+
|
|
65
|
+
`RemoteDelivery.connectTo({ endpoint, clientOptions? })` creates one lazy
|
|
66
|
+
`ServerEnvironmentDelivery`. Its `open()` creates one client plus one remote
|
|
67
|
+
inbox and work registry, then completes the client's bounded `shardSnapshot()`
|
|
68
|
+
readiness call before publishing those generic ports and its Admin source.
|
|
69
|
+
Every attached environment supervisor takes bounded snapshots, consumes later
|
|
70
|
+
updates as wake-up hints, and takes a fresh snapshot after a watch failure or
|
|
71
|
+
bounded observation overflow before consuming updates again. Durable Inbox rows
|
|
72
|
+
and exclusive shard pickup remain authoritative. Concurrent opens share an
|
|
73
|
+
attempt. A failed attempt closes only its client, and a later open creates a
|
|
74
|
+
fresh client.
|
|
75
|
+
|
|
76
|
+
Every identically configured node observes and attempts every reported shard.
|
|
77
|
+
The remote registry admits exactly one current owner per shard; notifications
|
|
78
|
+
are best-effort hints and snapshot recovery is the convergent source after a
|
|
79
|
+
stream break or bounded overflow. The winning owner repeats finite drains until
|
|
80
|
+
no deliverable Inbox row remains, including rows arriving during an active
|
|
81
|
+
drain, before release. There is no ordering guarantee across shards. The
|
|
82
|
+
immediate pre-commit ownership probe fences a detected stale owner, but cannot
|
|
83
|
+
make remote ownership and Entity storage one linearizable distributed
|
|
84
|
+
transaction.
|
|
85
|
+
|
|
86
|
+
Environment shutdown closes the client's HTTP/2 session. Concurrent/repeated
|
|
87
|
+
close calls share work; a failed phase is the only phase retried. This adds no
|
|
88
|
+
health route, provider selector, worker, or
|
|
89
|
+
delivery-server mode.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { type Transport } from "@connectrpc/connect";
|
|
2
|
+
import type { InboxMessage, InboxMessageId } from "@spine-event-engine/server";
|
|
3
|
+
import { ShardIndex } from "@spine-event-engine/server";
|
|
4
|
+
import { type DeliveryClientOptions, type DeliveryFindOneOptions, type DeliveryMutationOptions, type DeliveryReadPageOptions, type DeliveryShardObservationStream, type DeliveryWorkerId, type ReleasedShardSession, type RemoteShardObservation, type RemoteShardSession } from "./types.js";
|
|
5
|
+
export { DeliveryOutcomeUnknownError, DeliveryPagingError, DeliveryProtocolError, DeliveryShardObservationError, ShardObservationOverflowError, MAX_DELIVERY_BATCH_MESSAGES, MAX_INBOX_PAYLOAD_BYTES, MAX_DELIVERY_RPC_BYTES, } from "./types.js";
|
|
6
|
+
export type { DeliveryClientOptions, DeliveryFindOneOptions, DeliveryMutationOptions, DeliveryReadPageOptions, DeliveryShardObservationStream, DeliveryWorkerId, ReleasedShardSession, RemoteShardObservation, RemoteShardSession, } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Provides a Node client for the frozen delivery-server gRPC API.
|
|
9
|
+
*/
|
|
10
|
+
export declare class DeliveryClient {
|
|
11
|
+
#private;
|
|
12
|
+
private constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Gets the bounded page size configured for this client.
|
|
15
|
+
* @returns The maximum number of messages requested by default.
|
|
16
|
+
*/
|
|
17
|
+
get pageSize(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a client over a caller-owned standard Connect transport.
|
|
20
|
+
* @param transport Sends requests to the remote delivery service.
|
|
21
|
+
* @param options Configures bounded reads and observations.
|
|
22
|
+
* @returns A client that never closes the supplied transport.
|
|
23
|
+
*/
|
|
24
|
+
static usingTransport(transport: Transport, options?: DeliveryClientOptions): DeliveryClient;
|
|
25
|
+
/**
|
|
26
|
+
* Connects to a JVM delivery server with a client-owned HTTP/2 gRPC session.
|
|
27
|
+
*
|
|
28
|
+
* The URL and options are validated before opening the session. `close()` is
|
|
29
|
+
* synchronous: it aborts active calls and the owned session immediately; it
|
|
30
|
+
* does not wait for remote stream cleanup. Use {@link usingTransport} when
|
|
31
|
+
* the caller owns the transport lifecycle.
|
|
32
|
+
* @param baseUrl Supplies the absolute HTTP(S) delivery-server origin.
|
|
33
|
+
* @param options Configures bounded reads and observations.
|
|
34
|
+
* @returns A client that aborts its owned session when closed.
|
|
35
|
+
*/
|
|
36
|
+
static connectTo(baseUrl: string, options?: DeliveryClientOptions): DeliveryClient;
|
|
37
|
+
/**
|
|
38
|
+
* Reads validated detached Admin observations.
|
|
39
|
+
* @param options Bounds or cancels the read.
|
|
40
|
+
* @returns Detached observations that callers may safely mutate.
|
|
41
|
+
*/
|
|
42
|
+
shardSnapshot(options?: DeliveryFindOneOptions): Promise<readonly RemoteShardObservation[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Starts an ACK-gated Admin shard-update observation stream.
|
|
45
|
+
* @param options Bounds stream setup and cancels its lifetime.
|
|
46
|
+
* @returns A cancellable stream of detached shard observations.
|
|
47
|
+
*/
|
|
48
|
+
observeShardUpdates(options?: DeliveryFindOneOptions): DeliveryShardObservationStream;
|
|
49
|
+
/**
|
|
50
|
+
* Finds and decodes one inbox message.
|
|
51
|
+
* @param id Identifies the inbox message and its shard.
|
|
52
|
+
* @param options Bounds or cancels the safe read.
|
|
53
|
+
* @returns The detached message, or `undefined` when absent.
|
|
54
|
+
*/
|
|
55
|
+
findOne(id: InboxMessageId, options?: DeliveryFindOneOptions): Promise<InboxMessage | undefined>;
|
|
56
|
+
/**
|
|
57
|
+
* Reads and decodes the first bounded ordered page for one shard.
|
|
58
|
+
*
|
|
59
|
+
* A server rejects an encoded response above 4 MiB with `RESOURCE_EXHAUSTED`;
|
|
60
|
+
* retry this safe read with a smaller `pageSize`.
|
|
61
|
+
* @param shardIndex Identifies the shard to read.
|
|
62
|
+
* @param options Supplies page continuation, size, and read bounds.
|
|
63
|
+
* @returns Detached messages in remote timestamp order.
|
|
64
|
+
*/
|
|
65
|
+
readPage(shardIndex: ShardIndex, options?: DeliveryReadPageOptions): Promise<readonly InboxMessage[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Finds and decodes the newest pending message in a shard.
|
|
68
|
+
* @param shardIndex Identifies the shard to inspect.
|
|
69
|
+
* @param options Bounds or cancels the safe read.
|
|
70
|
+
* @returns The detached newest message, or `undefined` when absent.
|
|
71
|
+
*/
|
|
72
|
+
newestPending(shardIndex: ShardIndex, options?: DeliveryFindOneOptions): Promise<InboxMessage | undefined>;
|
|
73
|
+
/**
|
|
74
|
+
* Writes one message with exactly one delivery-server RPC attempt.
|
|
75
|
+
* @param message Supplies the message to write.
|
|
76
|
+
* @param options Bounds or cancels the mutation.
|
|
77
|
+
* @returns A promise that completes after the delivery server accepts the message.
|
|
78
|
+
*/
|
|
79
|
+
writeOne(message: InboxMessage, options?: DeliveryMutationOptions): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Removes one message with exactly one delivery-server RPC attempt.
|
|
82
|
+
* @param message Supplies the message to remove.
|
|
83
|
+
* @param options Bounds or cancels the mutation.
|
|
84
|
+
* @returns A promise that completes after the delivery server removes the message.
|
|
85
|
+
*/
|
|
86
|
+
removeOne(message: InboxMessage, options?: DeliveryMutationOptions): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Writes one bounded same-shard batch with exactly one delivery-server RPC attempt.
|
|
89
|
+
* @param messages Supplies the messages to write.
|
|
90
|
+
* @param options Bounds or cancels the mutation.
|
|
91
|
+
* @returns A promise that completes after the delivery server accepts the batch.
|
|
92
|
+
*/
|
|
93
|
+
writeMany(messages: readonly InboxMessage[], options?: DeliveryMutationOptions): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Removes one bounded same-shard batch with exactly one delivery-server RPC attempt.
|
|
96
|
+
* @param messages Supplies the messages to remove.
|
|
97
|
+
* @param options Bounds or cancels the mutation.
|
|
98
|
+
* @returns A promise that completes after the delivery server removes the batch.
|
|
99
|
+
*/
|
|
100
|
+
removeMany(messages: readonly InboxMessage[], options?: DeliveryMutationOptions): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Acquires a shard once.
|
|
103
|
+
* @param shardIndex Identifies the shard to acquire.
|
|
104
|
+
* @param workerId Identifies the worker requesting exclusive ownership.
|
|
105
|
+
* @param options Bounds or cancels the mutation.
|
|
106
|
+
* @returns A detached exclusive session, or `undefined` when held elsewhere.
|
|
107
|
+
*/
|
|
108
|
+
pickUp(shardIndex: ShardIndex, workerId: DeliveryWorkerId, options?: DeliveryMutationOptions): Promise<RemoteShardSession | undefined>;
|
|
109
|
+
/**
|
|
110
|
+
* Performs one exclusive shard-session release.
|
|
111
|
+
* @param value Supplies the session to release.
|
|
112
|
+
* @param options Bounds or cancels the mutation.
|
|
113
|
+
* @returns A promise that completes after the delivery server releases the session.
|
|
114
|
+
*/
|
|
115
|
+
release(value: RemoteShardSession, options?: DeliveryMutationOptions): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Performs releases for sessions inactive for a positive duration.
|
|
118
|
+
* @param inactivityMs Supplies the minimum inactivity in milliseconds.
|
|
119
|
+
* @param options Bounds or cancels the mutation.
|
|
120
|
+
* @returns Detached sessions released by the remote service.
|
|
121
|
+
*/
|
|
122
|
+
releaseExpired(inactivityMs: number, options?: DeliveryMutationOptions): Promise<readonly ReleasedShardSession[]>;
|
|
123
|
+
/**
|
|
124
|
+
* Closes this client by permanently aborting active reads and streams. This synchronous, idempotent
|
|
125
|
+
* method also aborts an owned HTTP/2 session, but never closes injected transport.
|
|
126
|
+
*/
|
|
127
|
+
close(): void;
|
|
128
|
+
}
|
|
129
|
+
type RemoteShardProbe = Readonly<{
|
|
130
|
+
readonly kind: "PICKED";
|
|
131
|
+
readonly session: RemoteShardSession;
|
|
132
|
+
}> | Readonly<{
|
|
133
|
+
readonly kind: "ALREADY_PICKED";
|
|
134
|
+
readonly session: RemoteShardSession;
|
|
135
|
+
}>;
|
|
136
|
+
/**
|
|
137
|
+
* Provides package-internal frozen-wire ownership probes without extending the public client API.
|
|
138
|
+
*/
|
|
139
|
+
export declare const deliveryClientAccess: Readonly<{
|
|
140
|
+
probePickUp: (client: DeliveryClient, shardIndex: ShardIndex, workerId: DeliveryWorkerId, options: DeliveryMutationOptions) => Promise<RemoteShardProbe>;
|
|
141
|
+
observeOnce: (client: DeliveryClient, options?: DeliveryFindOneOptions) => DeliveryShardObservationStream;
|
|
142
|
+
}>;
|
|
143
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
|