@fedify/fedify 2.4.0-dev.1488 → 2.4.0-dev.1504
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 +3 -4
- package/dist/{assert-OguE97r2.mjs → assert-DvVHoIZ0.mjs} +1 -1
- package/dist/{assert_instance_of-DBC5X09g.mjs → assert_instance_of-CxoC8bVq.mjs} +1 -1
- package/dist/{assert_not_equals-DkVK8oqV.mjs → assert_not_equals-C8vcTTA3.mjs} +1 -1
- package/dist/{assert_rejects-DN60FHPX.mjs → assert_rejects-DAdaaIWM.mjs} +2 -2
- package/dist/{assert_strict_equals-XEgZAlrj.mjs → assert_strict_equals-BzqyKuYL.mjs} +1 -1
- package/dist/{assert_throws-BOkhLGYc.mjs → assert_throws-zN79lgIC.mjs} +1 -1
- package/dist/{builder-Dcr6y6XD.mjs → builder-Ck0Fl_a5.mjs} +23 -3
- package/dist/codec-CmlPqjNX.mjs +103 -0
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +3 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-DVoTs_wM.mjs → context-BBRTgkrs.mjs} +8 -2
- package/dist/{context-BU6jSQdo.d.ts → context-BF5B4ZDk.d.ts} +529 -259
- package/dist/{context-BBVLF7lx.d.cts → context-CYF8X0ft.d.cts} +530 -259
- package/dist/{deno-BCFGf8NR.mjs → deno-D3gb4X9v.mjs} +1 -1
- package/dist/{docloader-DWEwaGqF.mjs → docloader-DUKu0GzG.mjs} +3 -3
- package/dist/federation/builder.test.mjs +5 -5
- package/dist/federation/circuit-breaker.test.mjs +5 -5
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +13 -13
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +4 -4
- package/dist/federation/middleware.test.mjs +200 -19
- package/dist/federation/mod.cjs +3 -259
- package/dist/federation/mod.d.cts +4 -4
- package/dist/federation/mod.d.ts +4 -4
- package/dist/federation/mod.js +1 -257
- package/dist/federation/mq.test.mjs +103 -261
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +5 -5
- package/dist/federation/send.test.mjs +10 -10
- package/dist/federation/tasks/codec.test.d.mts +2 -0
- package/dist/federation/tasks/codec.test.mjs +292 -0
- package/dist/federation/tasks/enqueue.test.d.mts +2 -0
- package/dist/federation/tasks/enqueue.test.mjs +992 -0
- package/dist/federation/tasks/tasks.test.d.mts +2 -0
- package/dist/federation/tasks/tasks.test.mjs +555 -0
- package/dist/federation/temporal.test.mjs +4 -4
- package/dist/federation/webfinger.test.mjs +6 -6
- package/dist/{http-RriziGDE.mjs → http-BNFQkiEZ.mjs} +4 -4
- package/dist/{http-DaVoLyyA.js → http-CrZzUAtV.js} +7 -17
- package/dist/{http-DLqxhQg1.cjs → http-D9p2_d2X.cjs} +7 -17
- package/dist/{key-Bkg8Zg36.mjs → key-BM_SRwBV.mjs} +8 -18
- package/dist/{kv-cache-BR--9V4L.mjs → kv-cache-BE1QIPdL.mjs} +1 -1
- package/dist/{kv-cache-DxlFLMiU.js → kv-cache-Ch_Zv5Yq.js} +1 -1
- package/dist/{kv-cache-Fw-iwKjy.cjs → kv-cache-Cna211RR.cjs} +1 -1
- package/dist/{ld-BjsmbqO7.mjs → ld-ubkf03eb.mjs} +3 -3
- package/dist/{metrics-BLoa2pab.mjs → metrics-BXR36qzu.mjs} +1 -1
- package/dist/{middleware-V-r1QH5Z.cjs → middleware-DUNeIkXN.cjs} +694 -51
- package/dist/{middleware-D3kuDjvb.mjs → middleware-iP9VRMus.mjs} +310 -67
- package/dist/{middleware-_9t5HVBi.js → middleware-lB4vtShP.js} +683 -52
- package/dist/{middleware-DNR3YBCi.mjs → middleware-pzCP79He.mjs} +1 -1
- package/dist/{mod-vPYVoa5n.d.ts → mod-4WGAuR6X.d.ts} +1 -1
- package/dist/{mod-C0F6kvgS.d.cts → mod-BHEB3xhE.d.cts} +1 -1
- package/dist/mod.cjs +6 -6
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +5 -5
- package/dist/mq-03vS-C9P.mjs +276 -0
- package/dist/{mq-D8uSFzxe.d.cts → mq-B5_hohs7.d.ts} +34 -0
- package/dist/{mq-D-nlpY04.d.ts → mq-DXMt_qCY.d.cts} +34 -0
- package/dist/nodeinfo/client.test.mjs +3 -3
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/{outgoing-jsonld-L_DbOaFe.mjs → outgoing-jsonld-BNL8AC14.mjs} +1 -1
- package/dist/{owner-NK2p1ihR.mjs → owner-Bf1KkncT.mjs} +2 -2
- package/dist/{proof-D7WVwQzs.js → proof-BMcsi8q_.js} +1 -1
- package/dist/{proof-CRXqo703.mjs → proof-Q781Ks5q.mjs} +5 -5
- package/dist/{proof-2WI6mMbC.cjs → proof-yeAU1MyT.cjs} +1 -1
- package/dist/{send-CTaPzl8L.mjs → send-DFV0S_n9.mjs} +3 -3
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +8 -8
- package/dist/sig/key.test.mjs +6 -56
- package/dist/sig/ld.test.mjs +7 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +8 -8
- package/dist/{std__assert-BBjXFNOb.mjs → std__assert-Dh6uLf_q.mjs} +4 -4
- package/dist/{temporal-C8M0Y7v9.mjs → temporal-CyOjsqPj.mjs} +1 -1
- package/dist/testing/mod.d.mts +1037 -8
- package/dist/testing/mod.mjs +3 -2
- package/dist/testing-Dy-WhqpN.mjs +77 -0
- package/dist/utils/docloader.test.mjs +6 -6
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +13 -8
- /package/dist/{accept-CPkZzmGN.mjs → accept-CgDcxvjV.mjs} +0 -0
- /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-BeTGV3wc.mjs} +0 -0
- /package/dist/{assert_equals-C-ZRDbaf.mjs → assert_equals-PBVKNMJd.mjs} +0 -0
- /package/dist/{circuit-breaker-CSWsyoef.mjs → circuit-breaker-hJBB6jwA.mjs} +0 -0
- /package/dist/{client-ByXmQhYD.mjs → client-B_A6mfn3.mjs} +0 -0
- /package/dist/{collection-Cc3DVAhE.mjs → collection-Dp5ky45w.mjs} +0 -0
- /package/dist/{keycache-BeU0LCII.mjs → keycache-CaOR6NYg.mjs} +0 -0
- /package/dist/{keys-DGu1NFwu.mjs → keys-CSYsOMFG.mjs} +0 -0
- /package/dist/{kv-rV3vodCc.mjs → kv-CIvR3Non.mjs} +0 -0
- /package/dist/{negotiation-DDstyBvc.mjs → negotiation-m_L2nyS3.mjs} +0 -0
- /package/dist/{public-audience-Cvbr2Gzt.mjs → public-audience-c9zmYKgA.mjs} +0 -0
- /package/dist/{retry-CXg_MBI-.mjs → retry-DI4O-zYl.mjs} +0 -0
- /package/dist/{types-J53Kw7so.mjs → types-BFowWFTT.mjs} +0 -0
|
@@ -3,13 +3,14 @@ import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client
|
|
|
3
3
|
import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-lf8Hsd91.js";
|
|
4
4
|
import { n as GetKeyOwnerOptions } from "./owner-CnngXDNJ.js";
|
|
5
5
|
import { n as KvStore, t as KvKey } from "./kv-D6hNiMTK.js";
|
|
6
|
-
import { r as MessageQueue } from "./mq-
|
|
6
|
+
import { r as MessageQueue } from "./mq-B5_hohs7.js";
|
|
7
7
|
import { Router } from "@fedify/uri-template";
|
|
8
8
|
import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
|
|
9
9
|
import { MeterProvider, Span, Tracer, TracerProvider } from "@opentelemetry/api";
|
|
10
10
|
import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions } from "@fedify/vocab-runtime";
|
|
11
11
|
import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger";
|
|
12
12
|
import { MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
13
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
13
14
|
|
|
14
15
|
//#region src/compat/types.d.ts
|
|
15
16
|
/**
|
|
@@ -18,177 +19,6 @@ import { MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/s
|
|
|
18
19
|
*/
|
|
19
20
|
type ActivityTransformer<TContextData> = (activity: Activity, context: Context<TContextData>) => Activity;
|
|
20
21
|
//#endregion
|
|
21
|
-
//#region src/federation/circuit-breaker.d.ts
|
|
22
|
-
/**
|
|
23
|
-
* The state of a remote host circuit breaker.
|
|
24
|
-
* @since 2.3.0
|
|
25
|
-
*/
|
|
26
|
-
type CircuitBreakerState = "closed" | "open" | "half-open";
|
|
27
|
-
/**
|
|
28
|
-
* The JSON-serializable state stored in the configured {@link KvStore}.
|
|
29
|
-
* @since 2.3.0
|
|
30
|
-
*/
|
|
31
|
-
interface CircuitBreakerKvState {
|
|
32
|
-
readonly state: CircuitBreakerState;
|
|
33
|
-
readonly failures: readonly string[];
|
|
34
|
-
readonly opened?: string;
|
|
35
|
-
readonly halfOpened?: string;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Details passed to {@link CircuitBreakerOptions.onActivityDrop} when a held
|
|
39
|
-
* activity expires before the remote host recovers.
|
|
40
|
-
* @since 2.3.0
|
|
41
|
-
*/
|
|
42
|
-
interface CircuitBreakerActivityDrop {
|
|
43
|
-
/** The inbox URL that would have received the activity. */
|
|
44
|
-
readonly inbox: URL;
|
|
45
|
-
/** The activity that was dropped. */
|
|
46
|
-
readonly activity: Activity;
|
|
47
|
-
/** The activity ID, when known. */
|
|
48
|
-
readonly activityId?: string;
|
|
49
|
-
/** The activity type. */
|
|
50
|
-
readonly activityType: string;
|
|
51
|
-
/** The actor IDs represented by this inbox. */
|
|
52
|
-
readonly actorIds: readonly URL[];
|
|
53
|
-
/** The time when Fedify first held this activity. */
|
|
54
|
-
readonly heldSince: Temporal.Instant;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Configures how a remote host circuit opens after repeated delivery
|
|
58
|
-
* failures.
|
|
59
|
-
* @since 2.3.0
|
|
60
|
-
*/
|
|
61
|
-
type CircuitBreakerFailurePolicy = {
|
|
62
|
-
failure(timestamps: readonly Temporal.Instant[]): boolean;
|
|
63
|
-
readonly failureThreshold?: never;
|
|
64
|
-
readonly failureWindow?: never;
|
|
65
|
-
} | {
|
|
66
|
-
readonly failure?: never;
|
|
67
|
-
readonly failureThreshold?: number;
|
|
68
|
-
readonly failureWindow?: Temporal.Duration | Temporal.DurationLike;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Options for Fedify's outbound activity circuit breaker.
|
|
72
|
-
* @since 2.3.0
|
|
73
|
-
*/
|
|
74
|
-
type CircuitBreakerOptions = CircuitBreakerFailurePolicy & {
|
|
75
|
-
/**
|
|
76
|
-
* How long an open circuit waits before allowing a half-open recovery probe.
|
|
77
|
-
* @default `{ minutes: 30 }`
|
|
78
|
-
*/
|
|
79
|
-
readonly recoveryDelay?: Temporal.Duration | Temporal.DurationLike;
|
|
80
|
-
/**
|
|
81
|
-
* How long Fedify keeps requeueing activities held by an open circuit before
|
|
82
|
-
* dropping them.
|
|
83
|
-
* @default `{ days: 7 }`
|
|
84
|
-
*/
|
|
85
|
-
readonly heldActivityTtl?: Temporal.Duration | Temporal.DurationLike;
|
|
86
|
-
/**
|
|
87
|
-
* How often other held activities retry while a half-open probe is in
|
|
88
|
-
* flight. The probe is treated as stale after the recovery delay.
|
|
89
|
-
* @default `{ seconds: 1 }`
|
|
90
|
-
*/
|
|
91
|
-
readonly releaseInterval?: Temporal.Duration | Temporal.DurationLike;
|
|
92
|
-
/**
|
|
93
|
-
* Called whenever the circuit state changes.
|
|
94
|
-
*/
|
|
95
|
-
readonly onStateChange?: (remoteHost: string, previousState: CircuitBreakerState, newState: CircuitBreakerState) => void | Promise<void>;
|
|
96
|
-
/**
|
|
97
|
-
* Called when an activity held by the circuit breaker expires.
|
|
98
|
-
*/
|
|
99
|
-
readonly onActivityDrop?: (remoteHost: string, details: CircuitBreakerActivityDrop) => void | Promise<void>;
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* Normalized circuit breaker options used internally by Fedify.
|
|
103
|
-
* @internal
|
|
104
|
-
*/
|
|
105
|
-
interface NormalizedCircuitBreakerOptions {
|
|
106
|
-
readonly failure: (timestamps: readonly Temporal.Instant[]) => boolean;
|
|
107
|
-
readonly pruneFailures: (timestamps: readonly Temporal.Instant[], now: Temporal.Instant) => readonly Temporal.Instant[];
|
|
108
|
-
readonly recoveryDelay: Temporal.Duration;
|
|
109
|
-
readonly heldActivityTtl: Temporal.Duration;
|
|
110
|
-
readonly releaseInterval: Temporal.Duration;
|
|
111
|
-
readonly onStateChange?: CircuitBreakerOptions["onStateChange"];
|
|
112
|
-
readonly onActivityDrop?: CircuitBreakerOptions["onActivityDrop"];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Constructor options for {@link CircuitBreaker}.
|
|
116
|
-
* @internal
|
|
117
|
-
*/
|
|
118
|
-
interface CircuitBreakerCreateOptions {
|
|
119
|
-
readonly kv: KvStore;
|
|
120
|
-
readonly prefix: KvKey;
|
|
121
|
-
readonly options?: CircuitBreakerOptions;
|
|
122
|
-
readonly now?: () => Temporal.Instant;
|
|
123
|
-
/**
|
|
124
|
-
* Observes state changes after user callbacks have run.
|
|
125
|
-
* @internal
|
|
126
|
-
*/
|
|
127
|
-
readonly stateChangeObserver?: (remoteHost: string, previousState: CircuitBreakerState, newState: CircuitBreakerState) => void | Promise<void>;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* The delivery decision returned by {@link CircuitBreaker.beforeSend}.
|
|
131
|
-
* @internal
|
|
132
|
-
*/
|
|
133
|
-
type CircuitBreakerBeforeSendDecision = {
|
|
134
|
-
readonly type: "send";
|
|
135
|
-
readonly probe: boolean;
|
|
136
|
-
readonly stateChange?: CircuitBreakerStateChange;
|
|
137
|
-
} | {
|
|
138
|
-
readonly type: "hold";
|
|
139
|
-
readonly state: "open" | "half-open";
|
|
140
|
-
readonly delay: Temporal.Duration;
|
|
141
|
-
readonly heldSince: Temporal.Instant;
|
|
142
|
-
} | {
|
|
143
|
-
readonly type: "drop";
|
|
144
|
-
readonly heldSince: Temporal.Instant;
|
|
145
|
-
};
|
|
146
|
-
/**
|
|
147
|
-
* A circuit breaker state transition.
|
|
148
|
-
* @since 2.3.0
|
|
149
|
-
*/
|
|
150
|
-
interface CircuitBreakerStateChange {
|
|
151
|
-
readonly previousState: CircuitBreakerState;
|
|
152
|
-
readonly newState: CircuitBreakerState;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Tracks reachability state for remote outbox delivery hosts.
|
|
156
|
-
* @since 2.3.0
|
|
157
|
-
*/
|
|
158
|
-
declare class CircuitBreaker {
|
|
159
|
-
#private;
|
|
160
|
-
constructor(options: CircuitBreakerCreateOptions);
|
|
161
|
-
get options(): NormalizedCircuitBreakerOptions;
|
|
162
|
-
capHeldDelay(heldSince: Temporal.Instant, delay: Temporal.Duration): Temporal.Duration;
|
|
163
|
-
beforeSend(remoteHost: string, message: {
|
|
164
|
-
readonly circuitHeldSince?: string;
|
|
165
|
-
}): Promise<CircuitBreakerBeforeSendDecision>;
|
|
166
|
-
recordSuccess(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
167
|
-
recordReachableFailure(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
168
|
-
recordFailure(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
169
|
-
dropActivity(remoteHost: string, details: CircuitBreakerActivityDrop): Promise<void>;
|
|
170
|
-
getState(remoteHost: string): Promise<CircuitBreakerKvState | undefined>;
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Normalizes user-provided circuit breaker options into the internal policy
|
|
174
|
-
* shape used while processing queued outbox deliveries.
|
|
175
|
-
*
|
|
176
|
-
* @param options The public circuit breaker options supplied to Fedify.
|
|
177
|
-
* @returns The normalized failure predicate, failure pruning function,
|
|
178
|
-
* duration values, and optional callbacks with defaults applied.
|
|
179
|
-
* @throws {RangeError} If any configured duration is not positive.
|
|
180
|
-
* @throws {TypeError} If `failureThreshold` is not a positive integer.
|
|
181
|
-
*/
|
|
182
|
-
declare function normalizeCircuitBreakerOptions(options: CircuitBreakerOptions): NormalizedCircuitBreakerOptions;
|
|
183
|
-
/**
|
|
184
|
-
* Parses a value loaded from the circuit breaker KV store.
|
|
185
|
-
*
|
|
186
|
-
* @param value The raw KV value to validate.
|
|
187
|
-
* @returns A circuit breaker state when `value` has a recognized state and
|
|
188
|
-
* valid instant strings, or `undefined` when the stored value is malformed.
|
|
189
|
-
*/
|
|
190
|
-
declare function parseCircuitBreakerKvState(value: unknown): CircuitBreakerKvState | undefined;
|
|
191
|
-
//#endregion
|
|
192
22
|
//#region src/federation/collection.d.ts
|
|
193
23
|
/**
|
|
194
24
|
* A page of items.
|
|
@@ -555,28 +385,199 @@ type ObjectAuthorizePredicate<TContextData, TParam extends string> = (context: R
|
|
|
555
385
|
*/
|
|
556
386
|
type CustomCollectionDispatcher<TItem, TParam extends string, TContext extends Context<TContextData>, TContextData> = (context: TContext, values: Record<TParam, string>, cursor: string | null) => PageItems<TItem> | null | Promise<PageItems<TItem> | null>;
|
|
557
387
|
/**
|
|
558
|
-
* A callback that counts the number of items in a custom collection.
|
|
388
|
+
* A callback that counts the number of items in a custom collection.
|
|
389
|
+
*
|
|
390
|
+
* @template TParams The parameter names of the requested URL.
|
|
391
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
392
|
+
* @param context The context.
|
|
393
|
+
* @param values The parameters of the requested URL.
|
|
394
|
+
* @since 1.8.0
|
|
395
|
+
*/
|
|
396
|
+
type CustomCollectionCounter<TParam extends string, TContextData> = (context: RequestContext<TContextData>, values: Record<TParam, string>) => number | bigint | null | Promise<number | bigint | null>;
|
|
397
|
+
/**
|
|
398
|
+
* A callback that returns a cursor for a custom collection.
|
|
399
|
+
*
|
|
400
|
+
* @template TParams The parameter names of the requested URL.
|
|
401
|
+
* @template TContext The type of the context. {@link Context} or
|
|
402
|
+
* {@link RequestContext}.
|
|
403
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
404
|
+
* @template TFilter The type of the filter, if any.
|
|
405
|
+
* @param context The context.
|
|
406
|
+
* @param values The parameters of the requested URL.
|
|
407
|
+
* @since 1.8.0
|
|
408
|
+
*/
|
|
409
|
+
type CustomCollectionCursor<TParam extends string, TContext extends Context<TContextData>, TContextData> = (context: TContext, values: Record<TParam, string>) => string | null | Promise<string | null>;
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/federation/circuit-breaker.d.ts
|
|
412
|
+
/**
|
|
413
|
+
* The state of a remote host circuit breaker.
|
|
414
|
+
* @since 2.3.0
|
|
415
|
+
*/
|
|
416
|
+
type CircuitBreakerState = "closed" | "open" | "half-open";
|
|
417
|
+
/**
|
|
418
|
+
* The JSON-serializable state stored in the configured {@link KvStore}.
|
|
419
|
+
* @since 2.3.0
|
|
420
|
+
*/
|
|
421
|
+
interface CircuitBreakerKvState {
|
|
422
|
+
readonly state: CircuitBreakerState;
|
|
423
|
+
readonly failures: readonly string[];
|
|
424
|
+
readonly opened?: string;
|
|
425
|
+
readonly halfOpened?: string;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Details passed to {@link CircuitBreakerOptions.onActivityDrop} when a held
|
|
429
|
+
* activity expires before the remote host recovers.
|
|
430
|
+
* @since 2.3.0
|
|
431
|
+
*/
|
|
432
|
+
interface CircuitBreakerActivityDrop {
|
|
433
|
+
/** The inbox URL that would have received the activity. */
|
|
434
|
+
readonly inbox: URL;
|
|
435
|
+
/** The activity that was dropped. */
|
|
436
|
+
readonly activity: Activity;
|
|
437
|
+
/** The activity ID, when known. */
|
|
438
|
+
readonly activityId?: string;
|
|
439
|
+
/** The activity type. */
|
|
440
|
+
readonly activityType: string;
|
|
441
|
+
/** The actor IDs represented by this inbox. */
|
|
442
|
+
readonly actorIds: readonly URL[];
|
|
443
|
+
/** The time when Fedify first held this activity. */
|
|
444
|
+
readonly heldSince: Temporal.Instant;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Configures how a remote host circuit opens after repeated delivery
|
|
448
|
+
* failures.
|
|
449
|
+
* @since 2.3.0
|
|
450
|
+
*/
|
|
451
|
+
type CircuitBreakerFailurePolicy = {
|
|
452
|
+
failure(timestamps: readonly Temporal.Instant[]): boolean;
|
|
453
|
+
readonly failureThreshold?: never;
|
|
454
|
+
readonly failureWindow?: never;
|
|
455
|
+
} | {
|
|
456
|
+
readonly failure?: never;
|
|
457
|
+
readonly failureThreshold?: number;
|
|
458
|
+
readonly failureWindow?: Temporal.Duration | Temporal.DurationLike;
|
|
459
|
+
};
|
|
460
|
+
/**
|
|
461
|
+
* Options for Fedify's outbound activity circuit breaker.
|
|
462
|
+
* @since 2.3.0
|
|
463
|
+
*/
|
|
464
|
+
type CircuitBreakerOptions = CircuitBreakerFailurePolicy & {
|
|
465
|
+
/**
|
|
466
|
+
* How long an open circuit waits before allowing a half-open recovery probe.
|
|
467
|
+
* @default `{ minutes: 30 }`
|
|
468
|
+
*/
|
|
469
|
+
readonly recoveryDelay?: Temporal.Duration | Temporal.DurationLike;
|
|
470
|
+
/**
|
|
471
|
+
* How long Fedify keeps requeueing activities held by an open circuit before
|
|
472
|
+
* dropping them.
|
|
473
|
+
* @default `{ days: 7 }`
|
|
474
|
+
*/
|
|
475
|
+
readonly heldActivityTtl?: Temporal.Duration | Temporal.DurationLike;
|
|
476
|
+
/**
|
|
477
|
+
* How often other held activities retry while a half-open probe is in
|
|
478
|
+
* flight. The probe is treated as stale after the recovery delay.
|
|
479
|
+
* @default `{ seconds: 1 }`
|
|
480
|
+
*/
|
|
481
|
+
readonly releaseInterval?: Temporal.Duration | Temporal.DurationLike;
|
|
482
|
+
/**
|
|
483
|
+
* Called whenever the circuit state changes.
|
|
484
|
+
*/
|
|
485
|
+
readonly onStateChange?: (remoteHost: string, previousState: CircuitBreakerState, newState: CircuitBreakerState) => void | Promise<void>;
|
|
486
|
+
/**
|
|
487
|
+
* Called when an activity held by the circuit breaker expires.
|
|
488
|
+
*/
|
|
489
|
+
readonly onActivityDrop?: (remoteHost: string, details: CircuitBreakerActivityDrop) => void | Promise<void>;
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Normalized circuit breaker options used internally by Fedify.
|
|
493
|
+
* @internal
|
|
494
|
+
*/
|
|
495
|
+
interface NormalizedCircuitBreakerOptions {
|
|
496
|
+
readonly failure: (timestamps: readonly Temporal.Instant[]) => boolean;
|
|
497
|
+
readonly pruneFailures: (timestamps: readonly Temporal.Instant[], now: Temporal.Instant) => readonly Temporal.Instant[];
|
|
498
|
+
readonly recoveryDelay: Temporal.Duration;
|
|
499
|
+
readonly heldActivityTtl: Temporal.Duration;
|
|
500
|
+
readonly releaseInterval: Temporal.Duration;
|
|
501
|
+
readonly onStateChange?: CircuitBreakerOptions["onStateChange"];
|
|
502
|
+
readonly onActivityDrop?: CircuitBreakerOptions["onActivityDrop"];
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Constructor options for {@link CircuitBreaker}.
|
|
506
|
+
* @internal
|
|
507
|
+
*/
|
|
508
|
+
interface CircuitBreakerCreateOptions {
|
|
509
|
+
readonly kv: KvStore;
|
|
510
|
+
readonly prefix: KvKey;
|
|
511
|
+
readonly options?: CircuitBreakerOptions;
|
|
512
|
+
readonly now?: () => Temporal.Instant;
|
|
513
|
+
/**
|
|
514
|
+
* Observes state changes after user callbacks have run.
|
|
515
|
+
* @internal
|
|
516
|
+
*/
|
|
517
|
+
readonly stateChangeObserver?: (remoteHost: string, previousState: CircuitBreakerState, newState: CircuitBreakerState) => void | Promise<void>;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* The delivery decision returned by {@link CircuitBreaker.beforeSend}.
|
|
521
|
+
* @internal
|
|
522
|
+
*/
|
|
523
|
+
type CircuitBreakerBeforeSendDecision = {
|
|
524
|
+
readonly type: "send";
|
|
525
|
+
readonly probe: boolean;
|
|
526
|
+
readonly stateChange?: CircuitBreakerStateChange;
|
|
527
|
+
} | {
|
|
528
|
+
readonly type: "hold";
|
|
529
|
+
readonly state: "open" | "half-open";
|
|
530
|
+
readonly delay: Temporal.Duration;
|
|
531
|
+
readonly heldSince: Temporal.Instant;
|
|
532
|
+
} | {
|
|
533
|
+
readonly type: "drop";
|
|
534
|
+
readonly heldSince: Temporal.Instant;
|
|
535
|
+
};
|
|
536
|
+
/**
|
|
537
|
+
* A circuit breaker state transition.
|
|
538
|
+
* @since 2.3.0
|
|
539
|
+
*/
|
|
540
|
+
interface CircuitBreakerStateChange {
|
|
541
|
+
readonly previousState: CircuitBreakerState;
|
|
542
|
+
readonly newState: CircuitBreakerState;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Tracks reachability state for remote outbox delivery hosts.
|
|
546
|
+
* @since 2.3.0
|
|
547
|
+
*/
|
|
548
|
+
declare class CircuitBreaker {
|
|
549
|
+
#private;
|
|
550
|
+
constructor(options: CircuitBreakerCreateOptions);
|
|
551
|
+
get options(): NormalizedCircuitBreakerOptions;
|
|
552
|
+
capHeldDelay(heldSince: Temporal.Instant, delay: Temporal.Duration): Temporal.Duration;
|
|
553
|
+
beforeSend(remoteHost: string, message: {
|
|
554
|
+
readonly circuitHeldSince?: string;
|
|
555
|
+
}): Promise<CircuitBreakerBeforeSendDecision>;
|
|
556
|
+
recordSuccess(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
557
|
+
recordReachableFailure(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
558
|
+
recordFailure(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
|
|
559
|
+
dropActivity(remoteHost: string, details: CircuitBreakerActivityDrop): Promise<void>;
|
|
560
|
+
getState(remoteHost: string): Promise<CircuitBreakerKvState | undefined>;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Normalizes user-provided circuit breaker options into the internal policy
|
|
564
|
+
* shape used while processing queued outbox deliveries.
|
|
559
565
|
*
|
|
560
|
-
* @
|
|
561
|
-
* @
|
|
562
|
-
*
|
|
563
|
-
* @
|
|
564
|
-
* @
|
|
566
|
+
* @param options The public circuit breaker options supplied to Fedify.
|
|
567
|
+
* @returns The normalized failure predicate, failure pruning function,
|
|
568
|
+
* duration values, and optional callbacks with defaults applied.
|
|
569
|
+
* @throws {RangeError} If any configured duration is not positive.
|
|
570
|
+
* @throws {TypeError} If `failureThreshold` is not a positive integer.
|
|
565
571
|
*/
|
|
566
|
-
|
|
572
|
+
declare function normalizeCircuitBreakerOptions(options: CircuitBreakerOptions): NormalizedCircuitBreakerOptions;
|
|
567
573
|
/**
|
|
568
|
-
*
|
|
574
|
+
* Parses a value loaded from the circuit breaker KV store.
|
|
569
575
|
*
|
|
570
|
-
* @
|
|
571
|
-
* @
|
|
572
|
-
*
|
|
573
|
-
* @template TContextData The context data to pass to the {@link Context}.
|
|
574
|
-
* @template TFilter The type of the filter, if any.
|
|
575
|
-
* @param context The context.
|
|
576
|
-
* @param values The parameters of the requested URL.
|
|
577
|
-
* @since 1.8.0
|
|
576
|
+
* @param value The raw KV value to validate.
|
|
577
|
+
* @returns A circuit breaker state when `value` has a recognized state and
|
|
578
|
+
* valid instant strings, or `undefined` when the stored value is malformed.
|
|
578
579
|
*/
|
|
579
|
-
|
|
580
|
+
declare function parseCircuitBreakerKvState(value: unknown): CircuitBreakerKvState | undefined;
|
|
580
581
|
//#endregion
|
|
581
582
|
//#region src/federation/handler.d.ts
|
|
582
583
|
/**
|
|
@@ -610,6 +611,220 @@ declare function respondWithObject(object: Object$1, options?: RespondWithObject
|
|
|
610
611
|
*/
|
|
611
612
|
declare function respondWithObjectIfAcceptable(object: Object$1, request: Request, options?: RespondWithObjectOptions): Promise<Response | null>;
|
|
612
613
|
//#endregion
|
|
614
|
+
//#region src/federation/retry.d.ts
|
|
615
|
+
/**
|
|
616
|
+
* The context passed to a {@link RetryPolicy} callback.
|
|
617
|
+
* @since 0.12.0
|
|
618
|
+
*/
|
|
619
|
+
interface RetryContext {
|
|
620
|
+
/**
|
|
621
|
+
* The elapsed time since the first attempt.
|
|
622
|
+
*/
|
|
623
|
+
readonly elapsedTime: Temporal.Duration;
|
|
624
|
+
/**
|
|
625
|
+
* The number of attempts so far.
|
|
626
|
+
*/
|
|
627
|
+
readonly attempts: number;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* A policy that determines the delay before the next retry.
|
|
631
|
+
* @param context The retry context.
|
|
632
|
+
* @returns The delay before the next retry, or `null` to stop retrying.
|
|
633
|
+
* It must not negative.
|
|
634
|
+
* @since 0.12.0
|
|
635
|
+
*/
|
|
636
|
+
type RetryPolicy = (context: RetryContext) => Temporal.Duration | null;
|
|
637
|
+
/**
|
|
638
|
+
* Options for {@link createExponentialBackoffPolicy} function.
|
|
639
|
+
* @since 0.12.0
|
|
640
|
+
*/
|
|
641
|
+
interface CreateExponentialBackoffPolicyOptions {
|
|
642
|
+
/**
|
|
643
|
+
* The initial delay before the first retry. Defaults to 1 second.
|
|
644
|
+
*/
|
|
645
|
+
readonly initialDelay?: Temporal.DurationLike;
|
|
646
|
+
/**
|
|
647
|
+
* The maximum delay between retries. Defaults to 12 hours.
|
|
648
|
+
*/
|
|
649
|
+
readonly maxDelay?: Temporal.DurationLike;
|
|
650
|
+
/**
|
|
651
|
+
* The maximum number of attempts before giving up.
|
|
652
|
+
* Defaults to 10.
|
|
653
|
+
*/
|
|
654
|
+
readonly maxAttempts?: number;
|
|
655
|
+
/**
|
|
656
|
+
* The factor to multiply the previous delay by for each retry.
|
|
657
|
+
* Defaults to 2.
|
|
658
|
+
*/
|
|
659
|
+
readonly factor?: number;
|
|
660
|
+
/**
|
|
661
|
+
* Whether to add jitter to the delay to avoid synchronization.
|
|
662
|
+
* Turned on by default.
|
|
663
|
+
*/
|
|
664
|
+
readonly jitter?: boolean;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Creates an exponential backoff retry policy. The delay between retries
|
|
668
|
+
* starts at the `initialDelay` and is multiplied by the `factor` for each
|
|
669
|
+
* subsequent retry, up to the `maxDelay`. The policy will give up after
|
|
670
|
+
* `maxAttempts` attempts. The actual delay is randomized to avoid
|
|
671
|
+
* synchronization (jitter).
|
|
672
|
+
* @param options The options for the policy.
|
|
673
|
+
* @returns The retry policy.
|
|
674
|
+
* @since 0.12.0
|
|
675
|
+
*/
|
|
676
|
+
declare function createExponentialBackoffPolicy(options?: CreateExponentialBackoffPolicyOptions): RetryPolicy;
|
|
677
|
+
//#endregion
|
|
678
|
+
//#region src/federation/tasks/task.d.ts
|
|
679
|
+
/**
|
|
680
|
+
* A callback that processes a custom background task.
|
|
681
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
682
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
683
|
+
* schema.
|
|
684
|
+
* @param ctx The context for the worker processing the task.
|
|
685
|
+
* @param data The decoded and validated task payload.
|
|
686
|
+
* @since 2.4.0
|
|
687
|
+
*/
|
|
688
|
+
type TaskHandler<TContextData, TData> = (ctx: Context<TContextData>, data: TData) => Promise<void> | void;
|
|
689
|
+
/**
|
|
690
|
+
* Options for {@link TaskRegistry.defineTask}.
|
|
691
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
692
|
+
* @template TSchema The [Standard Schema](https://standardschema.dev/) that
|
|
693
|
+
* validates the task payload.
|
|
694
|
+
* @since 2.4.0
|
|
695
|
+
*/
|
|
696
|
+
interface TaskDefinitionOptions<TContextData, TSchema extends StandardSchemaV1> {
|
|
697
|
+
/**
|
|
698
|
+
* The [Standard Schema](https://standardschema.dev/) that validates the
|
|
699
|
+
* task payload. The payload type is inferred from this schema.
|
|
700
|
+
*
|
|
701
|
+
* The payload is validated twice: once at enqueue time (fail fast) and
|
|
702
|
+
* once at dequeue time (drift protection against payloads enqueued by an
|
|
703
|
+
* older deployment). Because the same schema runs on both sides, its
|
|
704
|
+
* validation must be idempotent: the validated output must itself be
|
|
705
|
+
* a valid input. Transforming schemas (e.g., Zod's `.transform()`) whose
|
|
706
|
+
* output differs in shape from their input are not supported.
|
|
707
|
+
*/
|
|
708
|
+
readonly schema: TSchema;
|
|
709
|
+
/**
|
|
710
|
+
* The callback that processes the task on a background worker.
|
|
711
|
+
*/
|
|
712
|
+
readonly handler: TaskHandler<TContextData, StandardSchemaV1.InferOutput<TSchema>>;
|
|
713
|
+
/**
|
|
714
|
+
* The retry policy for this task. If omitted, the federation-wide
|
|
715
|
+
* task retry policy is used, which defaults to an exponential backoff
|
|
716
|
+
* policy.
|
|
717
|
+
*/
|
|
718
|
+
readonly retryPolicy?: RetryPolicy;
|
|
719
|
+
/**
|
|
720
|
+
* A callback invoked when the {@link handler} throws an error, before
|
|
721
|
+
* a retry is scheduled.
|
|
722
|
+
* @param ctx The context for the worker processing the task.
|
|
723
|
+
* @param error The error thrown by the handler.
|
|
724
|
+
* @param data The decoded and validated task payload.
|
|
725
|
+
*/
|
|
726
|
+
readonly onError?: (ctx: Context<TContextData>, error: unknown, data: StandardSchemaV1.InferOutput<TSchema>) => Promise<void> | void;
|
|
727
|
+
/**
|
|
728
|
+
* The message queue dedicated to this task. If omitted, the task is
|
|
729
|
+
* routed to the federation-wide task queue, falling back to the outbox
|
|
730
|
+
* queue (unless `taskQueueResolution: "strict"` is configured).
|
|
731
|
+
*/
|
|
732
|
+
readonly queue?: MessageQueue;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Phantom key binding a {@link TaskDefinition} to its federation's context
|
|
736
|
+
* data type. Declared only—no value exists at runtime, and the symbol is
|
|
737
|
+
* not exported, so the marker stays out of user-facing completions.
|
|
738
|
+
*/
|
|
739
|
+
declare const contextDataBrand: unique symbol;
|
|
740
|
+
/**
|
|
741
|
+
* The handle returned by {@link TaskRegistry.defineTask}. It carries the
|
|
742
|
+
* task name and schema so that {@link Context.enqueueTask} can validate the
|
|
743
|
+
* payload and infer its type at every call site.
|
|
744
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
745
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
746
|
+
* schema.
|
|
747
|
+
* @since 2.4.0
|
|
748
|
+
*/
|
|
749
|
+
interface TaskDefinition<TContextData, TData> {
|
|
750
|
+
/**
|
|
751
|
+
* The unique name of the task.
|
|
752
|
+
*/
|
|
753
|
+
readonly name: string;
|
|
754
|
+
/**
|
|
755
|
+
* The [Standard Schema](https://standardschema.dev/) that validates the
|
|
756
|
+
* task payload.
|
|
757
|
+
*/
|
|
758
|
+
readonly schema: StandardSchemaV1<unknown, TData>;
|
|
759
|
+
/**
|
|
760
|
+
* @internal Phantom marker binding the handle to its federation.
|
|
761
|
+
*/
|
|
762
|
+
readonly [contextDataBrand]?: TContextData;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Registration of custom background tasks. Both {@link Federation} and
|
|
766
|
+
* {@link FederationBuilder} implement this interface.
|
|
767
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
768
|
+
* @since 2.4.0
|
|
769
|
+
*/
|
|
770
|
+
interface TaskRegistry<TContextData> {
|
|
771
|
+
/**
|
|
772
|
+
* Defines a custom background task. The returned handle is passed to
|
|
773
|
+
* {@link Context.enqueueTask} to enqueue the task.
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ``` typescript
|
|
777
|
+
* const sendDigest = federation.defineTask("sendDigest", {
|
|
778
|
+
* schema: digestSchema,
|
|
779
|
+
* handler: async (ctx, data) => {
|
|
780
|
+
* // …process the payload on a background worker…
|
|
781
|
+
* },
|
|
782
|
+
* });
|
|
783
|
+
* ```
|
|
784
|
+
*
|
|
785
|
+
* @param name The unique name of the task.
|
|
786
|
+
* @param options The task definition options. The payload type is
|
|
787
|
+
* inferred from `options.schema`.
|
|
788
|
+
* @returns The handle to pass to {@link Context.enqueueTask}.
|
|
789
|
+
* @throws {TypeError} If a task with the same name is already defined.
|
|
790
|
+
*/
|
|
791
|
+
defineTask<TSchema extends StandardSchemaV1>(name: string, options: TaskDefinitionOptions<TContextData, TSchema>): TaskDefinition<TContextData, StandardSchemaV1.InferOutput<TSchema>>;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Options for {@link Context.enqueueTask} and {@link Context.enqueueTaskMany}.
|
|
795
|
+
* @since 2.4.0
|
|
796
|
+
*/
|
|
797
|
+
interface TaskEnqueueOptions {
|
|
798
|
+
/**
|
|
799
|
+
* The delay before the task is processed. No delay by default.
|
|
800
|
+
*/
|
|
801
|
+
readonly delay?: Temporal.DurationLike;
|
|
802
|
+
/**
|
|
803
|
+
* An optional key that ensures tasks with the same ordering key are
|
|
804
|
+
* processed sequentially (one at a time).
|
|
805
|
+
*/
|
|
806
|
+
readonly orderingKey?: string;
|
|
807
|
+
/**
|
|
808
|
+
* An optional key requesting at-most-once enqueue for tasks that share it.
|
|
809
|
+
*
|
|
810
|
+
* A queue with {@link MessageQueue.nativeDeduplication} `true` enforces it
|
|
811
|
+
* strictly; otherwise deduplication is best-effort via {@link KvStore.cas},
|
|
812
|
+
* and {@link FederationOptions.taskDeduplicationFallback} decides whether a
|
|
813
|
+
* missing `cas` proceeds without deduplication or throws.
|
|
814
|
+
*
|
|
815
|
+
* For {@link Context.enqueueTaskMany}, one key governs the whole batch. When
|
|
816
|
+
* deduplication is actually applied—a native queue, or the key–value
|
|
817
|
+
* fallback through {@link KvStore.cas}—a multi-item batch with a
|
|
818
|
+
* `deduplicationKey` requires the queue to implement
|
|
819
|
+
* {@link MessageQueue.enqueueMany} so it enqueues atomically, or the call
|
|
820
|
+
* throws a `TypeError`. Under the `"open"` fallback with no `cas`, no marker
|
|
821
|
+
* is taken, so such a batch instead fans out without deduplication.
|
|
822
|
+
*
|
|
823
|
+
* @since 2.4.0
|
|
824
|
+
*/
|
|
825
|
+
readonly deduplicationKey?: string;
|
|
826
|
+
}
|
|
827
|
+
//#endregion
|
|
613
828
|
//#region src/federation/builder.d.ts
|
|
614
829
|
/**
|
|
615
830
|
* Creates a new {@link FederationBuilder} instance.
|
|
@@ -632,7 +847,7 @@ interface SenderKeyJwkPair {
|
|
|
632
847
|
* type.
|
|
633
848
|
* @since 1.6.0
|
|
634
849
|
*/
|
|
635
|
-
type Message = FanoutMessage | OutboxMessage | InboxMessage;
|
|
850
|
+
type Message = FanoutMessage | OutboxMessage | InboxMessage | TaskMessage;
|
|
636
851
|
interface FanoutMessage {
|
|
637
852
|
readonly type: "fanout";
|
|
638
853
|
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
@@ -686,6 +901,24 @@ interface OutboxMessage {
|
|
|
686
901
|
readonly circuitHeldSince?: string;
|
|
687
902
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
688
903
|
}
|
|
904
|
+
/**
|
|
905
|
+
* A message that carries a custom background task. Every field is
|
|
906
|
+
* a string, number, or plain record so that the message survives both
|
|
907
|
+
* JSON serialization and structured clone on every queue backend.
|
|
908
|
+
* @since 2.4.0
|
|
909
|
+
*/
|
|
910
|
+
interface TaskMessage {
|
|
911
|
+
readonly type: "task";
|
|
912
|
+
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
913
|
+
readonly baseUrl: string;
|
|
914
|
+
readonly taskName: string;
|
|
915
|
+
/** devalue-encoded task data; vocab objects bridged to expanded JSON-LD. */
|
|
916
|
+
readonly data: string;
|
|
917
|
+
readonly started: string;
|
|
918
|
+
readonly attempt: number;
|
|
919
|
+
readonly orderingKey?: string;
|
|
920
|
+
readonly traceContext: Readonly<Record<string, string>>;
|
|
921
|
+
}
|
|
689
922
|
interface InboxMessage {
|
|
690
923
|
readonly type: "inbox";
|
|
691
924
|
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
@@ -733,70 +966,6 @@ interface InboxMessage {
|
|
|
733
966
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
734
967
|
}
|
|
735
968
|
//#endregion
|
|
736
|
-
//#region src/federation/retry.d.ts
|
|
737
|
-
/**
|
|
738
|
-
* The context passed to a {@link RetryPolicy} callback.
|
|
739
|
-
* @since 0.12.0
|
|
740
|
-
*/
|
|
741
|
-
interface RetryContext {
|
|
742
|
-
/**
|
|
743
|
-
* The elapsed time since the first attempt.
|
|
744
|
-
*/
|
|
745
|
-
readonly elapsedTime: Temporal.Duration;
|
|
746
|
-
/**
|
|
747
|
-
* The number of attempts so far.
|
|
748
|
-
*/
|
|
749
|
-
readonly attempts: number;
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
* A policy that determines the delay before the next retry.
|
|
753
|
-
* @param context The retry context.
|
|
754
|
-
* @returns The delay before the next retry, or `null` to stop retrying.
|
|
755
|
-
* It must not negative.
|
|
756
|
-
* @since 0.12.0
|
|
757
|
-
*/
|
|
758
|
-
type RetryPolicy = (context: RetryContext) => Temporal.Duration | null;
|
|
759
|
-
/**
|
|
760
|
-
* Options for {@link createExponentialBackoffPolicy} function.
|
|
761
|
-
* @since 0.12.0
|
|
762
|
-
*/
|
|
763
|
-
interface CreateExponentialBackoffPolicyOptions {
|
|
764
|
-
/**
|
|
765
|
-
* The initial delay before the first retry. Defaults to 1 second.
|
|
766
|
-
*/
|
|
767
|
-
readonly initialDelay?: Temporal.DurationLike;
|
|
768
|
-
/**
|
|
769
|
-
* The maximum delay between retries. Defaults to 12 hours.
|
|
770
|
-
*/
|
|
771
|
-
readonly maxDelay?: Temporal.DurationLike;
|
|
772
|
-
/**
|
|
773
|
-
* The maximum number of attempts before giving up.
|
|
774
|
-
* Defaults to 10.
|
|
775
|
-
*/
|
|
776
|
-
readonly maxAttempts?: number;
|
|
777
|
-
/**
|
|
778
|
-
* The factor to multiply the previous delay by for each retry.
|
|
779
|
-
* Defaults to 2.
|
|
780
|
-
*/
|
|
781
|
-
readonly factor?: number;
|
|
782
|
-
/**
|
|
783
|
-
* Whether to add jitter to the delay to avoid synchronization.
|
|
784
|
-
* Turned on by default.
|
|
785
|
-
*/
|
|
786
|
-
readonly jitter?: boolean;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Creates an exponential backoff retry policy. The delay between retries
|
|
790
|
-
* starts at the `initialDelay` and is multiplied by the `factor` for each
|
|
791
|
-
* subsequent retry, up to the `maxDelay`. The policy will give up after
|
|
792
|
-
* `maxAttempts` attempts. The actual delay is randomized to avoid
|
|
793
|
-
* synchronization (jitter).
|
|
794
|
-
* @param options The options for the policy.
|
|
795
|
-
* @returns The retry policy.
|
|
796
|
-
* @since 0.12.0
|
|
797
|
-
*/
|
|
798
|
-
declare function createExponentialBackoffPolicy(options?: CreateExponentialBackoffPolicyOptions): RetryPolicy;
|
|
799
|
-
//#endregion
|
|
800
969
|
//#region src/federation/middleware.d.ts
|
|
801
970
|
/**
|
|
802
971
|
* Configures the task queues for sending and receiving activities.
|
|
@@ -820,6 +989,13 @@ interface FederationQueueOptions {
|
|
|
820
989
|
* {@link Context.sendActivity} calls.
|
|
821
990
|
*/
|
|
822
991
|
readonly fanout?: MessageQueue;
|
|
992
|
+
/**
|
|
993
|
+
* The message queue for custom background tasks. If not provided,
|
|
994
|
+
* tasks are routed to the outbox queue (unless
|
|
995
|
+
* {@link FederationOptions.taskQueueResolution} is `"strict"`).
|
|
996
|
+
* @since 2.4.0
|
|
997
|
+
*/
|
|
998
|
+
readonly task?: MessageQueue;
|
|
823
999
|
}
|
|
824
1000
|
/**
|
|
825
1001
|
* Prefixes for namespacing keys in the Deno KV store.
|
|
@@ -863,6 +1039,14 @@ interface FederationKvPrefixes {
|
|
|
863
1039
|
* @since 2.3.0
|
|
864
1040
|
*/
|
|
865
1041
|
readonly circuitBreaker: KvKey;
|
|
1042
|
+
/**
|
|
1043
|
+
* The key prefix used for storing custom background task deduplication
|
|
1044
|
+
* markers. Kept separate from {@link activityIdempotence} so the two key
|
|
1045
|
+
* spaces never collide.
|
|
1046
|
+
* @default `["_fedify", "taskDeduplication"]`
|
|
1047
|
+
* @since 2.4.0
|
|
1048
|
+
*/
|
|
1049
|
+
readonly taskDeduplication: KvKey;
|
|
866
1050
|
}
|
|
867
1051
|
/**
|
|
868
1052
|
* Options for {@link FederationOptions.origin} when it is not a string.
|
|
@@ -904,18 +1088,18 @@ interface FederationStartQueueOptions {
|
|
|
904
1088
|
signal?: AbortSignal;
|
|
905
1089
|
/**
|
|
906
1090
|
* Starts the task worker only for the specified queue. If unspecified,
|
|
907
|
-
* which is the default, the task worker starts for all
|
|
908
|
-
* inbox, outbox, and
|
|
1091
|
+
* which is the default, the task worker starts for all four queues:
|
|
1092
|
+
* inbox, outbox, fanout, and task.
|
|
909
1093
|
* @since 1.3.0
|
|
910
1094
|
*/
|
|
911
|
-
queue?: "inbox" | "outbox" | "fanout";
|
|
1095
|
+
queue?: "inbox" | "outbox" | "fanout" | "task";
|
|
912
1096
|
}
|
|
913
1097
|
/**
|
|
914
1098
|
* A common interface between {@link Federation} and {@link FederationBuilder}.
|
|
915
1099
|
* @template TContextData The context data to pass to the {@link Context}.
|
|
916
1100
|
* @since 1.6.0
|
|
917
1101
|
*/
|
|
918
|
-
interface Federatable<TContextData> {
|
|
1102
|
+
interface Federatable<TContextData> extends TaskRegistry<TContextData> {
|
|
919
1103
|
/**
|
|
920
1104
|
* Registers a NodeInfo dispatcher.
|
|
921
1105
|
* @param path The URI path pattern for the NodeInfo dispatcher. The syntax
|
|
@@ -1622,6 +1806,50 @@ interface FederationOptions<TContextData> {
|
|
|
1622
1806
|
*/
|
|
1623
1807
|
inboxRetryPolicy?: RetryPolicy;
|
|
1624
1808
|
/**
|
|
1809
|
+
* The retry policy for processing custom background tasks. By default,
|
|
1810
|
+
* this uses an exponential backoff strategy with a maximum of 10 attempts
|
|
1811
|
+
* and a maximum delay of 12 hours. A per-task retry policy
|
|
1812
|
+
* ({@link TaskDefinitionOptions.retryPolicy}) overrides this.
|
|
1813
|
+
* @since 2.4.0
|
|
1814
|
+
*/
|
|
1815
|
+
taskRetryPolicy?: RetryPolicy;
|
|
1816
|
+
/**
|
|
1817
|
+
* How a queue is resolved for a custom background task when neither
|
|
1818
|
+
* a per-task queue ({@link TaskDefinitionOptions.queue}) nor a dedicated
|
|
1819
|
+
* task queue ({@link FederationQueueOptions.task}) is configured.
|
|
1820
|
+
*
|
|
1821
|
+
* - `"fallback"` (the default): the task is routed to the outbox queue.
|
|
1822
|
+
* - `"strict"`: no fallback; enqueuing the task throws instead of
|
|
1823
|
+
* silently sharing the outbox queue.
|
|
1824
|
+
* @default `"fallback"`
|
|
1825
|
+
* @since 2.4.0
|
|
1826
|
+
*/
|
|
1827
|
+
taskQueueResolution?: "fallback" | "strict";
|
|
1828
|
+
/**
|
|
1829
|
+
* The time-to-live for a {@link TaskEnqueueOptions.deduplicationKey} marker
|
|
1830
|
+
* stored in the key–value deduplication fallback. A second enqueue with the
|
|
1831
|
+
* same key within this window is skipped; once it expires, the key may
|
|
1832
|
+
* enqueue again. Ignored when the task's queue declares
|
|
1833
|
+
* {@link MessageQueue.nativeDeduplication} (the backend owns the window).
|
|
1834
|
+
* @default `{ hours: 1 }`
|
|
1835
|
+
* @since 2.4.0
|
|
1836
|
+
*/
|
|
1837
|
+
taskDeduplicationTtl?: Temporal.DurationLike;
|
|
1838
|
+
/**
|
|
1839
|
+
* The behavior when a {@link TaskEnqueueOptions.deduplicationKey} is supplied
|
|
1840
|
+
* but the task's queue does not declare
|
|
1841
|
+
* {@link MessageQueue.nativeDeduplication} *and* the configured
|
|
1842
|
+
* {@link KvStore} exposes no `cas` (compare-and-swap) primitive:
|
|
1843
|
+
*
|
|
1844
|
+
* - `"open"` (the default): proceeds without deduplication after logging at
|
|
1845
|
+
* debug level.
|
|
1846
|
+
* - `"closed"`: rejects with a `TypeError` before enqueuing.
|
|
1847
|
+
*
|
|
1848
|
+
* @default `"open"`
|
|
1849
|
+
* @since 2.4.0
|
|
1850
|
+
*/
|
|
1851
|
+
taskDeduplicationFallback?: "open" | "closed";
|
|
1852
|
+
/**
|
|
1625
1853
|
* Activity transformers that are applied to outgoing activities. It is
|
|
1626
1854
|
* useful for adjusting outgoing activities to satisfy some ActivityPub
|
|
1627
1855
|
* implementations.
|
|
@@ -2374,6 +2602,48 @@ interface Context<TContextData> {
|
|
|
2374
2602
|
*/
|
|
2375
2603
|
routeActivity(recipient: string | null, activity: Activity, options?: RouteActivityOptions): Promise<boolean>;
|
|
2376
2604
|
/**
|
|
2605
|
+
* Enqueues a custom background task. The payload is validated against
|
|
2606
|
+
* the task's schema, serialized, and processed by the task's handler on
|
|
2607
|
+
* a background worker.
|
|
2608
|
+
*
|
|
2609
|
+
* @example
|
|
2610
|
+
* ``` typescript
|
|
2611
|
+
* await ctx.enqueueTask(sendDigest, { userId: "alice" });
|
|
2612
|
+
* ```
|
|
2613
|
+
*
|
|
2614
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
2615
|
+
* schema.
|
|
2616
|
+
* @param task The handle returned by {@link TaskRegistry.defineTask}.
|
|
2617
|
+
* @param data The task payload. It is validated against the task's
|
|
2618
|
+
* schema before being enqueued.
|
|
2619
|
+
* @param options Options for enqueuing the task.
|
|
2620
|
+
* @throws {TypeError} If the task is not defined on this federation,
|
|
2621
|
+
* if no message queue is configured for tasks, or if
|
|
2622
|
+
* the payload fails schema validation.
|
|
2623
|
+
* @since 2.4.0
|
|
2624
|
+
*/
|
|
2625
|
+
enqueueTask<TData>(task: TaskDefinition<TContextData, TData>, data: TData, options?: TaskEnqueueOptions): Promise<void>;
|
|
2626
|
+
/**
|
|
2627
|
+
* Enqueues multiple payloads for a custom background task at once.
|
|
2628
|
+
* Uses the queue's bulk enqueue operation when available. Without
|
|
2629
|
+
* deduplication, it may fall back to parallel single enqueues when the
|
|
2630
|
+
* queue does not implement bulk enqueue.
|
|
2631
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
2632
|
+
* schema.
|
|
2633
|
+
* @param task The handle returned by {@link TaskRegistry.defineTask}.
|
|
2634
|
+
* @param payloads The task payloads. Each is validated against the
|
|
2635
|
+
* task's schema before being enqueued.
|
|
2636
|
+
* @param options Options for enqueuing the tasks.
|
|
2637
|
+
* @throws {TypeError} If the task is not defined on this federation,
|
|
2638
|
+
* if no message queue is configured for tasks, if
|
|
2639
|
+
* a payload fails schema validation, or if a
|
|
2640
|
+
* deduplicated multi-item batch cannot be enqueued
|
|
2641
|
+
* atomically because the queue does not implement
|
|
2642
|
+
* bulk enqueue.
|
|
2643
|
+
* @since 2.4.0
|
|
2644
|
+
*/
|
|
2645
|
+
enqueueTaskMany<TData>(task: TaskDefinition<TContextData, TData>, payloads: readonly TData[], options?: TaskEnqueueOptions): Promise<void>;
|
|
2646
|
+
/**
|
|
2377
2647
|
* Builds the URI of a collection of objects with the given name and values.
|
|
2378
2648
|
* @param name The name of the collection, which can be a string or a symbol.
|
|
2379
2649
|
* @param values The values of the URI parameters.
|
|
@@ -2884,4 +3154,4 @@ interface ActorKeyPair extends CryptoKeyPair {
|
|
|
2884
3154
|
readonly multikey: Multikey;
|
|
2885
3155
|
}
|
|
2886
3156
|
//#endregion
|
|
2887
|
-
export {
|
|
3157
|
+
export { CircuitBreakerFailurePolicy as $, Rfc6570Expression as A, WebFingerLinksDispatcher as At, TaskHandler as B, FederationStartQueueOptions as C, OutboxErrorHandler as Ct, InboxListenerSetters as D, SharedInboxKeyDispatcher as Dt, InboxChallengePolicy as E, OutboxPermanentFailureHandler as Et, Message as F, digest as Ft, createExponentialBackoffPolicy as G, CreateExponentialBackoffPolicyOptions as H, createFederationBuilder as I, ActivityTransformer as It, respondWithObjectIfAcceptable as J, RespondWithObjectOptions as K, TaskDefinition as L, FederationOrigin as M, SenderKeyPair as Mt, FederationQueueOptions as N, PageItems as Nt, ObjectCallbackSetters as O, UnverifiedActivityHandler as Ot, createFederation as P, buildCollectionSynchronizationHeader as Pt, CircuitBreakerCreateOptions as Q, TaskDefinitionOptions as R, FederationOptions as S, ObjectDispatcher as St, IdempotencyStrategy as T, OutboxListenerErrorHandler as Tt, RetryContext as U, TaskRegistry as V, RetryPolicy as W, CircuitBreakerActivityDrop as X, CircuitBreaker as Y, CircuitBreakerBeforeSendDecision as Z, Federatable as _, CustomCollectionDispatcher as _t, GetSignedKeyOptions as a, normalizeCircuitBreakerOptions as at, FederationBuilder as b, NodeInfoDispatcher as bt, ParseUriResult as c, ActorDispatcher as ct, SendActivityOptions as d, AuthorizePredicate as dt, CircuitBreakerKvState as et, SendActivityOptionsForCollection as f, CollectionCounter as ft, CustomCollectionCallbackSetters as g, CustomCollectionCursor as gt, ConstructorWithTypeId as h, CustomCollectionCounter as ht, GetActorOptions as i, NormalizedCircuitBreakerOptions as it, FederationKvPrefixes as j, SendActivityError as jt, OutboxListenerSetters as k, UnverifiedActivityReason as kt, RequestContext as l, ActorHandleMapper as lt, CollectionCallbackSetters as m, CollectionDispatcher as mt, Context as n, CircuitBreakerState as nt, InboxContext as o, parseCircuitBreakerKvState as ot, ActorCallbackSetters as p, CollectionCursor as pt, respondWithObject as q, ForwardActivityOptions as r, CircuitBreakerStateChange as rt, OutboxContext as s, ActorAliasMapper as st, ActorKeyPair as t, CircuitBreakerOptions as tt, RouteActivityOptions as u, ActorKeyPairsDispatcher as ut, Federation as v, InboxErrorHandler as vt, IdempotencyKeyCallback as w, OutboxListener as wt, FederationFetchOptions as x, ObjectAuthorizePredicate as xt, FederationBenchmarkOptions as y, InboxListener as yt, TaskEnqueueOptions as z };
|