@relaybus/mongodb 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -88
- package/dist/index.cjs +1957 -510
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -20
- package/dist/index.d.ts +159 -20
- package/dist/index.js +1958 -511
- package/dist/index.js.map +1 -1
- package/package.json +22 -9
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventStore, IdentifierGenerator, AppendEntry, AppendResult, ClaimRequest, ClaimedDelivery, LeaseReference, ErrorInfo, DeliveryQuery, DeliveryRecord, PurgeRequest, PurgeResult, EventStoreStatistics } from '@relaybus/core';
|
|
1
|
+
import { EventStore, RelayBusLogger, IdentifierGenerator, EventStoreTransactionOptions, AppendEntry, AppendResult, ClaimRequest, ClaimedDelivery, LeaseReference, ErrorInfo, DeliveryQuery, DeliveryRecord, PurgeRequest, PurgeResult, EventStoreStatistics } from '@relaybus/core';
|
|
2
2
|
import { ClientSession, MongoClient, TransactionOptions } from 'mongodb';
|
|
3
3
|
|
|
4
4
|
interface MongoEventStoreOptions {
|
|
@@ -6,7 +6,7 @@ interface MongoEventStoreOptions {
|
|
|
6
6
|
readonly client: MongoClient;
|
|
7
7
|
/** Database holding the relaybus collections. Default: the client's default database. */
|
|
8
8
|
readonly database?: string;
|
|
9
|
-
/** Prefix of the
|
|
9
|
+
/** Prefix of the collection names. Default `relaybus_`. */
|
|
10
10
|
readonly collectionPrefix?: string;
|
|
11
11
|
/**
|
|
12
12
|
* Options of the transactions the store opens. Default: snapshot read
|
|
@@ -15,7 +15,20 @@ interface MongoEventStoreOptions {
|
|
|
15
15
|
readonly transactionOptions?: TransactionOptions;
|
|
16
16
|
/** Rows deleted per purge step. Default 500. */
|
|
17
17
|
readonly purgeBatchSize?: number;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Keep an append-only record of every completed delivery in
|
|
20
|
+
* `<prefix>completed_deliveries`, listed as `completed`, counted by
|
|
21
|
+
* `statistics` and removed by `purge({ completedBefore })`. Default false: a
|
|
22
|
+
* completed delivery is deleted and leaves nothing behind. Use the same value
|
|
23
|
+
* in every process.
|
|
24
|
+
*/
|
|
25
|
+
readonly completionHistory?: boolean;
|
|
26
|
+
/** Receives warnings about best-effort steps that failed (parking). Default `console`. */
|
|
27
|
+
readonly logger?: RelayBusLogger;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated Ignored. Lease tokens name the lane and its epoch
|
|
30
|
+
* (`<laneId>:<epoch>:<claims>`) and are no longer generated.
|
|
31
|
+
*/
|
|
19
32
|
readonly generateIdentifier?: IdentifierGenerator;
|
|
20
33
|
}
|
|
21
34
|
/**
|
|
@@ -24,29 +37,75 @@ interface MongoEventStoreOptions {
|
|
|
24
37
|
* session can carry your own writes (native driver or Mongoose).
|
|
25
38
|
*
|
|
26
39
|
* Guarantees:
|
|
27
|
-
* - `append` is atomic with the caller's writes
|
|
28
|
-
* (event id, handler).
|
|
40
|
+
* - **Atomic, idempotent append.** `append` is atomic with the caller's writes
|
|
41
|
+
* and idempotent on event id and on (event id, handler). An event remembers
|
|
42
|
+
* every handler it ever had a delivery for, so a redelivered or republished
|
|
43
|
+
* event never runs a completed handler again although completed deliveries are
|
|
44
|
+
* deleted. Duplicates are detected by reading, never by catching a
|
|
29
45
|
* duplicate-key error, which would abort the surrounding transaction.
|
|
30
|
-
* - Per-key sequences
|
|
31
|
-
* transaction. Two transactions appending the same key cannot both hold
|
|
32
|
-
* counter, so the loser conflicts, restarts after the winner committed, and
|
|
33
|
-
* its sequence is higher: sequence order is commit order.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
46
|
+
* - **Per-key order.** Per-key sequences come from a counter document inside the
|
|
47
|
+
* append transaction. Two transactions appending the same key cannot both hold
|
|
48
|
+
* the counter, so the loser conflicts, restarts after the winner committed, and
|
|
49
|
+
* its sequence is higher: sequence order is commit order. A keyed delivery is
|
|
50
|
+
* claimed only when no earlier delivery of its handler and key is pending and
|
|
51
|
+
* no other delivery of them runs.
|
|
52
|
+
* - **Lane leases.** Every delivery belongs to one of 256 lanes (a hash of its
|
|
53
|
+
* ordering key, or of its event id), so all deliveries of a key share a lane.
|
|
54
|
+
* Workers lease lanes with one conditional write on a lane document, and a
|
|
55
|
+
* claim records its whole batch in the lane documents: it writes no delivery
|
|
56
|
+
* document. While a lane lease is live, other workers do not see the pending
|
|
57
|
+
* deliveries of that lane, even idle ones. A lane changes hands only when its
|
|
58
|
+
* lease expired or its owner handed it back.
|
|
59
|
+
* - **Fencing.** A lease token is `<laneId>:<epoch>:<claims>`. The epoch grows
|
|
60
|
+
* whenever the lane is taken; `claims`, the delivery's claim generation, grows
|
|
61
|
+
* whenever a claim of it ends (retry, release, burial, lost lease), so the
|
|
62
|
+
* lease of an earlier claim never matches a later claim of the same delivery
|
|
63
|
+
* in the same lane epoch. Completion, retry, burial, release and renewal apply
|
|
64
|
+
* only while the lane has that epoch, lists the delivery as in flight, and the
|
|
65
|
+
* delivery has that claim generation.
|
|
66
|
+
* - **Effectively-once for transactional handlers.** A worker that takes a lane
|
|
67
|
+
* over first writes every delivery the previous owner had in flight (it
|
|
68
|
+
* charges the lost attempt) and only then reads what to claim. A completion
|
|
69
|
+
* inside a transaction (a transactional handler's, or any completion when a
|
|
70
|
+
* completion history is kept) deletes the delivery after checking the lane:
|
|
71
|
+
* both write the same delivery document, so the later of the two either
|
|
72
|
+
* conflicts and retries (and then sees the new epoch or the missing
|
|
73
|
+
* delivery), or waits for the earlier to commit. Other completions run
|
|
74
|
+
* without a transaction: they read the deliveries' claim generations, then
|
|
75
|
+
* the lanes, and delete only deliveries whose generation did not change,
|
|
76
|
+
* which a takeover, a retry or a release always changes. Either way a completion and a takeover
|
|
77
|
+
* cannot both succeed. Completions never write the lane document, so
|
|
78
|
+
* concurrent completions of one lane never conflict with each other.
|
|
79
|
+
* - **Attempts survive crashes.** `attempts` counts attempts that ended. The
|
|
80
|
+
* claim result reports `attempts + 1`; a failure records it; a lane taken over
|
|
81
|
+
* charges one attempt to every delivery the previous owner still had in flight,
|
|
82
|
+
* so a poison message still reaches the retry limit after crashes.
|
|
83
|
+
*
|
|
84
|
+
* - **Deduplication record.** A completion records its time on the event
|
|
85
|
+
* (`completedAt`). An event nothing references any more stays until
|
|
86
|
+
* `purge({ completedBefore })` passes that time, however old the event is, and
|
|
87
|
+
* `deadBefore` alone never removes it. Once purged, the event takes its list
|
|
88
|
+
* of handlers with it: a broker redelivery or publish retry of that event id
|
|
89
|
+
* afterwards is appended as a new event and runs its handlers again, as in
|
|
90
|
+
* the PostgreSQL store, so keep completed retention longer than any
|
|
91
|
+
* redelivery window.
|
|
41
92
|
*
|
|
42
93
|
* `transaction` may run `work` more than once (see {@link MongoEventStore.transaction}).
|
|
94
|
+
* Claims of one `leaseOwner` on one store instance run one after the other
|
|
95
|
+
* (a claim that overlaps another of the same owner waits for it); different
|
|
96
|
+
* owners claim concurrently, from any number of processes. Lanes are held per store
|
|
97
|
+
* instance, so a process restarted with the same `leaseOwner` takes its
|
|
98
|
+
* predecessor's lanes over only once their leases expired.
|
|
43
99
|
*/
|
|
44
100
|
declare class MongoEventStore implements EventStore<ClientSession> {
|
|
45
101
|
#private;
|
|
46
102
|
constructor(options: MongoEventStoreOptions);
|
|
47
103
|
/**
|
|
48
|
-
* Verifies the deployment supports transactions
|
|
49
|
-
*
|
|
104
|
+
* Verifies the deployment supports transactions, creates the collections and
|
|
105
|
+
* indexes and seeds the lane documents. Upgrades a 0.1.0 database in place
|
|
106
|
+
* first (see `MongoSchema.#upgradeFromVersion010`); the seeded lanes
|
|
107
|
+
* mark the upgrade as done, so later runs skip it. Safe to run repeatedly and
|
|
108
|
+
* from several processes. Stop 0.1.0 workers before the first run.
|
|
50
109
|
*
|
|
51
110
|
* @throws ConfigurationError when the server is a standalone mongod.
|
|
52
111
|
*/
|
|
@@ -61,19 +120,99 @@ declare class MongoEventStore implements EventStore<ClientSession> {
|
|
|
61
120
|
* not safe for side effects outside the session (HTTP calls, other databases),
|
|
62
121
|
* so keep those out of `work`; relaybus handlers are already at-least-once.
|
|
63
122
|
*
|
|
123
|
+
* With `options.timeoutMs` (from `bus.transaction`) the server bounds the commit with
|
|
124
|
+
* `maxCommitTimeMS`; the bus aborts a transaction that ran past the budget before its commit.
|
|
125
|
+
*
|
|
64
126
|
* @throws ConfigurationError when the deployment does not support transactions.
|
|
65
127
|
*/
|
|
66
|
-
transaction<T>(work: (transaction: ClientSession) => Promise<T
|
|
128
|
+
transaction<T>(work: (transaction: ClientSession) => Promise<T>, options?: EventStoreTransactionOptions): Promise<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Writes the entries in `session`. An existing event gets a delivery only for
|
|
131
|
+
* handlers it does not list yet; the added handlers are appended to its list
|
|
132
|
+
* together with a `revision` increment, a real write that makes a concurrent
|
|
133
|
+
* purge of the event conflict with this transaction.
|
|
134
|
+
*/
|
|
67
135
|
append(session: ClientSession, entries: readonly AppendEntry[], now: Date): Promise<AppendResult>;
|
|
136
|
+
/**
|
|
137
|
+
* Claims up to `limit` due deliveries. It claims from the lanes this owner
|
|
138
|
+
* (and this store instance) holds under a live lease first, then takes free
|
|
139
|
+
* lanes with due work, a few at a time (4, 8, 16, ...) and the lane with the
|
|
140
|
+
* oldest due delivery first, so a worker holds only as many lanes as it
|
|
141
|
+
* needs. It then records the batch with one write per lane and hands back the
|
|
142
|
+
* lanes that yielded nothing and run nothing. No delivery document is
|
|
143
|
+
* written, except for the attempt charged to deliveries of a lane taken over
|
|
144
|
+
* and for parking (see `MongoOrdering.#parkDeliveries`).
|
|
145
|
+
*
|
|
146
|
+
* Taking a lane is one conditional `findOneAndUpdate` that also moves the
|
|
147
|
+
* previous owner's in-flight list to the lane's `lost` list; a lane another
|
|
148
|
+
* claimer took first is skipped, never waited for. Lost deliveries are charged
|
|
149
|
+
* one attempt before anything is read from the lane, and `lost` is cleared
|
|
150
|
+
* only after that. Whoever holds the lane next charges a `lost` list it finds
|
|
151
|
+
* first, so a claim that fails anywhere after the take loses no charge; the
|
|
152
|
+
* charge of a lost claim is recorded on the delivery, so charging the list
|
|
153
|
+
* again after a failure before the clear charges nothing twice.
|
|
154
|
+
* Nothing a failed claim did leaves a delivery listed as running.
|
|
155
|
+
*/
|
|
68
156
|
claim(request: ClaimRequest): Promise<ClaimedDelivery[]>;
|
|
69
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Extends the lease of the lane a running delivery belongs to. The lane lease
|
|
159
|
+
* never shrinks, so a repeated renewal with the same value still holds. An
|
|
160
|
+
* expired lease nobody took over is still renewed, so `_now` is not needed.
|
|
161
|
+
*/
|
|
162
|
+
extendLease(lease: LeaseReference, leaseExpiresAt: Date, _now?: Date): Promise<boolean>;
|
|
163
|
+
/**
|
|
164
|
+
* Deletes the delivery (and records it in the completion history, when kept).
|
|
165
|
+
* With `session` the deletion commits with the caller's transaction; without,
|
|
166
|
+
* it runs in a transaction of its own. Returns false when the lease was lost.
|
|
167
|
+
*/
|
|
70
168
|
complete(lease: LeaseReference, now: Date, session?: ClientSession): Promise<boolean>;
|
|
169
|
+
/**
|
|
170
|
+
* Completes many leases with a fixed number of round trips, whatever lanes
|
|
171
|
+
* they belong to: three commands without a completion history, one
|
|
172
|
+
* transaction with it (see `MongoCompletion.#deleteFenced`).
|
|
173
|
+
* Returns one flag per lease in input order; a lease listed twice completes
|
|
174
|
+
* once, and a token this store cannot have issued is refused.
|
|
175
|
+
*/
|
|
176
|
+
completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]>;
|
|
177
|
+
/** Returns a running delivery to pending, due at `availableAt`, and counts the attempt that ended. */
|
|
71
178
|
reschedule(lease: LeaseReference, availableAt: Date, error: ErrorInfo, now: Date): Promise<boolean>;
|
|
179
|
+
/** Gives a running delivery back without counting the attempt: pending, due `now`. */
|
|
72
180
|
release(lease: LeaseReference, now: Date): Promise<boolean>;
|
|
181
|
+
/** Moves a running delivery to dead and counts the attempt that ended. */
|
|
73
182
|
bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean>;
|
|
183
|
+
/**
|
|
184
|
+
* Frees every lane `leaseOwner` holds that runs no delivery, so other workers
|
|
185
|
+
* need not wait for the lease to expire. Lanes with running deliveries stay leased.
|
|
186
|
+
*/
|
|
187
|
+
relinquish(leaseOwner: string): Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* Lists deliveries in creation order. A delivery is `processing` while its
|
|
190
|
+
* document exists as `pending` and its lane lists it; its attempt count then
|
|
191
|
+
* includes the running attempt, and owner and expiry are those of the lane
|
|
192
|
+
* lease. Completion history records (when kept) are listed as `completed`.
|
|
193
|
+
*/
|
|
74
194
|
listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]>;
|
|
195
|
+
/** Moves dead deliveries back to pending with a fresh attempt budget. */
|
|
75
196
|
requeue(deliveryIds: readonly string[], now: Date): Promise<number>;
|
|
197
|
+
/**
|
|
198
|
+
* Deletes, in batches of `purgeBatchSize`, dead deliveries last updated before
|
|
199
|
+
* `deadBefore`, and completion history records (and `completed` documents left
|
|
200
|
+
* by 0.1.0) completed before `completedBefore`, each batch in one transaction
|
|
201
|
+
* together with the events it left without any reference. Finally, events
|
|
202
|
+
* nothing references are deleted: one with a completed delivery once its last
|
|
203
|
+
* completion is before `completedBefore` (never by `deadBefore` alone), one
|
|
204
|
+
* that never had a completion (no subscribers, or only dead letters) once it
|
|
205
|
+
* was created before the earliest given cutoff. The batch step applies the
|
|
206
|
+
* same rule to events whose last completion is recorded.
|
|
207
|
+
*/
|
|
76
208
|
purge(request: PurgeRequest): Promise<PurgeResult>;
|
|
209
|
+
/**
|
|
210
|
+
* Counts by derived status. `pending` excludes running deliveries; `completed`
|
|
211
|
+
* counts history records and 0.1.0 `completed` documents. `oldestDueAt` is the
|
|
212
|
+
* oldest instant at which a delivery became claimable: the due time of a
|
|
213
|
+
* pending delivery nobody runs, or the lease expiry of a lane that still runs
|
|
214
|
+
* deliveries.
|
|
215
|
+
*/
|
|
77
216
|
statistics(now: Date): Promise<EventStoreStatistics>;
|
|
78
217
|
}
|
|
79
218
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventStore, IdentifierGenerator, AppendEntry, AppendResult, ClaimRequest, ClaimedDelivery, LeaseReference, ErrorInfo, DeliveryQuery, DeliveryRecord, PurgeRequest, PurgeResult, EventStoreStatistics } from '@relaybus/core';
|
|
1
|
+
import { EventStore, RelayBusLogger, IdentifierGenerator, EventStoreTransactionOptions, AppendEntry, AppendResult, ClaimRequest, ClaimedDelivery, LeaseReference, ErrorInfo, DeliveryQuery, DeliveryRecord, PurgeRequest, PurgeResult, EventStoreStatistics } from '@relaybus/core';
|
|
2
2
|
import { ClientSession, MongoClient, TransactionOptions } from 'mongodb';
|
|
3
3
|
|
|
4
4
|
interface MongoEventStoreOptions {
|
|
@@ -6,7 +6,7 @@ interface MongoEventStoreOptions {
|
|
|
6
6
|
readonly client: MongoClient;
|
|
7
7
|
/** Database holding the relaybus collections. Default: the client's default database. */
|
|
8
8
|
readonly database?: string;
|
|
9
|
-
/** Prefix of the
|
|
9
|
+
/** Prefix of the collection names. Default `relaybus_`. */
|
|
10
10
|
readonly collectionPrefix?: string;
|
|
11
11
|
/**
|
|
12
12
|
* Options of the transactions the store opens. Default: snapshot read
|
|
@@ -15,7 +15,20 @@ interface MongoEventStoreOptions {
|
|
|
15
15
|
readonly transactionOptions?: TransactionOptions;
|
|
16
16
|
/** Rows deleted per purge step. Default 500. */
|
|
17
17
|
readonly purgeBatchSize?: number;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Keep an append-only record of every completed delivery in
|
|
20
|
+
* `<prefix>completed_deliveries`, listed as `completed`, counted by
|
|
21
|
+
* `statistics` and removed by `purge({ completedBefore })`. Default false: a
|
|
22
|
+
* completed delivery is deleted and leaves nothing behind. Use the same value
|
|
23
|
+
* in every process.
|
|
24
|
+
*/
|
|
25
|
+
readonly completionHistory?: boolean;
|
|
26
|
+
/** Receives warnings about best-effort steps that failed (parking). Default `console`. */
|
|
27
|
+
readonly logger?: RelayBusLogger;
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated Ignored. Lease tokens name the lane and its epoch
|
|
30
|
+
* (`<laneId>:<epoch>:<claims>`) and are no longer generated.
|
|
31
|
+
*/
|
|
19
32
|
readonly generateIdentifier?: IdentifierGenerator;
|
|
20
33
|
}
|
|
21
34
|
/**
|
|
@@ -24,29 +37,75 @@ interface MongoEventStoreOptions {
|
|
|
24
37
|
* session can carry your own writes (native driver or Mongoose).
|
|
25
38
|
*
|
|
26
39
|
* Guarantees:
|
|
27
|
-
* - `append` is atomic with the caller's writes
|
|
28
|
-
* (event id, handler).
|
|
40
|
+
* - **Atomic, idempotent append.** `append` is atomic with the caller's writes
|
|
41
|
+
* and idempotent on event id and on (event id, handler). An event remembers
|
|
42
|
+
* every handler it ever had a delivery for, so a redelivered or republished
|
|
43
|
+
* event never runs a completed handler again although completed deliveries are
|
|
44
|
+
* deleted. Duplicates are detected by reading, never by catching a
|
|
29
45
|
* duplicate-key error, which would abort the surrounding transaction.
|
|
30
|
-
* - Per-key sequences
|
|
31
|
-
* transaction. Two transactions appending the same key cannot both hold
|
|
32
|
-
* counter, so the loser conflicts, restarts after the winner committed, and
|
|
33
|
-
* its sequence is higher: sequence order is commit order.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
46
|
+
* - **Per-key order.** Per-key sequences come from a counter document inside the
|
|
47
|
+
* append transaction. Two transactions appending the same key cannot both hold
|
|
48
|
+
* the counter, so the loser conflicts, restarts after the winner committed, and
|
|
49
|
+
* its sequence is higher: sequence order is commit order. A keyed delivery is
|
|
50
|
+
* claimed only when no earlier delivery of its handler and key is pending and
|
|
51
|
+
* no other delivery of them runs.
|
|
52
|
+
* - **Lane leases.** Every delivery belongs to one of 256 lanes (a hash of its
|
|
53
|
+
* ordering key, or of its event id), so all deliveries of a key share a lane.
|
|
54
|
+
* Workers lease lanes with one conditional write on a lane document, and a
|
|
55
|
+
* claim records its whole batch in the lane documents: it writes no delivery
|
|
56
|
+
* document. While a lane lease is live, other workers do not see the pending
|
|
57
|
+
* deliveries of that lane, even idle ones. A lane changes hands only when its
|
|
58
|
+
* lease expired or its owner handed it back.
|
|
59
|
+
* - **Fencing.** A lease token is `<laneId>:<epoch>:<claims>`. The epoch grows
|
|
60
|
+
* whenever the lane is taken; `claims`, the delivery's claim generation, grows
|
|
61
|
+
* whenever a claim of it ends (retry, release, burial, lost lease), so the
|
|
62
|
+
* lease of an earlier claim never matches a later claim of the same delivery
|
|
63
|
+
* in the same lane epoch. Completion, retry, burial, release and renewal apply
|
|
64
|
+
* only while the lane has that epoch, lists the delivery as in flight, and the
|
|
65
|
+
* delivery has that claim generation.
|
|
66
|
+
* - **Effectively-once for transactional handlers.** A worker that takes a lane
|
|
67
|
+
* over first writes every delivery the previous owner had in flight (it
|
|
68
|
+
* charges the lost attempt) and only then reads what to claim. A completion
|
|
69
|
+
* inside a transaction (a transactional handler's, or any completion when a
|
|
70
|
+
* completion history is kept) deletes the delivery after checking the lane:
|
|
71
|
+
* both write the same delivery document, so the later of the two either
|
|
72
|
+
* conflicts and retries (and then sees the new epoch or the missing
|
|
73
|
+
* delivery), or waits for the earlier to commit. Other completions run
|
|
74
|
+
* without a transaction: they read the deliveries' claim generations, then
|
|
75
|
+
* the lanes, and delete only deliveries whose generation did not change,
|
|
76
|
+
* which a takeover, a retry or a release always changes. Either way a completion and a takeover
|
|
77
|
+
* cannot both succeed. Completions never write the lane document, so
|
|
78
|
+
* concurrent completions of one lane never conflict with each other.
|
|
79
|
+
* - **Attempts survive crashes.** `attempts` counts attempts that ended. The
|
|
80
|
+
* claim result reports `attempts + 1`; a failure records it; a lane taken over
|
|
81
|
+
* charges one attempt to every delivery the previous owner still had in flight,
|
|
82
|
+
* so a poison message still reaches the retry limit after crashes.
|
|
83
|
+
*
|
|
84
|
+
* - **Deduplication record.** A completion records its time on the event
|
|
85
|
+
* (`completedAt`). An event nothing references any more stays until
|
|
86
|
+
* `purge({ completedBefore })` passes that time, however old the event is, and
|
|
87
|
+
* `deadBefore` alone never removes it. Once purged, the event takes its list
|
|
88
|
+
* of handlers with it: a broker redelivery or publish retry of that event id
|
|
89
|
+
* afterwards is appended as a new event and runs its handlers again, as in
|
|
90
|
+
* the PostgreSQL store, so keep completed retention longer than any
|
|
91
|
+
* redelivery window.
|
|
41
92
|
*
|
|
42
93
|
* `transaction` may run `work` more than once (see {@link MongoEventStore.transaction}).
|
|
94
|
+
* Claims of one `leaseOwner` on one store instance run one after the other
|
|
95
|
+
* (a claim that overlaps another of the same owner waits for it); different
|
|
96
|
+
* owners claim concurrently, from any number of processes. Lanes are held per store
|
|
97
|
+
* instance, so a process restarted with the same `leaseOwner` takes its
|
|
98
|
+
* predecessor's lanes over only once their leases expired.
|
|
43
99
|
*/
|
|
44
100
|
declare class MongoEventStore implements EventStore<ClientSession> {
|
|
45
101
|
#private;
|
|
46
102
|
constructor(options: MongoEventStoreOptions);
|
|
47
103
|
/**
|
|
48
|
-
* Verifies the deployment supports transactions
|
|
49
|
-
*
|
|
104
|
+
* Verifies the deployment supports transactions, creates the collections and
|
|
105
|
+
* indexes and seeds the lane documents. Upgrades a 0.1.0 database in place
|
|
106
|
+
* first (see `MongoSchema.#upgradeFromVersion010`); the seeded lanes
|
|
107
|
+
* mark the upgrade as done, so later runs skip it. Safe to run repeatedly and
|
|
108
|
+
* from several processes. Stop 0.1.0 workers before the first run.
|
|
50
109
|
*
|
|
51
110
|
* @throws ConfigurationError when the server is a standalone mongod.
|
|
52
111
|
*/
|
|
@@ -61,19 +120,99 @@ declare class MongoEventStore implements EventStore<ClientSession> {
|
|
|
61
120
|
* not safe for side effects outside the session (HTTP calls, other databases),
|
|
62
121
|
* so keep those out of `work`; relaybus handlers are already at-least-once.
|
|
63
122
|
*
|
|
123
|
+
* With `options.timeoutMs` (from `bus.transaction`) the server bounds the commit with
|
|
124
|
+
* `maxCommitTimeMS`; the bus aborts a transaction that ran past the budget before its commit.
|
|
125
|
+
*
|
|
64
126
|
* @throws ConfigurationError when the deployment does not support transactions.
|
|
65
127
|
*/
|
|
66
|
-
transaction<T>(work: (transaction: ClientSession) => Promise<T
|
|
128
|
+
transaction<T>(work: (transaction: ClientSession) => Promise<T>, options?: EventStoreTransactionOptions): Promise<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Writes the entries in `session`. An existing event gets a delivery only for
|
|
131
|
+
* handlers it does not list yet; the added handlers are appended to its list
|
|
132
|
+
* together with a `revision` increment, a real write that makes a concurrent
|
|
133
|
+
* purge of the event conflict with this transaction.
|
|
134
|
+
*/
|
|
67
135
|
append(session: ClientSession, entries: readonly AppendEntry[], now: Date): Promise<AppendResult>;
|
|
136
|
+
/**
|
|
137
|
+
* Claims up to `limit` due deliveries. It claims from the lanes this owner
|
|
138
|
+
* (and this store instance) holds under a live lease first, then takes free
|
|
139
|
+
* lanes with due work, a few at a time (4, 8, 16, ...) and the lane with the
|
|
140
|
+
* oldest due delivery first, so a worker holds only as many lanes as it
|
|
141
|
+
* needs. It then records the batch with one write per lane and hands back the
|
|
142
|
+
* lanes that yielded nothing and run nothing. No delivery document is
|
|
143
|
+
* written, except for the attempt charged to deliveries of a lane taken over
|
|
144
|
+
* and for parking (see `MongoOrdering.#parkDeliveries`).
|
|
145
|
+
*
|
|
146
|
+
* Taking a lane is one conditional `findOneAndUpdate` that also moves the
|
|
147
|
+
* previous owner's in-flight list to the lane's `lost` list; a lane another
|
|
148
|
+
* claimer took first is skipped, never waited for. Lost deliveries are charged
|
|
149
|
+
* one attempt before anything is read from the lane, and `lost` is cleared
|
|
150
|
+
* only after that. Whoever holds the lane next charges a `lost` list it finds
|
|
151
|
+
* first, so a claim that fails anywhere after the take loses no charge; the
|
|
152
|
+
* charge of a lost claim is recorded on the delivery, so charging the list
|
|
153
|
+
* again after a failure before the clear charges nothing twice.
|
|
154
|
+
* Nothing a failed claim did leaves a delivery listed as running.
|
|
155
|
+
*/
|
|
68
156
|
claim(request: ClaimRequest): Promise<ClaimedDelivery[]>;
|
|
69
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Extends the lease of the lane a running delivery belongs to. The lane lease
|
|
159
|
+
* never shrinks, so a repeated renewal with the same value still holds. An
|
|
160
|
+
* expired lease nobody took over is still renewed, so `_now` is not needed.
|
|
161
|
+
*/
|
|
162
|
+
extendLease(lease: LeaseReference, leaseExpiresAt: Date, _now?: Date): Promise<boolean>;
|
|
163
|
+
/**
|
|
164
|
+
* Deletes the delivery (and records it in the completion history, when kept).
|
|
165
|
+
* With `session` the deletion commits with the caller's transaction; without,
|
|
166
|
+
* it runs in a transaction of its own. Returns false when the lease was lost.
|
|
167
|
+
*/
|
|
70
168
|
complete(lease: LeaseReference, now: Date, session?: ClientSession): Promise<boolean>;
|
|
169
|
+
/**
|
|
170
|
+
* Completes many leases with a fixed number of round trips, whatever lanes
|
|
171
|
+
* they belong to: three commands without a completion history, one
|
|
172
|
+
* transaction with it (see `MongoCompletion.#deleteFenced`).
|
|
173
|
+
* Returns one flag per lease in input order; a lease listed twice completes
|
|
174
|
+
* once, and a token this store cannot have issued is refused.
|
|
175
|
+
*/
|
|
176
|
+
completeMany(leases: readonly LeaseReference[], now: Date): Promise<boolean[]>;
|
|
177
|
+
/** Returns a running delivery to pending, due at `availableAt`, and counts the attempt that ended. */
|
|
71
178
|
reschedule(lease: LeaseReference, availableAt: Date, error: ErrorInfo, now: Date): Promise<boolean>;
|
|
179
|
+
/** Gives a running delivery back without counting the attempt: pending, due `now`. */
|
|
72
180
|
release(lease: LeaseReference, now: Date): Promise<boolean>;
|
|
181
|
+
/** Moves a running delivery to dead and counts the attempt that ended. */
|
|
73
182
|
bury(lease: LeaseReference, error: ErrorInfo, now: Date): Promise<boolean>;
|
|
183
|
+
/**
|
|
184
|
+
* Frees every lane `leaseOwner` holds that runs no delivery, so other workers
|
|
185
|
+
* need not wait for the lease to expire. Lanes with running deliveries stay leased.
|
|
186
|
+
*/
|
|
187
|
+
relinquish(leaseOwner: string): Promise<void>;
|
|
188
|
+
/**
|
|
189
|
+
* Lists deliveries in creation order. A delivery is `processing` while its
|
|
190
|
+
* document exists as `pending` and its lane lists it; its attempt count then
|
|
191
|
+
* includes the running attempt, and owner and expiry are those of the lane
|
|
192
|
+
* lease. Completion history records (when kept) are listed as `completed`.
|
|
193
|
+
*/
|
|
74
194
|
listDeliveries(query: DeliveryQuery): Promise<DeliveryRecord[]>;
|
|
195
|
+
/** Moves dead deliveries back to pending with a fresh attempt budget. */
|
|
75
196
|
requeue(deliveryIds: readonly string[], now: Date): Promise<number>;
|
|
197
|
+
/**
|
|
198
|
+
* Deletes, in batches of `purgeBatchSize`, dead deliveries last updated before
|
|
199
|
+
* `deadBefore`, and completion history records (and `completed` documents left
|
|
200
|
+
* by 0.1.0) completed before `completedBefore`, each batch in one transaction
|
|
201
|
+
* together with the events it left without any reference. Finally, events
|
|
202
|
+
* nothing references are deleted: one with a completed delivery once its last
|
|
203
|
+
* completion is before `completedBefore` (never by `deadBefore` alone), one
|
|
204
|
+
* that never had a completion (no subscribers, or only dead letters) once it
|
|
205
|
+
* was created before the earliest given cutoff. The batch step applies the
|
|
206
|
+
* same rule to events whose last completion is recorded.
|
|
207
|
+
*/
|
|
76
208
|
purge(request: PurgeRequest): Promise<PurgeResult>;
|
|
209
|
+
/**
|
|
210
|
+
* Counts by derived status. `pending` excludes running deliveries; `completed`
|
|
211
|
+
* counts history records and 0.1.0 `completed` documents. `oldestDueAt` is the
|
|
212
|
+
* oldest instant at which a delivery became claimable: the due time of a
|
|
213
|
+
* pending delivery nobody runs, or the lease expiry of a lane that still runs
|
|
214
|
+
* deliveries.
|
|
215
|
+
*/
|
|
77
216
|
statistics(now: Date): Promise<EventStoreStatistics>;
|
|
78
217
|
}
|
|
79
218
|
|