@fedify/fedify 2.3.0-dev.1069 → 2.3.0-dev.1099

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.
Files changed (113) hide show
  1. package/dist/{builder-DQ2zYTeA.mjs → builder-BkRRjxzb.mjs} +4 -4
  2. package/dist/{chunk-nlSIicah.js → chunk-CRNNMoPX.js} +2 -2
  3. package/dist/{chunk-QSgtlS85.mjs → chunk-DNRtMIoB.mjs} +1 -1
  4. package/dist/{client-z-8dc-e1.d.cts → client-CAM_bQXx.d.cts} +1 -0
  5. package/dist/{client-AtlibPOU.d.ts → client-CSddvgWN.d.ts} +1 -2
  6. package/dist/compat/mod.d.cts +2 -1
  7. package/dist/compat/mod.d.ts +2 -3
  8. package/dist/compat/mod.js +3 -3
  9. package/dist/compat/outgoing-jsonld.test.mjs +2 -2
  10. package/dist/compat/public-audience.test.mjs +2 -2
  11. package/dist/compat/transformers.test.mjs +2 -2
  12. package/dist/{context-7Azky82W.mjs → context-BAE7AKLA.mjs} +61 -3
  13. package/dist/{context-DrNqYkPw.d.ts → context-C0C_sRha.d.cts} +6 -7
  14. package/dist/{context-BKLGj9QO.d.cts → context-Dqgt8saU.d.ts} +6 -5
  15. package/dist/{deno-CFXqOz6w.mjs → deno-DBabeupC.mjs} +1 -1
  16. package/dist/{docloader-QNtAtTZF.mjs → docloader-DA5FzJOR.mjs} +3 -3
  17. package/dist/{esm-DhnRLoG9.mjs → esm-sdtqOUPu.mjs} +5 -7
  18. package/dist/{execAsync-eck5rbtb.mjs → execAsync-DCBrgFiV.mjs} +2 -2
  19. package/dist/federation/builder.test.mjs +3 -3
  20. package/dist/federation/handler.test.mjs +86 -4
  21. package/dist/federation/idempotency.test.mjs +3 -3
  22. package/dist/federation/inbox.test.mjs +1 -1
  23. package/dist/federation/keycache.test.mjs +1 -1
  24. package/dist/federation/middleware.test.mjs +387 -20
  25. package/dist/federation/mod.cjs +1 -1
  26. package/dist/federation/mod.d.cts +4 -3
  27. package/dist/federation/mod.d.ts +4 -5
  28. package/dist/federation/mod.js +2 -2
  29. package/dist/federation/mq.test.mjs +1 -1
  30. package/dist/federation/negotiation.test.mjs +1 -1
  31. package/dist/federation/router.test.mjs +1 -1
  32. package/dist/federation/send.test.mjs +133 -139
  33. package/dist/federation/webfinger.test.mjs +3 -3
  34. package/dist/{getMachineId-bsd-DqZ4QRFp.mjs → getMachineId-bsd-etIyxDet.mjs} +3 -3
  35. package/dist/{getMachineId-darwin-DMbbW3m7.mjs → getMachineId-darwin-D23zTf4g.mjs} +3 -3
  36. package/dist/{getMachineId-linux-lyeD2ug3.mjs → getMachineId-linux-ObI47Hql.mjs} +2 -2
  37. package/dist/{getMachineId-unsupported-JuKr57jY.mjs → getMachineId-unsupported-Ddu-PFeh.mjs} +2 -2
  38. package/dist/{getMachineId-win-Dxyf5pJq.mjs → getMachineId-win-Dpap6v5i.mjs} +3 -3
  39. package/dist/{http-QHJGzUe8.mjs → http-5G18W3NP.mjs} +59 -11
  40. package/dist/{http-CrGuipxe.d.cts → http-BDZeS5om.d.ts} +2 -1
  41. package/dist/{http-aQzN9Ayi.d.ts → http-C87EWkO0.d.cts} +2 -3
  42. package/dist/{http-D2EDlTr2.js → http-Dzy5c472.js} +58 -10
  43. package/dist/{http-e1wtIlFo.cjs → http-W2u_KBoQ.cjs} +57 -9
  44. package/dist/{key-CpAxygvh.mjs → key-D9dUsyow.mjs} +2 -2
  45. package/dist/{kv-CbLNp3zQ.d.cts → kv-D6hNiMTK.d.ts} +1 -0
  46. package/dist/{kv-cache-B3GfB70S.cjs → kv-cache-BygrlQ1c.cjs} +2 -2
  47. package/dist/{kv-cache-KLjvIlKt.js → kv-cache-CBSgxEsZ.js} +2 -2
  48. package/dist/{kv-cache-Bmv7tUzz.mjs → kv-cache-CiiNwT6W.mjs} +2 -2
  49. package/dist/{kv-GFYnFoOl.d.ts → kv-gJ8LYbxX.d.cts} +1 -3
  50. package/dist/{ld-Ce_vkKjG.mjs → ld-hbxDLO1k.mjs} +3 -3
  51. package/dist/{middleware-DsGmXfXz.mjs → middleware-BXnhAGF9.mjs} +201 -119
  52. package/dist/{middleware-DOLrvK_b.cjs → middleware-Caj827xW.cjs} +358 -139
  53. package/dist/{middleware-BJMPv7_l.mjs → middleware-DZQsPMZb.mjs} +1 -1
  54. package/dist/{middleware-De241etq.js → middleware-vCF_cKAq.js} +346 -111
  55. package/dist/{mod-CLgIXe9w.d.ts → mod-B0rWmfW5.d.cts} +4 -5
  56. package/dist/{mod-CMEbIaNh.d.cts → mod-BhU_H1I_.d.ts} +4 -3
  57. package/dist/{mod-B8Z8mBLk.d.ts → mod-CLPnQPsv.d.cts} +2 -3
  58. package/dist/{mod-Cr3f-ACa.d.cts → mod-DHO9lk3D.d.ts} +3 -2
  59. package/dist/{mod-CR8soWa9.d.ts → mod-DXY9JF28.d.cts} +3 -4
  60. package/dist/{mod-DClCOv0M.d.cts → mod-Dx3-hqyo.d.ts} +2 -1
  61. package/dist/mod.cjs +4 -4
  62. package/dist/mod.d.cts +9 -8
  63. package/dist/mod.d.ts +9 -10
  64. package/dist/mod.js +9 -9
  65. package/dist/{negotiation-VnHNB0Q5.mjs → negotiation-DDstyBvc.mjs} +29 -0
  66. package/dist/nodeinfo/client.test.mjs +2 -2
  67. package/dist/nodeinfo/handler.test.mjs +2 -2
  68. package/dist/nodeinfo/mod.d.cts +2 -1
  69. package/dist/nodeinfo/mod.d.ts +2 -3
  70. package/dist/nodeinfo/mod.js +3 -3
  71. package/dist/otel/exporter.test.mjs +2 -2
  72. package/dist/otel/mod.d.cts +2 -1
  73. package/dist/otel/mod.d.ts +2 -3
  74. package/dist/otel/mod.js +2 -2
  75. package/dist/{outgoing-jsonld-Bi7n-dEy.mjs → outgoing-jsonld-BgFLCJQ_.mjs} +2 -2
  76. package/dist/{owner-CptqhsOy.d.cts → owner-CnngXDNJ.d.ts} +2 -1
  77. package/dist/{owner-74ARJ5TL.d.ts → owner-DEvZuyOE.d.cts} +2 -3
  78. package/dist/{owner-DmgzyItA.mjs → owner-DwJe0BH9.mjs} +2 -2
  79. package/dist/{proof-BU1TpFYI.cjs → proof-CZCaAURh.cjs} +3 -3
  80. package/dist/{proof-DLDsFYfD.js → proof-DMJJZnKd.js} +2 -2
  81. package/dist/{proof-C3q2IhUr.mjs → proof-erpV_J_n.mjs} +5 -5
  82. package/dist/runtime/mod.d.cts +1 -0
  83. package/dist/runtime/mod.d.ts +1 -2
  84. package/dist/runtime/mod.js +3 -3
  85. package/dist/{send-CTi2iPXp.mjs → send-BOwz4Hw5.mjs} +128 -4
  86. package/dist/sig/http.test.mjs +140 -27
  87. package/dist/sig/key.test.mjs +2 -2
  88. package/dist/sig/ld.test.mjs +3 -3
  89. package/dist/sig/mod.cjs +2 -2
  90. package/dist/sig/mod.d.cts +4 -3
  91. package/dist/sig/mod.d.ts +4 -5
  92. package/dist/sig/mod.js +4 -4
  93. package/dist/sig/owner.test.mjs +2 -2
  94. package/dist/sig/proof.test.mjs +3 -3
  95. package/dist/testing/mod.d.mts +6 -1
  96. package/dist/testing/mod.mjs +1 -2
  97. package/dist/{transformers-ve6e2xcg.js → transformers-BGMIq1cs.js} +2 -2
  98. package/dist/{types-hvL8ElAs.js → types-CAY3OdLq.js} +2 -2
  99. package/dist/utils/docloader.test.mjs +3 -3
  100. package/dist/utils/kv-cache.test.mjs +2 -2
  101. package/dist/utils/mod.cjs +1 -1
  102. package/dist/utils/mod.d.cts +2 -1
  103. package/dist/utils/mod.d.ts +2 -3
  104. package/dist/utils/mod.js +3 -3
  105. package/dist/vocab/cjs.test.mjs +1 -1
  106. package/dist/vocab/mod.d.cts +1 -0
  107. package/dist/vocab/mod.d.ts +1 -2
  108. package/dist/vocab/mod.js +2 -2
  109. package/package.json +15 -15
  110. package/dist/middleware-CibncbiT.cjs +0 -4
  111. package/dist/{client-CIiz1WX7.mjs → client-B_A6mfn3.mjs} +1 -1
  112. package/dist/{public-audience-PVTwU_Ex.mjs → public-audience-N3pyOx2p.mjs} +1 -1
  113. /package/dist/{router-CrMLXoOr.mjs → router-BT_F5748.mjs} +0 -0
@@ -1,31 +1,31 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as RouterError } from "./router-CrMLXoOr.mjs";
5
- import { n as version, t as name } from "./deno-CFXqOz6w.mjs";
4
+ import { n as RouterError } from "./router-BT_F5748.mjs";
5
+ import { n as version, t as name } from "./deno-DBabeupC.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CceiKpCy.mjs";
7
- import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-CpAxygvh.mjs";
8
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-QHJGzUe8.mjs";
9
- import { t as getAuthenticatedDocumentLoader } from "./docloader-QNtAtTZF.mjs";
10
- import { n as kvCache } from "./kv-cache-Bmv7tUzz.mjs";
11
- import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-Ce_vkKjG.mjs";
12
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DmgzyItA.mjs";
13
- import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-Bi7n-dEy.mjs";
14
- import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-C3q2IhUr.mjs";
15
- import { t as getNodeInfo } from "./client-CIiz1WX7.mjs";
7
+ import { a as importJwk, o as validateCryptoKey, t as exportJwk } from "./key-D9dUsyow.mjs";
8
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-5G18W3NP.mjs";
9
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-DA5FzJOR.mjs";
10
+ import { n as kvCache } from "./kv-cache-CiiNwT6W.mjs";
11
+ import { a as signJsonLd, i as hasSignatureLike, o as verifyJsonLd, r as detachSignature } from "./ld-hbxDLO1k.mjs";
12
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DwJe0BH9.mjs";
13
+ import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-BgFLCJQ_.mjs";
14
+ import { i as verifyObject, n as hasProofLike, r as signObject } from "./proof-erpV_J_n.mjs";
15
+ import { t as getNodeInfo } from "./client-B_A6mfn3.mjs";
16
16
  import { t as nodeInfoToJson } from "./types-BFowWFTT.mjs";
17
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-DQ2zYTeA.mjs";
17
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BkRRjxzb.mjs";
18
18
  import { t as buildCollectionSynchronizationHeader } from "./collection-CA3V5zyK.mjs";
19
- import { a as getFederationMetrics, i as getDurationMs, n as extractInboxes, o as getRemoteHost, r as sendActivity, t as SendActivityError } from "./send-CTi2iPXp.mjs";
19
+ import { a as getFederationMetrics, c as recordOutboxEnqueue, i as getDurationMs, n as extractInboxes, o as getRemoteHost, r as sendActivity, s as isAbortError, t as SendActivityError } from "./send-BOwz4Hw5.mjs";
20
20
  import { t as KvKeyCache } from "./keycache-BeU0LCII.mjs";
21
- import { t as acceptsJsonLd } from "./negotiation-VnHNB0Q5.mjs";
21
+ import { t as acceptsJsonLd } from "./negotiation-DDstyBvc.mjs";
22
22
  import { t as createExponentialBackoffPolicy } from "./retry-_VvV0h9f.mjs";
23
+ import { getLogger, withContext } from "@logtape/logtape";
23
24
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
24
25
  import { lookupWebFinger } from "@fedify/webfinger";
25
26
  import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
26
27
  import { uniq } from "es-toolkit";
27
28
  import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
28
- import { getLogger, withContext } from "@logtape/logtape";
29
29
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
30
30
  import { domainToASCII } from "node:url";
31
31
  //#region src/compat/transformers.ts
@@ -230,6 +230,11 @@ async function routeActivity({ context: ctx, json, activity, recipient, inboxLis
230
230
  });
231
231
  throw error;
232
232
  }
233
+ getFederationMetrics(meterProvider).recordQueueTaskEnqueued({
234
+ role: "inbox",
235
+ queue,
236
+ activityType: getTypeId(activity).href
237
+ }, 0);
233
238
  logger.info("Activity {activityId} is enqueued.", {
234
239
  activityId: activity.id?.href,
235
240
  activity: json,
@@ -1117,6 +1122,14 @@ async function _handleOrderedCollection(request, { name, values, context, tracer
1117
1122
  * @since 1.8.0
1118
1123
  */
1119
1124
  var CustomCollectionHandler = class {
1125
+ name;
1126
+ values;
1127
+ context;
1128
+ callbacks;
1129
+ tracerProvider;
1130
+ Collection;
1131
+ CollectionPage;
1132
+ filterPredicate;
1120
1133
  /**
1121
1134
  * The tracer for telemetry.
1122
1135
  * @type {Tracer}
@@ -1863,78 +1876,123 @@ var FederationImpl = class extends FederationBuilderImpl {
1863
1876
  processQueuedTask(contextData, message) {
1864
1877
  const tracer = this._getTracer();
1865
1878
  const extractedContext = propagation.extract(context.active(), message.traceContext);
1879
+ const meter = getFederationMetrics(this.meterProvider);
1866
1880
  return withContext({ messageId: message.id }, async () => {
1867
- if (message.type === "fanout") await tracer.startActiveSpan("activitypub.fanout", {
1868
- kind: SpanKind.CONSUMER,
1869
- attributes: { "activitypub.activity.type": message.activityType }
1870
- }, extractedContext, async (span) => {
1871
- const spanCtx = span.spanContext();
1872
- return await withContext({
1873
- traceId: spanCtx.traceId,
1874
- spanId: spanCtx.spanId
1875
- }, async () => {
1876
- if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1877
- try {
1878
- await this.#listenFanoutMessage(contextData, message);
1879
- } catch (e) {
1880
- span.setStatus({
1881
- code: SpanStatusCode.ERROR,
1882
- message: String(e)
1883
- });
1884
- throw e;
1885
- } finally {
1886
- span.end();
1887
- }
1881
+ if (message.type === "fanout") {
1882
+ const common = {
1883
+ role: "fanout",
1884
+ queue: this.fanoutQueue,
1885
+ activityType: message.activityType
1886
+ };
1887
+ await tracer.startActiveSpan("activitypub.fanout", {
1888
+ kind: SpanKind.CONSUMER,
1889
+ attributes: { "activitypub.activity.type": message.activityType }
1890
+ }, extractedContext, async (span) => {
1891
+ const spanCtx = span.spanContext();
1892
+ return await withContext({
1893
+ traceId: spanCtx.traceId,
1894
+ spanId: spanCtx.spanId
1895
+ }, async () => {
1896
+ if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1897
+ meter.recordQueueTaskStarted(common);
1898
+ meter.incrementQueueTaskInFlight(common);
1899
+ const startedAt = performance.now();
1900
+ let outcome = "completed";
1901
+ try {
1902
+ await this.#listenFanoutMessage(contextData, message);
1903
+ } catch (e) {
1904
+ const aborted = isAbortError(e);
1905
+ outcome = aborted ? "aborted" : "failed";
1906
+ if (!aborted) span.setStatus({
1907
+ code: SpanStatusCode.ERROR,
1908
+ message: String(e)
1909
+ });
1910
+ throw e;
1911
+ } finally {
1912
+ meter.recordQueueTaskOutcome(common, outcome, getDurationMs(startedAt));
1913
+ meter.decrementQueueTaskInFlight(common);
1914
+ span.end();
1915
+ }
1916
+ });
1888
1917
  });
1889
- });
1890
- else if (message.type === "outbox") await tracer.startActiveSpan("activitypub.outbox", {
1891
- kind: SpanKind.CONSUMER,
1892
- attributes: {
1893
- "activitypub.activity.type": message.activityType,
1894
- "activitypub.activity.retries": message.attempt
1895
- }
1896
- }, extractedContext, async (span) => {
1897
- const spanCtx = span.spanContext();
1898
- return await withContext({
1899
- traceId: spanCtx.traceId,
1900
- spanId: spanCtx.spanId
1901
- }, async () => {
1902
- if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1903
- try {
1904
- await this.#listenOutboxMessage(contextData, message, span);
1905
- } catch (e) {
1906
- span.setStatus({
1907
- code: SpanStatusCode.ERROR,
1908
- message: String(e)
1909
- });
1910
- throw e;
1911
- } finally {
1912
- span.end();
1918
+ } else if (message.type === "outbox") {
1919
+ const common = {
1920
+ role: "outbox",
1921
+ queue: this.outboxQueue,
1922
+ activityType: message.activityType
1923
+ };
1924
+ await tracer.startActiveSpan("activitypub.outbox", {
1925
+ kind: SpanKind.CONSUMER,
1926
+ attributes: {
1927
+ "activitypub.activity.type": message.activityType,
1928
+ "activitypub.activity.retries": message.attempt
1913
1929
  }
1930
+ }, extractedContext, async (span) => {
1931
+ const spanCtx = span.spanContext();
1932
+ return await withContext({
1933
+ traceId: spanCtx.traceId,
1934
+ spanId: spanCtx.spanId
1935
+ }, async () => {
1936
+ if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1937
+ meter.recordQueueTaskStarted(common);
1938
+ meter.incrementQueueTaskInFlight(common);
1939
+ const startedAt = performance.now();
1940
+ let outcome = "completed";
1941
+ try {
1942
+ await this.#listenOutboxMessage(contextData, message, span);
1943
+ } catch (e) {
1944
+ const aborted = isAbortError(e);
1945
+ outcome = aborted ? "aborted" : "failed";
1946
+ if (!aborted) span.setStatus({
1947
+ code: SpanStatusCode.ERROR,
1948
+ message: String(e)
1949
+ });
1950
+ throw e;
1951
+ } finally {
1952
+ meter.recordQueueTaskOutcome(common, outcome, getDurationMs(startedAt));
1953
+ meter.decrementQueueTaskInFlight(common);
1954
+ span.end();
1955
+ }
1956
+ });
1914
1957
  });
1915
- });
1916
- else if (message.type === "inbox") await tracer.startActiveSpan("activitypub.inbox", {
1917
- kind: SpanKind.CONSUMER,
1918
- attributes: { "activitypub.shared_inbox": message.identifier == null }
1919
- }, extractedContext, async (span) => {
1920
- const spanCtx = span.spanContext();
1921
- return await withContext({
1922
- traceId: spanCtx.traceId,
1923
- spanId: spanCtx.spanId
1924
- }, async () => {
1925
- try {
1926
- await this.#listenInboxMessage(contextData, message, span);
1927
- } catch (e) {
1928
- span.setStatus({
1929
- code: SpanStatusCode.ERROR,
1930
- message: String(e)
1931
- });
1932
- throw e;
1933
- } finally {
1934
- span.end();
1935
- }
1958
+ } else if (message.type === "inbox") {
1959
+ const common = {
1960
+ role: "inbox",
1961
+ queue: this.inboxQueue
1962
+ };
1963
+ await tracer.startActiveSpan("activitypub.inbox", {
1964
+ kind: SpanKind.CONSUMER,
1965
+ attributes: { "activitypub.shared_inbox": message.identifier == null }
1966
+ }, extractedContext, async (span) => {
1967
+ const spanCtx = span.spanContext();
1968
+ return await withContext({
1969
+ traceId: spanCtx.traceId,
1970
+ spanId: spanCtx.spanId
1971
+ }, async () => {
1972
+ meter.recordQueueTaskStarted(common);
1973
+ meter.incrementQueueTaskInFlight(common);
1974
+ const startedAt = performance.now();
1975
+ let outcome = "completed";
1976
+ try {
1977
+ await this.#listenInboxMessage(contextData, message, span, (activityType) => {
1978
+ common.activityType = activityType;
1979
+ });
1980
+ } catch (e) {
1981
+ const aborted = isAbortError(e);
1982
+ outcome = aborted ? "aborted" : "failed";
1983
+ if (!aborted) span.setStatus({
1984
+ code: SpanStatusCode.ERROR,
1985
+ message: String(e)
1986
+ });
1987
+ throw e;
1988
+ } finally {
1989
+ meter.recordQueueTaskOutcome(common, outcome, getDurationMs(startedAt));
1990
+ meter.decrementQueueTaskInFlight(common);
1991
+ span.end();
1992
+ }
1993
+ });
1936
1994
  });
1937
- });
1995
+ }
1938
1996
  });
1939
1997
  }
1940
1998
  async #listenFanoutMessage(data, message) {
@@ -2091,10 +2149,19 @@ var FederationImpl = class extends FederationBuilderImpl {
2091
2149
  ...logData,
2092
2150
  error
2093
2151
  });
2094
- await this.outboxQueue?.enqueue({
2152
+ const retryMessage = {
2095
2153
  ...message,
2096
2154
  attempt: message.attempt + 1
2097
- }, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
2155
+ };
2156
+ const { outboxQueue } = this;
2157
+ if (outboxQueue != null) {
2158
+ await outboxQueue.enqueue(retryMessage, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
2159
+ getFederationMetrics(this.meterProvider).recordQueueTaskEnqueued({
2160
+ role: "outbox",
2161
+ queue: outboxQueue,
2162
+ activityType: retryMessage.activityType
2163
+ }, retryMessage.attempt);
2164
+ }
2098
2165
  } else logger.error("Failed to send activity {activityId} to {inbox} after {attempt} attempts; giving up:\n{error}", {
2099
2166
  ...logData,
2100
2167
  error
@@ -2103,7 +2170,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2103
2170
  }
2104
2171
  logger.info("Successfully sent activity {activityId} to {inbox}.", { ...logData });
2105
2172
  }
2106
- async #listenInboxMessage(ctxData, message, span) {
2173
+ async #listenInboxMessage(ctxData, message, span, onActivityType) {
2107
2174
  const logger = getLogger([
2108
2175
  "fedify",
2109
2176
  "federation",
@@ -2117,7 +2184,9 @@ var FederationImpl = class extends FederationBuilderImpl {
2117
2184
  if (identity != null) context = this.#createContext(baseUrl, ctxData, { documentLoader: "identifier" in identity || "username" in identity ? await context.getDocumentLoader(identity) : context.getDocumentLoader(identity) });
2118
2185
  }
2119
2186
  const activity = await Activity.fromJsonLd(message.activity, context);
2120
- span.setAttribute("activitypub.activity.type", getTypeId(activity).href);
2187
+ const activityType = getTypeId(activity).href;
2188
+ span.setAttribute("activitypub.activity.type", activityType);
2189
+ onActivityType?.(activityType);
2121
2190
  if (activity.id != null) span.setAttribute("activitypub.activity.id", activity.id.href);
2122
2191
  const cacheKey = activity.id == null ? null : [
2123
2192
  ...this.kvPrefixes.activityIdempotence,
@@ -2145,7 +2214,7 @@ var FederationImpl = class extends FederationBuilderImpl {
2145
2214
  });
2146
2215
  span.setStatus({
2147
2216
  code: SpanStatusCode.ERROR,
2148
- message: `Unsupported activity type: ${getTypeId(activity).href}`
2217
+ message: `Unsupported activity type: ${activityType}`
2149
2218
  });
2150
2219
  span.end();
2151
2220
  return;
@@ -2153,7 +2222,6 @@ var FederationImpl = class extends FederationBuilderImpl {
2153
2222
  const { class: cls, listener } = dispatched;
2154
2223
  span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
2155
2224
  try {
2156
- const activityType = getTypeId(activity).href;
2157
2225
  const started = performance.now();
2158
2226
  try {
2159
2227
  await listener(context.toInboxContext(message.identifier, message.activity, activity.id?.href, activityType), activity);
@@ -2198,10 +2266,19 @@ var FederationImpl = class extends FederationBuilderImpl {
2198
2266
  activity: message.activity,
2199
2267
  recipient: message.identifier
2200
2268
  });
2201
- await this.inboxQueue?.enqueue({
2269
+ const retryMessage = {
2202
2270
  ...message,
2203
2271
  attempt: message.attempt + 1
2204
- }, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
2272
+ };
2273
+ const { inboxQueue } = this;
2274
+ if (inboxQueue != null) {
2275
+ await inboxQueue.enqueue(retryMessage, { delay: Temporal.Duration.compare(delay, { seconds: 0 }) < 0 ? Temporal.Duration.from({ seconds: 0 }) : delay });
2276
+ getFederationMetrics(this.meterProvider).recordQueueTaskEnqueued({
2277
+ role: "inbox",
2278
+ queue: inboxQueue,
2279
+ activityType
2280
+ }, retryMessage.attempt);
2281
+ }
2205
2282
  } else logger.error("Failed to process the incoming activity {activityId} after {trial} attempts; giving up:\n{error}", {
2206
2283
  error,
2207
2284
  activityId: activity.id?.href,
@@ -2390,9 +2467,11 @@ var FederationImpl = class extends FederationBuilderImpl {
2390
2467
  });
2391
2468
  }
2392
2469
  const { outboxQueue } = this;
2393
- if (outboxQueue.enqueueMany == null) {
2394
- const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
2395
- const errors = (await Promise.allSettled(promises)).filter((r) => r.status === "rejected").map((r) => r.reason);
2470
+ if (outboxQueue.enqueueMany == null || orderingKey != null) {
2471
+ const errors = (await Promise.allSettled(messages.map(async (m) => {
2472
+ await outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey });
2473
+ recordOutboxEnqueue(this.meterProvider, outboxQueue, m.message);
2474
+ }))).filter((r) => r.status === "rejected").map((r) => r.reason);
2396
2475
  if (errors.length > 0) {
2397
2476
  logger.error("Failed to enqueue activity {activityId} to send later: {errors}", {
2398
2477
  activityId: activity.id.href,
@@ -2401,25 +2480,17 @@ var FederationImpl = class extends FederationBuilderImpl {
2401
2480
  if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
2402
2481
  throw errors[0];
2403
2482
  }
2404
- } else if (orderingKey != null) {
2405
- const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
2406
- const errors = (await Promise.allSettled(promises)).filter((r) => r.status === "rejected").map((r) => r.reason);
2407
- if (errors.length > 0) {
2408
- logger.error("Failed to enqueue activity {activityId} to send later: {errors}", {
2483
+ } else {
2484
+ try {
2485
+ await outboxQueue.enqueueMany(messages.map((m) => m.message));
2486
+ } catch (error) {
2487
+ logger.error("Failed to enqueue activity {activityId} to send later: {error}", {
2409
2488
  activityId: activity.id.href,
2410
- errors
2489
+ error
2411
2490
  });
2412
- if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
2413
- throw errors[0];
2491
+ throw error;
2414
2492
  }
2415
- } else try {
2416
- await outboxQueue.enqueueMany(messages.map((m) => m.message));
2417
- } catch (error) {
2418
- logger.error("Failed to enqueue activity {activityId} to send later: {error}", {
2419
- activityId: activity.id.href,
2420
- error
2421
- });
2422
- throw error;
2493
+ for (const m of messages) recordOutboxEnqueue(this.meterProvider, outboxQueue, m.message);
2423
2494
  }
2424
2495
  }
2425
2496
  fetch(request, options) {
@@ -3235,6 +3306,11 @@ var ContextImpl = class ContextImpl {
3235
3306
  };
3236
3307
  if (!this.federation.manuallyStartQueue) this.federation._startQueueInternal(this.data);
3237
3308
  await this.federation.fanoutQueue.enqueue(message, { orderingKey: options.orderingKey });
3309
+ getFederationMetrics(this.federation.meterProvider).recordQueueTaskEnqueued({
3310
+ role: "fanout",
3311
+ queue: this.federation.fanoutQueue,
3312
+ activityType: message.activityType
3313
+ }, 0);
3238
3314
  return true;
3239
3315
  }
3240
3316
  async *getFollowers(identifier) {
@@ -3365,6 +3441,7 @@ var ContextImpl = class ContextImpl {
3365
3441
  kvPrefixes: this.federation.kvPrefixes,
3366
3442
  queue: this.federation.inboxQueue,
3367
3443
  span,
3444
+ meterProvider: this.federation.meterProvider,
3368
3445
  tracerProvider: options.tracerProvider ?? this.tracerProvider,
3369
3446
  idempotencyStrategy: this.federation.idempotencyStrategy
3370
3447
  });
@@ -3614,8 +3691,10 @@ async function forwardActivityInternal(ctx, loggerCategory, forwarder, recipient
3614
3691
  }
3615
3692
  const { outboxQueue } = ctx.federation;
3616
3693
  if (outboxQueue.enqueueMany == null || orderingKey != null) {
3617
- const promises = messages.map((m) => outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey }));
3618
- const errors = (await Promise.allSettled(promises)).filter((r) => r.status === "rejected").map((r) => r.reason);
3694
+ const errors = (await Promise.allSettled(messages.map(async (m) => {
3695
+ await outboxQueue.enqueue(m.message, { orderingKey: m.orderingKey });
3696
+ recordOutboxEnqueue(ctx.federation.meterProvider, outboxQueue, m.message);
3697
+ }))).filter((r) => r.status === "rejected").map((r) => r.reason);
3619
3698
  if (errors.length > 0) {
3620
3699
  logger.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", {
3621
3700
  activityId: ctx.activityId,
@@ -3624,14 +3703,17 @@ async function forwardActivityInternal(ctx, loggerCategory, forwarder, recipient
3624
3703
  if (errors.length > 1) throw new AggregateError(errors, `Failed to enqueue activity ${ctx.activityId} to forward later.`);
3625
3704
  throw errors[0];
3626
3705
  }
3627
- } else try {
3628
- await outboxQueue.enqueueMany(messages.map((m) => m.message));
3629
- } catch (error) {
3630
- logger.error("Failed to enqueue activity {activityId} to forward later:\n{error}", {
3631
- activityId: ctx.activityId,
3632
- error
3633
- });
3634
- throw error;
3706
+ } else {
3707
+ try {
3708
+ await outboxQueue.enqueueMany(messages.map((m) => m.message));
3709
+ } catch (error) {
3710
+ logger.error("Failed to enqueue activity {activityId} to forward later:\n{error}", {
3711
+ activityId: ctx.activityId,
3712
+ error
3713
+ });
3714
+ throw error;
3715
+ }
3716
+ for (const m of messages) recordOutboxEnqueue(ctx.federation.meterProvider, outboxQueue, m.message);
3635
3717
  }
3636
3718
  return true;
3637
3719
  }