@fedify/fedify 2.3.0-dev.994 → 2.3.0-pr.809.37
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 +16 -7
- package/dist/{assert-DikXweDx.mjs → assert-OguE97r2.mjs} +1 -1
- package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert_instance_of-DBC5X09g.mjs} +1 -1
- package/dist/{assert_not_equals--wG9hV7u.mjs → assert_not_equals-DkVK8oqV.mjs} +1 -1
- package/dist/{assert_rejects-B-qJtC9Z.mjs → assert_rejects-DN60FHPX.mjs} +28 -3
- package/dist/{assert_strict_equals-Dmjbg-bA.mjs → assert_strict_equals-XEgZAlrj.mjs} +1 -1
- package/dist/{assert_throws-4NwKEy2q.mjs → assert_throws-BOkhLGYc.mjs} +1 -1
- package/dist/{builder-yAlpiIqP.mjs → builder-Dl5Sdmc9.mjs} +96 -42
- package/dist/{chunk-nlSIicah.js → chunk-CRNNMoPX.js} +2 -2
- package/dist/circuit-breaker-CSWsyoef.mjs +337 -0
- package/dist/{client-z-8dc-e1.d.cts → client-CAM_bQXx.d.cts} +1 -0
- package/dist/{client-AtlibPOU.d.ts → client-CSddvgWN.d.ts} +1 -2
- package/dist/compat/mod.d.cts +2 -1
- package/dist/compat/mod.d.ts +2 -3
- package/dist/compat/mod.js +3 -3
- package/dist/compat/outgoing-jsonld.test.mjs +4 -4
- package/dist/compat/public-audience.test.mjs +4 -4
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-BzH2-ajs.d.ts → context-BBVLF7lx.d.cts} +342 -269
- package/dist/{context-DJGagtNd.d.cts → context-BU6jSQdo.d.ts} +344 -266
- package/dist/{context-Dk_tacqz.mjs → context-DVoTs_wM.mjs} +64 -5
- package/dist/{deno-XBVlKnOX.mjs → deno-BID9qTPk.mjs} +1 -1
- package/dist/{docloader-DPp-X6gk.mjs → docloader-BYFuVwwi.mjs} +4 -4
- package/dist/{esm-DVILvP5e.mjs → esm-vrlUxr60.mjs} +4 -7
- package/dist/federation/builder.test.mjs +163 -11
- package/dist/federation/circuit-breaker.test.d.mts +2 -0
- package/dist/federation/circuit-breaker.test.mjs +446 -0
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +1770 -29
- package/dist/federation/idempotency.test.mjs +5 -5
- package/dist/federation/inbox.test.mjs +4 -4
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +2 -2
- package/dist/federation/metrics.test.d.mts +2 -0
- package/dist/federation/metrics.test.mjs +634 -0
- package/dist/federation/middleware.test.mjs +4036 -146
- package/dist/federation/mod.cjs +195 -14
- package/dist/federation/mod.d.cts +6 -4
- package/dist/federation/mod.d.ts +6 -6
- package/dist/federation/mod.js +192 -14
- package/dist/federation/mq.test.mjs +176 -15
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +190 -9
- package/dist/federation/send.test.mjs +153 -15
- package/dist/federation/temporal.test.d.mts +2 -0
- package/dist/federation/temporal.test.mjs +71 -0
- package/dist/federation/webfinger.test.mjs +150 -5
- package/dist/{http-B4rrzxtg.js → http-B47Jg9iX.js} +994 -64
- package/dist/{http-CSlLA54v.mjs → http-CO59u1Yk.mjs} +146 -47
- package/dist/{http-BrGqJDXL.cjs → http-CjZwUPiT.cjs} +1099 -61
- package/dist/{http-aQzN9Ayi.d.ts → http-VyDTd4G3.d.cts} +15 -3
- package/dist/{http-CrGuipxe.d.cts → http-lf8Hsd91.d.ts} +15 -1
- package/dist/{key-Bzx--sHD.mjs → key-Dqdlo3mG.mjs} +43 -18
- package/dist/{kv-CbLNp3zQ.d.cts → kv-D6hNiMTK.d.ts} +1 -0
- package/dist/{kv-cache-DI-Sk7-I.cjs → kv-cache-BQ1-zDKX.cjs} +20 -3
- package/dist/{kv-cache-EMIqoIuB.js → kv-cache-Dh2ZH9Gr.js} +20 -3
- package/dist/{kv-cache-U__xU4qR.mjs → kv-cache-DhLkLv0P.mjs} +21 -3
- package/dist/{kv-GFYnFoOl.d.ts → kv-gJ8LYbxX.d.cts} +1 -3
- package/dist/ld-JbCByP5P.mjs +626 -0
- package/dist/metrics-ColY3QKj.mjs +815 -0
- package/dist/{middleware-zjZ6AFCW.mjs → middleware-Buqzuiaf.mjs} +1 -1
- package/dist/{middleware-An4DjES4.cjs → middleware-CWQ3Yi07.cjs} +2318 -623
- package/dist/{middleware-K1g6bEkV.mjs → middleware-Cg4EyWsq.mjs} +1639 -373
- package/dist/{middleware-nidH7VZH.js → middleware-iAJY2aU-.js} +2260 -556
- package/dist/{mod-CR8soWa9.d.ts → mod-B0hW12_O.d.cts} +26 -4
- package/dist/mod-C0F6kvgS.d.cts +182 -0
- package/dist/{mod-Cr3f-ACa.d.cts → mod-COIAjwRS.d.ts} +26 -2
- package/dist/{mod-CMEbIaNh.d.cts → mod-DFvNJcNb.d.ts} +56 -4
- package/dist/mod-vPYVoa5n.d.ts +182 -0
- package/dist/{mod-CLgIXe9w.d.ts → mod-yvIXFAEi.d.cts} +56 -6
- package/dist/mod.cjs +9 -6
- package/dist/mod.d.cts +12 -10
- package/dist/mod.d.ts +12 -12
- package/dist/mod.js +11 -11
- package/dist/mq-D-nlpY04.d.ts +208 -0
- package/dist/mq-D8uSFzxe.d.cts +208 -0
- package/dist/{negotiation-SQvQgUqe.mjs → negotiation-DDstyBvc.mjs} +29 -0
- package/dist/nodeinfo/client.test.mjs +4 -4
- package/dist/nodeinfo/handler.test.mjs +4 -4
- package/dist/nodeinfo/mod.d.cts +2 -1
- package/dist/nodeinfo/mod.d.ts +2 -3
- package/dist/nodeinfo/mod.js +3 -3
- package/dist/nodeinfo/types.test.mjs +3 -3
- package/dist/otel/exporter.test.mjs +28 -25
- package/dist/otel/mod.cjs +6 -5
- package/dist/otel/mod.d.cts +5 -3
- package/dist/otel/mod.d.ts +5 -5
- package/dist/otel/mod.js +8 -7
- package/dist/{outgoing-jsonld-CNmZLixq.mjs → outgoing-jsonld-L_DbOaFe.mjs} +2 -2
- package/dist/{owner-C-tqfvxn.mjs → owner-B4LgOmzV.mjs} +2 -2
- package/dist/{owner-CptqhsOy.d.cts → owner-CnngXDNJ.d.ts} +2 -1
- package/dist/{owner-74ARJ5TL.d.ts → owner-DEvZuyOE.d.cts} +2 -3
- package/dist/{proof-BlmRPzrK.mjs → proof-BoSGOq9q.mjs} +26 -8
- package/dist/{proof-Bbbwf8_x.js → proof-CzhZuawt.js} +378 -15
- package/dist/{proof-BW89QMVB.cjs → proof-DvMI-3vq.cjs} +432 -15
- package/dist/runtime/mod.d.cts +1 -0
- package/dist/runtime/mod.d.ts +1 -2
- package/dist/runtime/mod.js +3 -3
- package/dist/{send-05pJLcb6.mjs → send-ByK1Q7DK.mjs} +72 -26
- package/dist/sig/http.test.mjs +356 -33
- package/dist/sig/key.test.mjs +103 -6
- package/dist/sig/ld.test.mjs +696 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +4 -3
- package/dist/sig/mod.d.ts +4 -5
- package/dist/sig/mod.js +4 -4
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +169 -8
- package/dist/{std__assert-CRDpx_HF.mjs → std__assert-BBjXFNOb.mjs} +5 -30
- package/dist/temporal-LpjyAjKb.mjs +95 -0
- package/dist/testing/mod.d.mts +110 -10
- package/dist/testing/mod.mjs +1 -2
- package/dist/{transformers-ve6e2xcg.js → transformers-BGMIq1cs.js} +2 -2
- package/dist/{types-hvL8ElAs.js → types-CAY3OdLq.js} +2 -2
- package/dist/utils/docloader.test.mjs +6 -6
- package/dist/utils/kv-cache.test.mjs +67 -2
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +2 -1
- package/dist/utils/mod.d.ts +2 -3
- package/dist/utils/mod.js +3 -3
- package/dist/vocab/cjs.test.mjs +1 -1
- package/dist/vocab/mod.d.cts +1 -0
- package/dist/vocab/mod.d.ts +1 -2
- package/dist/vocab/mod.js +2 -2
- package/package.json +16 -16
- package/dist/ld-DR78beiv.mjs +0 -279
- package/dist/middleware-BFBaR0mF.cjs +0 -4
- package/dist/mod-2d12ffz3.d.ts +0 -64
- package/dist/mod-D35TRn09.d.cts +0 -62
- package/dist/router-CrMLXoOr.mjs +0 -114
- package/dist/{activity-listener-ell7W1s9.mjs → activity-listener-tztVvlNb.mjs} +0 -0
- package/dist/{assert_equals-Ew3jOFa3.mjs → assert_equals-C-ZRDbaf.mjs} +0 -0
- package/dist/{client-D_1QpnWt.mjs → client-ByXmQhYD.mjs} +1 -1
- package/dist/{collection-D-HqUuA2.mjs → collection-Cc3DVAhE.mjs} +0 -0
- package/dist/{keycache-EGATflN-.mjs → keycache-BeU0LCII.mjs} +0 -0
- package/dist/{public-audience-DYFHzm_c.mjs → public-audience-Cvbr2Gzt.mjs} +1 -1
- /package/dist/{retry-bMXBL97A.mjs → retry-CXg_MBI-.mjs} +0 -0
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import { URLPattern } from "urlpattern-polyfill";
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
3
2
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
4
|
-
import { TracerProvider } from "@opentelemetry/api";
|
|
5
3
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
|
+
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
6
5
|
|
|
7
6
|
//#region src/sig/key.d.ts
|
|
8
7
|
/**
|
|
@@ -53,6 +52,13 @@ interface FetchKeyOptions {
|
|
|
53
52
|
* @since 1.3.0
|
|
54
53
|
*/
|
|
55
54
|
tracerProvider?: TracerProvider;
|
|
55
|
+
/**
|
|
56
|
+
* The OpenTelemetry meter provider to use for recording
|
|
57
|
+
* `activitypub.key.lookup` and `activitypub.key.lookup.duration`. If
|
|
58
|
+
* omitted, the global meter provider is used.
|
|
59
|
+
* @since 2.3.0
|
|
60
|
+
*/
|
|
61
|
+
meterProvider?: MeterProvider;
|
|
56
62
|
}
|
|
57
63
|
/**
|
|
58
64
|
* The result of {@link fetchKey}.
|
|
@@ -465,6 +471,12 @@ interface VerifyRequestOptions {
|
|
|
465
471
|
* @since 1.3.0
|
|
466
472
|
*/
|
|
467
473
|
tracerProvider?: TracerProvider;
|
|
474
|
+
/**
|
|
475
|
+
* The OpenTelemetry meter provider. If omitted, the global meter provider
|
|
476
|
+
* is used.
|
|
477
|
+
* @since 2.3.0
|
|
478
|
+
*/
|
|
479
|
+
meterProvider?: MeterProvider;
|
|
468
480
|
}
|
|
469
481
|
/**
|
|
470
482
|
* The reason why {@link verifyRequestDetailed} could not verify a request.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
1
2
|
import { CryptographicKey, Multikey } from "@fedify/vocab";
|
|
3
|
+
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
2
4
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
3
|
-
import { TracerProvider } from "@opentelemetry/api";
|
|
4
5
|
|
|
5
6
|
//#region src/sig/key.d.ts
|
|
6
7
|
/**
|
|
@@ -51,6 +52,13 @@ interface FetchKeyOptions {
|
|
|
51
52
|
* @since 1.3.0
|
|
52
53
|
*/
|
|
53
54
|
tracerProvider?: TracerProvider;
|
|
55
|
+
/**
|
|
56
|
+
* The OpenTelemetry meter provider to use for recording
|
|
57
|
+
* `activitypub.key.lookup` and `activitypub.key.lookup.duration`. If
|
|
58
|
+
* omitted, the global meter provider is used.
|
|
59
|
+
* @since 2.3.0
|
|
60
|
+
*/
|
|
61
|
+
meterProvider?: MeterProvider;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
64
|
* The result of {@link fetchKey}.
|
|
@@ -463,6 +471,12 @@ interface VerifyRequestOptions {
|
|
|
463
471
|
* @since 1.3.0
|
|
464
472
|
*/
|
|
465
473
|
tracerProvider?: TracerProvider;
|
|
474
|
+
/**
|
|
475
|
+
* The OpenTelemetry meter provider. If omitted, the global meter provider
|
|
476
|
+
* is used.
|
|
477
|
+
* @since 2.3.0
|
|
478
|
+
*/
|
|
479
|
+
meterProvider?: MeterProvider;
|
|
466
480
|
}
|
|
467
481
|
/**
|
|
468
482
|
* The reason why {@link verifyRequestDetailed} could not verify a request.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-BID9qTPk.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-ColY3QKj.mjs";
|
|
6
|
+
import { getLogger } from "@logtape/logtape";
|
|
5
7
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
6
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
9
|
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
8
|
-
import { getLogger } from "@logtape/logtape";
|
|
9
10
|
//#region src/sig/key.ts
|
|
10
11
|
/**
|
|
11
12
|
* Checks if the given key is valid and supported. No-op if the key is valid,
|
|
@@ -306,24 +307,48 @@ async function resolveFetchedKey(document, cacheKey, keyId, cls, { documentLoade
|
|
|
306
307
|
};
|
|
307
308
|
}
|
|
308
309
|
async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, onFetchError) {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
"sig",
|
|
312
|
-
"key"
|
|
313
|
-
]);
|
|
314
|
-
const keyId = cacheKey.href;
|
|
315
|
-
const keyCache = options.keyCache;
|
|
316
|
-
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
317
|
-
if (cached?.key === null && cached.cached) return await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
318
|
-
if (cached != null) return cached;
|
|
319
|
-
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
320
|
-
let document;
|
|
310
|
+
const start = performance.now();
|
|
311
|
+
let outcome = { result: "error" };
|
|
321
312
|
try {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
const logger = getLogger([
|
|
314
|
+
"fedify",
|
|
315
|
+
"sig",
|
|
316
|
+
"key"
|
|
317
|
+
]);
|
|
318
|
+
const keyId = cacheKey.href;
|
|
319
|
+
const keyCache = options.keyCache;
|
|
320
|
+
const cached = await getCachedFetchKey(cacheKey, keyId, cls, keyCache, logger);
|
|
321
|
+
if (cached?.key === null && cached.cached) {
|
|
322
|
+
const cachedUnavailable = await onCachedUnavailable(cacheKey, keyId, keyCache, logger);
|
|
323
|
+
outcome = { result: "hit" };
|
|
324
|
+
return cachedUnavailable;
|
|
325
|
+
}
|
|
326
|
+
if (cached != null) {
|
|
327
|
+
outcome = { result: "hit" };
|
|
328
|
+
return cached;
|
|
329
|
+
}
|
|
330
|
+
logger.debug("Fetching key {keyId} to verify signature...", { keyId });
|
|
331
|
+
let document;
|
|
332
|
+
try {
|
|
333
|
+
document = (await (options.documentLoader ?? getDocumentLoader())(keyId)).document;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
const classified = classifyFetchError(error);
|
|
336
|
+
const errored = await onFetchError(error, cacheKey, keyId, keyCache, logger);
|
|
337
|
+
outcome = classified;
|
|
338
|
+
return errored;
|
|
339
|
+
}
|
|
340
|
+
const resolved = await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
341
|
+
outcome = { result: resolved.key != null ? "fetched" : "invalid" };
|
|
342
|
+
return resolved;
|
|
343
|
+
} finally {
|
|
344
|
+
recordKeyLookup(options.meterProvider, {
|
|
345
|
+
durationMs: getDurationMs(start),
|
|
346
|
+
result: outcome.result,
|
|
347
|
+
remoteUrl: cacheKey,
|
|
348
|
+
cacheEnabled: options.keyCache != null,
|
|
349
|
+
statusCode: outcome.statusCode
|
|
350
|
+
});
|
|
325
351
|
}
|
|
326
|
-
return await resolveFetchedKey(document, cacheKey, keyId, cls, options, logger);
|
|
327
352
|
}
|
|
328
353
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
329
354
|
return await fetchKeyWithResult(typeof keyId === "string" ? new URL(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
require("./chunk-DDcVe30Y.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-CjZwUPiT.cjs");
|
|
5
5
|
let _logtape_logtape = require("@logtape/logtape");
|
|
6
6
|
let es_toolkit = require("es-toolkit");
|
|
7
7
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
@@ -56,10 +56,25 @@ const logger = (0, _logtape_logtape.getLogger)([
|
|
|
56
56
|
* @param parameters The parameters for the cache.
|
|
57
57
|
* @returns The decorated document loader which is cache-enabled.
|
|
58
58
|
*/
|
|
59
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
59
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
60
60
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
61
61
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
62
62
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
63
|
+
const lookupKind = kind ?? "object";
|
|
64
|
+
function emitCacheMetric(url, result) {
|
|
65
|
+
if (meterProvider == null) return;
|
|
66
|
+
let remoteUrl;
|
|
67
|
+
try {
|
|
68
|
+
remoteUrl = new URL(url);
|
|
69
|
+
} catch {
|
|
70
|
+
remoteUrl = void 0;
|
|
71
|
+
}
|
|
72
|
+
require_http.recordDocumentCache(meterProvider, {
|
|
73
|
+
kind: lookupKind,
|
|
74
|
+
result,
|
|
75
|
+
remoteUrl
|
|
76
|
+
});
|
|
77
|
+
}
|
|
63
78
|
return async (url, options) => {
|
|
64
79
|
if (url in _fedify_vocab_runtime.preloadedContexts) {
|
|
65
80
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -82,6 +97,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
82
97
|
});
|
|
83
98
|
}
|
|
84
99
|
if (cache == null) {
|
|
100
|
+
emitCacheMetric(url, "miss");
|
|
85
101
|
const remoteDoc = await loader(url, options);
|
|
86
102
|
try {
|
|
87
103
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -93,12 +109,13 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
93
109
|
}
|
|
94
110
|
return remoteDoc;
|
|
95
111
|
}
|
|
112
|
+
emitCacheMetric(url, "hit");
|
|
96
113
|
return cache;
|
|
97
114
|
};
|
|
98
115
|
}
|
|
99
116
|
function matchRule(url, rules) {
|
|
100
117
|
for (const [pattern, d] of rules) {
|
|
101
|
-
const duration =
|
|
118
|
+
const duration = Temporal.Duration.from(d);
|
|
102
119
|
if (typeof pattern === "string") {
|
|
103
120
|
if (url === pattern) return duration;
|
|
104
121
|
continue;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { d as validateCryptoKey, t as doubleKnock } from "./http-
|
|
3
|
+
import { C as recordDocumentCache, d as validateCryptoKey, t as doubleKnock } from "./http-B47Jg9iX.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { curry } from "es-toolkit";
|
|
6
6
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -55,10 +55,25 @@ const logger = getLogger([
|
|
|
55
55
|
* @param parameters The parameters for the cache.
|
|
56
56
|
* @returns The decorated document loader which is cache-enabled.
|
|
57
57
|
*/
|
|
58
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
58
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
59
59
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
60
60
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
61
61
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
62
|
+
const lookupKind = kind ?? "object";
|
|
63
|
+
function emitCacheMetric(url, result) {
|
|
64
|
+
if (meterProvider == null) return;
|
|
65
|
+
let remoteUrl;
|
|
66
|
+
try {
|
|
67
|
+
remoteUrl = new URL(url);
|
|
68
|
+
} catch {
|
|
69
|
+
remoteUrl = void 0;
|
|
70
|
+
}
|
|
71
|
+
recordDocumentCache(meterProvider, {
|
|
72
|
+
kind: lookupKind,
|
|
73
|
+
result,
|
|
74
|
+
remoteUrl
|
|
75
|
+
});
|
|
76
|
+
}
|
|
62
77
|
return async (url, options) => {
|
|
63
78
|
if (url in preloadedContexts) {
|
|
64
79
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -81,6 +96,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
81
96
|
});
|
|
82
97
|
}
|
|
83
98
|
if (cache == null) {
|
|
99
|
+
emitCacheMetric(url, "miss");
|
|
84
100
|
const remoteDoc = await loader(url, options);
|
|
85
101
|
try {
|
|
86
102
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -92,12 +108,13 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
92
108
|
}
|
|
93
109
|
return remoteDoc;
|
|
94
110
|
}
|
|
111
|
+
emitCacheMetric(url, "hit");
|
|
95
112
|
return cache;
|
|
96
113
|
};
|
|
97
114
|
}
|
|
98
115
|
function matchRule(url, rules) {
|
|
99
116
|
for (const [pattern, d] of rules) {
|
|
100
|
-
const duration =
|
|
117
|
+
const duration = Temporal.Duration.from(d);
|
|
101
118
|
if (typeof pattern === "string") {
|
|
102
119
|
if (url === pattern) return duration;
|
|
103
120
|
continue;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import {
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-ColY3QKj.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
|
+
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
6
7
|
//#region src/utils/kv-cache.ts
|
|
7
8
|
const logger = getLogger([
|
|
8
9
|
"fedify",
|
|
@@ -44,10 +45,25 @@ var MockKvStore = class {
|
|
|
44
45
|
* @param parameters The parameters for the cache.
|
|
45
46
|
* @returns The decorated document loader which is cache-enabled.
|
|
46
47
|
*/
|
|
47
|
-
function kvCache({ loader, kv, prefix, rules }) {
|
|
48
|
+
function kvCache({ loader, kv, prefix, rules, meterProvider, kind }) {
|
|
48
49
|
const keyPrefix = prefix ?? ["_fedify", "remoteDocument"];
|
|
49
50
|
rules ??= [[new URLPattern({}), Temporal.Duration.from({ minutes: 5 })]];
|
|
50
51
|
for (const [p, duration] of rules) if (Temporal.Duration.compare(duration, { days: 30 }) > 0) throw new TypeError("The maximum cache duration is 30 days: " + (p instanceof URLPattern ? `${p.protocol}://${p.username}:${p.password}@${p.hostname}:${p.port}/${p.pathname}?${p.search}#${p.hash}` : p.toString()));
|
|
52
|
+
const lookupKind = kind ?? "object";
|
|
53
|
+
function emitCacheMetric(url, result) {
|
|
54
|
+
if (meterProvider == null) return;
|
|
55
|
+
let remoteUrl;
|
|
56
|
+
try {
|
|
57
|
+
remoteUrl = new URL(url);
|
|
58
|
+
} catch {
|
|
59
|
+
remoteUrl = void 0;
|
|
60
|
+
}
|
|
61
|
+
recordDocumentCache(meterProvider, {
|
|
62
|
+
kind: lookupKind,
|
|
63
|
+
result,
|
|
64
|
+
remoteUrl
|
|
65
|
+
});
|
|
66
|
+
}
|
|
51
67
|
return async (url, options) => {
|
|
52
68
|
if (url in preloadedContexts) {
|
|
53
69
|
logger.debug("Using preloaded context: {url}.", { url });
|
|
@@ -70,6 +86,7 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
70
86
|
});
|
|
71
87
|
}
|
|
72
88
|
if (cache == null) {
|
|
89
|
+
emitCacheMetric(url, "miss");
|
|
73
90
|
const remoteDoc = await loader(url, options);
|
|
74
91
|
try {
|
|
75
92
|
await kv.set(key, remoteDoc, { ttl: match });
|
|
@@ -81,12 +98,13 @@ function kvCache({ loader, kv, prefix, rules }) {
|
|
|
81
98
|
}
|
|
82
99
|
return remoteDoc;
|
|
83
100
|
}
|
|
101
|
+
emitCacheMetric(url, "hit");
|
|
84
102
|
return cache;
|
|
85
103
|
};
|
|
86
104
|
}
|
|
87
105
|
function matchRule(url, rules) {
|
|
88
106
|
for (const [pattern, d] of rules) {
|
|
89
|
-
const duration =
|
|
107
|
+
const duration = Temporal.Duration.from(d);
|
|
90
108
|
if (typeof pattern === "string") {
|
|
91
109
|
if (url === pattern) return duration;
|
|
92
110
|
continue;
|