@opinionated-machine/sse-fallback 0.1.1 → 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 +258 -4
- package/dist/binding.d.ts +13 -0
- package/dist/binding.d.ts.map +1 -1
- package/dist/binding.js +22 -0
- package/dist/binding.js.map +1 -1
- package/dist/bindingTypes.d.ts +57 -2
- package/dist/bindingTypes.d.ts.map +1 -1
- package/dist/bindingTypes.js +4 -1
- package/dist/bindingTypes.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/subscription.d.ts +144 -3
- package/dist/subscription.d.ts.map +1 -1
- package/dist/subscription.js +421 -42
- package/dist/subscription.js.map +1 -1
- package/dist/transport.d.ts +5 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +5 -2
- package/dist/transport.js.map +1 -1
- package/package.json +3 -3
package/dist/subscription.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { FallbackBinding, FallbackRequestParams } from './binding.ts';
|
|
|
2
2
|
import type { EventPayloadMap, FallbackEvent, FallbackPolicy } from './bindingTypes.ts';
|
|
3
3
|
import type { PollGate } from './pollGate.ts';
|
|
4
4
|
import type { InvalidVersionInfo, VersionGap } from './reconciler.ts';
|
|
5
|
-
import type { FallbackTransport } from './transport.ts';
|
|
5
|
+
import type { FallbackTransport, TransportRequest } from './transport.ts';
|
|
6
6
|
export type SubscriptionStatus = 'connecting' | 'live' | 'reconnecting' | 'polling' | 'stopped';
|
|
7
7
|
/**
|
|
8
8
|
* Why a subscription reached `'stopped'`.
|
|
@@ -14,7 +14,13 @@ export type SubscriptionStatus = 'connecting' | 'live' | 'reconnecting' | 'polli
|
|
|
14
14
|
* - `'terminal-event'` — a terminal event was delivered. Success.
|
|
15
15
|
* - `'unretryable-status'` — the stream or a poll was refused with a status in
|
|
16
16
|
* `unretryableStatuses` (and `onAuthChallenge`, if any, did not recover).
|
|
17
|
-
* `status` carries which
|
|
17
|
+
* `status` carries the refusing status and `channel` which channel met it.
|
|
18
|
+
* A poll refusal always lands here. A stream refusal lands here under
|
|
19
|
+
* `streamRefusal: 'stop'`, and under the default `'auto'` only for a binding
|
|
20
|
+
* whose snapshot is synthesized: with an endpoint snapshot, `'auto'` (like
|
|
21
|
+
* `'keep-polling'`) gives the stream up and keeps the subscription alive on
|
|
22
|
+
* its poll, reported through `streamAbandoned` and
|
|
23
|
+
* `diagnostics.onStreamRefused` instead.
|
|
18
24
|
* - `'budget-exhausted'` — `subscriptionBudget` ran out. `limit` says which
|
|
19
25
|
* half. Show an actionable error and offer a manual retry.
|
|
20
26
|
* - `'manual'` — the caller called `stop()`, or the `signal` passed at
|
|
@@ -30,6 +36,12 @@ export type SubscriptionStopDetail = {
|
|
|
30
36
|
limit?: 'maxDurationMs' | 'maxPolls';
|
|
31
37
|
/** Which channel hit the refusal, for `'unretryable-status'`. */
|
|
32
38
|
channel?: 'poll' | 'stream';
|
|
39
|
+
/**
|
|
40
|
+
* Whether the stream had ever carried bytes, for a refusal with
|
|
41
|
+
* `channel: 'stream'`. Same signal as `diagnostics.onStreamRefused`, which
|
|
42
|
+
* only fires where the subscription keeps polling instead of stopping.
|
|
43
|
+
*/
|
|
44
|
+
streamWasLive?: boolean;
|
|
33
45
|
};
|
|
34
46
|
/**
|
|
35
47
|
* Rejection thrown by `waitFor` / `waitForTerminal` when the subscription
|
|
@@ -41,8 +53,72 @@ export declare class SubscriptionStoppedError extends Error {
|
|
|
41
53
|
readonly status: number | undefined;
|
|
42
54
|
readonly limit: 'maxDurationMs' | 'maxPolls' | undefined;
|
|
43
55
|
readonly channel: 'poll' | 'stream' | undefined;
|
|
56
|
+
readonly streamWasLive: boolean | undefined;
|
|
44
57
|
constructor(detail: SubscriptionStopDetail);
|
|
45
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* A request answered with a status the channel cannot use. Handed to
|
|
61
|
+
* `onStreamError` / `onPollError`, and as the `cause` of a
|
|
62
|
+
* {@link FallbackDegradedError}.
|
|
63
|
+
*/
|
|
64
|
+
export declare class FallbackHttpError extends Error {
|
|
65
|
+
readonly channel: 'poll' | 'stream';
|
|
66
|
+
readonly status: number;
|
|
67
|
+
readonly request: TransportRequest;
|
|
68
|
+
constructor(message: string, detail: {
|
|
69
|
+
channel: 'poll' | 'stream';
|
|
70
|
+
status: number;
|
|
71
|
+
request: TransportRequest;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* What broke the stream, as far as a client can tell.
|
|
76
|
+
*
|
|
77
|
+
* - `'stream-refused'`: a status in `unretryableStatuses`; the stream is given up for good.
|
|
78
|
+
* A refusal that `onAuthChallenge` recovers is not a failure and has no kind.
|
|
79
|
+
* - `'stream-rejected'`: any other non-200 status, or a 200 that is not `text/event-stream`
|
|
80
|
+
* (a proxy error page, an SPA fallback route).
|
|
81
|
+
* - `'stream-silent'`: accepted, then closed or timed out without a single byte. A proxy that
|
|
82
|
+
* buffers the response is the usual cause.
|
|
83
|
+
* - `'stream-unreachable'`: the connect threw or timed out. An offline client produces this too,
|
|
84
|
+
* which is the one kind a reporter may want to rank lower.
|
|
85
|
+
*/
|
|
86
|
+
export type DegradationKind = 'stream-refused' | 'stream-rejected' | 'stream-silent' | 'stream-unreachable';
|
|
87
|
+
/**
|
|
88
|
+
* The stream stopped working for a reason the client can name, and the subscription is running
|
|
89
|
+
* without it: on its poll for an endpoint snapshot, or on nothing at all for a synthesized one.
|
|
90
|
+
*
|
|
91
|
+
* Delivered to `diagnostics.onDegraded` when the subscription degrades, and again every
|
|
92
|
+
* `degradationReportIntervalMs` for as long as it stays degraded, so a tab that lives on the
|
|
93
|
+
* fallback keeps showing up in an error tracker instead of reporting once and going quiet.
|
|
94
|
+
* Hand it to one as it is: the message names the route, the status and the channel left.
|
|
95
|
+
*/
|
|
96
|
+
export declare class FallbackDegradedError extends Error {
|
|
97
|
+
readonly kind: DegradationKind;
|
|
98
|
+
/** The refusing or rejecting status, for `'stream-refused'` and `'stream-rejected'`. */
|
|
99
|
+
readonly status: number | undefined;
|
|
100
|
+
/** The stream request that failed. */
|
|
101
|
+
readonly request: TransportRequest;
|
|
102
|
+
/** Whether any stream of this subscription had carried bytes before it broke. */
|
|
103
|
+
readonly streamWasLive: boolean;
|
|
104
|
+
/** Whether a poll keeps delivering while the stream is down. */
|
|
105
|
+
readonly pollCarriesDelivery: boolean;
|
|
106
|
+
/** How many times this degradation has been reported, starting at 1. */
|
|
107
|
+
readonly reportCount: number;
|
|
108
|
+
/** Time since the subscription degraded, 0 on the first report. */
|
|
109
|
+
readonly degradedForMs: number;
|
|
110
|
+
constructor(detail: {
|
|
111
|
+
kind: DegradationKind;
|
|
112
|
+
status?: number;
|
|
113
|
+
contentType?: string;
|
|
114
|
+
request: TransportRequest;
|
|
115
|
+
streamWasLive: boolean;
|
|
116
|
+
pollCarriesDelivery: boolean;
|
|
117
|
+
reportCount: number;
|
|
118
|
+
degradedForMs: number;
|
|
119
|
+
cause?: unknown;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
46
122
|
/**
|
|
47
123
|
* Observability hooks — all optional, all no-ops by default. None of these
|
|
48
124
|
* affect delivery semantics; they exist so applications can meter the
|
|
@@ -51,9 +127,46 @@ export declare class SubscriptionStoppedError extends Error {
|
|
|
51
127
|
export type FallbackDiagnostics = {
|
|
52
128
|
onGap?: (gap: VersionGap) => void;
|
|
53
129
|
onDuplicate?: (event: string) => void;
|
|
130
|
+
/**
|
|
131
|
+
* A snapshot was dropped because the stream had already delivered newer
|
|
132
|
+
* news: below the watermark, or, for `version: 'none'`, requested before a
|
|
133
|
+
* pushed event it would have overwritten.
|
|
134
|
+
*/
|
|
54
135
|
onStaleSnapshot?: () => void;
|
|
55
136
|
onPollError?: (error: unknown) => void;
|
|
56
137
|
onStreamError?: (error: unknown) => void;
|
|
138
|
+
/**
|
|
139
|
+
* The stream broke for a reason a client can name and the subscription is
|
|
140
|
+
* running without it. Fires on degrading, and again on the
|
|
141
|
+
* `degradationReportIntervalMs` cadence until it recovers.
|
|
142
|
+
*
|
|
143
|
+
* This is the hook to send to an error tracker. A fallback that works is
|
|
144
|
+
* exactly what hides a broken main path: delivery carries on, late, and
|
|
145
|
+
* nothing else says why. Not fired for `mode: 'poll-only'`, which never
|
|
146
|
+
* had a stream to lose.
|
|
147
|
+
*/
|
|
148
|
+
onDegraded?: (error: FallbackDegradedError) => void;
|
|
149
|
+
/** A degradation reported through `onDegraded` ended: the stream carried bytes again. */
|
|
150
|
+
onRecovered?: (recovery: {
|
|
151
|
+
kind: DegradationKind;
|
|
152
|
+
degradedForMs: number;
|
|
153
|
+
}) => void;
|
|
154
|
+
/**
|
|
155
|
+
* The stream was refused with a status it cannot retry past, and the
|
|
156
|
+
* subscription carried on polling instead of stopping: `streamRefusal:
|
|
157
|
+
* 'keep-polling'`, or the default `'auto'` on a binding with
|
|
158
|
+
* `snapshotSource: 'endpoint'`. Delivery keeps working, late: nothing else
|
|
159
|
+
* reports that the push channel is gone.
|
|
160
|
+
*
|
|
161
|
+
* `streamWasLive` says whether this subscription had ever received bytes
|
|
162
|
+
* over the stream. That separates a route nobody could reach (a deploy that
|
|
163
|
+
* moved the path) from one withdrawn mid-session (a permission change),
|
|
164
|
+
* which are different faults with different owners.
|
|
165
|
+
*/
|
|
166
|
+
onStreamRefused?: (refusal: {
|
|
167
|
+
status: number;
|
|
168
|
+
streamWasLive: boolean;
|
|
169
|
+
}) => void;
|
|
57
170
|
/**
|
|
58
171
|
* A gap suspended the state layer: `getState()` is frozen at its pre-gap
|
|
59
172
|
* value until a snapshot repairs it, even though events keep flowing.
|
|
@@ -94,6 +207,9 @@ export type CreateResilientSubscriptionOptions = {
|
|
|
94
207
|
* throw, to stop the subscription with `'unretryable-status'`. The retry is
|
|
95
208
|
* granted once per auth failure streak: a second refusal with no successful
|
|
96
209
|
* request in between stops the subscription.
|
|
210
|
+
*
|
|
211
|
+
* A refusal the hook recovers is not a stream failure: the retry runs at
|
|
212
|
+
* once, with no backoff, and does not count toward `degradedAfterFailures`.
|
|
97
213
|
*/
|
|
98
214
|
onAuthChallenge?: (challenge: {
|
|
99
215
|
status: number;
|
|
@@ -119,11 +235,31 @@ export type ResilientSubscription<Events extends EventPayloadMap = EventPayloadM
|
|
|
119
235
|
getState(): State | undefined;
|
|
120
236
|
onStateChange(listener: (state: State) => void): () => void;
|
|
121
237
|
readonly status: SubscriptionStatus;
|
|
238
|
+
/**
|
|
239
|
+
* Whether the stream has been given up for the life of the subscription: a
|
|
240
|
+
* refusal met `streamRefusal: 'keep-polling'` (or `'auto'` with an endpoint
|
|
241
|
+
* snapshot), so nothing will reconnect.
|
|
242
|
+
* `'polling'` alone does not say that, since it is equally where a
|
|
243
|
+
* subscription sits while it degrades and keeps probing SSE. A badge that
|
|
244
|
+
* tells "slower for now" from "push is gone until you resubscribe" reads
|
|
245
|
+
* this alongside {@link status}.
|
|
246
|
+
*/
|
|
247
|
+
readonly streamAbandoned: boolean;
|
|
122
248
|
/**
|
|
123
249
|
* Observe status transitions. `detail` is present exactly when `status` is
|
|
124
250
|
* `'stopped'`, and says why — see {@link StopReason}.
|
|
125
251
|
*/
|
|
126
252
|
onStatusChange(listener: (status: SubscriptionStatus, detail?: SubscriptionStopDetail) => void): () => void;
|
|
253
|
+
/**
|
|
254
|
+
* Run a listener each time a stream connection carries its first byte.
|
|
255
|
+
*
|
|
256
|
+
* With a synthesized snapshot an accepted connect reports `'live'` before
|
|
257
|
+
* any byte, since quiet is normal there. That makes `'live'` the wrong
|
|
258
|
+
* trigger for work that must not repeat on every retry: an upstream that
|
|
259
|
+
* accepts and closes at once cycles `'reconnecting'` and `'live'` on each
|
|
260
|
+
* attempt. This fires only for a connection that delivered something.
|
|
261
|
+
*/
|
|
262
|
+
onStreamEstablished(listener: () => void): () => void;
|
|
127
263
|
/**
|
|
128
264
|
* Why the subscription stopped, or `undefined` while it is still running.
|
|
129
265
|
* Also delivered to `onStop` and `onStatusChange` at the moment it stops.
|
|
@@ -135,7 +271,12 @@ export type ResilientSubscription<Events extends EventPayloadMap = EventPayloadM
|
|
|
135
271
|
* between subscribing and a terminal event that arrived first.
|
|
136
272
|
*/
|
|
137
273
|
onStop(listener: (detail: SubscriptionStopDetail) => void): () => void;
|
|
138
|
-
/**
|
|
274
|
+
/**
|
|
275
|
+
* Force a repair now: a reconciliation poll, or, for a binding whose
|
|
276
|
+
* snapshot is synthesized, a reconnect that skips whatever is left of the
|
|
277
|
+
* reconnect backoff. A stream that is connecting or open is left to the
|
|
278
|
+
* stale-connection watchdog either way: quiet is not evidence of a fault.
|
|
279
|
+
*/
|
|
139
280
|
nudge(): void;
|
|
140
281
|
/** Stop the subscription: cancel timers, abort in-flight requests. */
|
|
141
282
|
stop(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../src/subscription.ts"],"names":[],"mappings":"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"}
|