Skip to content

Commit 3b1212b

Browse files
authored
refactor(outbound): share audit history projection (#113597)
1 parent 902cc53 commit 3b1212b

2 files changed

Lines changed: 87 additions & 61 deletions

File tree

src/infra/outbound/outbound-audit.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { describe, expect, it, vi } from "vitest";
22
import type { TrustedMessageAuditEvent } from "../../audit/message-audit-events.js";
33
import { onTrustedMessageAuditEventForTest as onTrustedMessageAuditEvent } from "../../audit/message-audit-events.test-support.js";
4+
import type { OutboundPayloadDeliveryOutcome } from "./deliver-types.js";
45
import {
56
completedOutboundAuditTerminals,
67
emitOutboundAuditTerminals,
8+
failedOutboundAuditTerminals,
79
uniformOutboundAuditTerminals,
810
} from "./outbound-audit.js";
911

@@ -165,6 +167,56 @@ describe("outbound audit projection", () => {
165167
expect(events[0]).not.toHaveProperty("deliveryKind");
166168
});
167169

170+
it.each([
171+
{
172+
kind: "completed",
173+
project: (payloadOutcomes: OutboundPayloadDeliveryOutcome[]) =>
174+
completedOutboundAuditTerminals({
175+
payloadCount: 1,
176+
results: [],
177+
payloadOutcomes,
178+
}),
179+
},
180+
{
181+
kind: "failed",
182+
project: (payloadOutcomes: OutboundPayloadDeliveryOutcome[]) =>
183+
failedOutboundAuditTerminals({
184+
payloadCount: 1,
185+
results: [],
186+
payloadOutcomes,
187+
failureStage: "platform_send",
188+
}),
189+
},
190+
])("projects recorded history consistently for $kind runs", ({ project }) => {
191+
const result = { channel: "matrix" as const, messageId: "platform-1" };
192+
193+
expect(
194+
project([
195+
{ index: 0, status: "suppressed", reason: "adapter_returned_no_identity" },
196+
{ index: 0, status: "sent", results: [result] },
197+
]),
198+
).toEqual([
199+
{
200+
payloadIndex: 0,
201+
terminal: { outcome: "unknown", failureStage: "platform_send" },
202+
},
203+
]);
204+
expect(
205+
project([{ index: 0, status: "sent", results: [result], deliveryKind: "media" }]),
206+
).toEqual([
207+
{
208+
payloadIndex: 0,
209+
terminal: { outcome: "sent", results: [result], deliveryKind: "media" },
210+
},
211+
]);
212+
expect(project([{ index: 0, status: "suppressed", reason: "no_visible_payload" }])).toEqual([
213+
{
214+
payloadIndex: 0,
215+
terminal: { outcome: "suppressed", reasonCode: "no_visible_payload" },
216+
},
217+
]);
218+
});
219+
168220
it("counts physical sends once across receipt representations and result fallbacks", () => {
169221
const events: TrustedMessageAuditEvent[] = [];
170222
const unsubscribe = onTrustedMessageAuditEvent((event) => events.push(event));

src/infra/outbound/outbound-audit.ts

Lines changed: 35 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,34 @@ function sentResults(
9494
return sent?.results ?? [];
9595
}
9696

97-
function hasUnknownAdapterSideEffect(history: readonly OutboundPayloadDeliveryOutcome[]): boolean {
98-
return history.some(
99-
(outcome) =>
100-
outcome.status === "suppressed" && outcome.reason === "adapter_returned_no_identity",
101-
);
97+
function projectRecordedOutboundAuditTerminal(
98+
history: readonly OutboundPayloadDeliveryOutcome[],
99+
): OutboundAuditTerminal | undefined {
100+
// A missing adapter identity leaves the whole payload history uncertain,
101+
// even if a later retry reports another terminal outcome.
102+
if (
103+
history.some(
104+
(outcome) =>
105+
outcome.status === "suppressed" && outcome.reason === "adapter_returned_no_identity",
106+
)
107+
) {
108+
return { outcome: "unknown", failureStage: "platform_send" };
109+
}
110+
const latest = history.at(-1);
111+
if (latest?.status === "sent") {
112+
return {
113+
outcome: "sent",
114+
results: latest.results,
115+
...(latest.deliveryKind ? { deliveryKind: latest.deliveryKind } : {}),
116+
};
117+
}
118+
if (latest?.status === "suppressed") {
119+
if (latest.reason === "adapter_returned_no_identity") {
120+
return { outcome: "unknown", failureStage: "platform_send" };
121+
}
122+
return { outcome: "suppressed", reasonCode: latest.reason };
123+
}
124+
return undefined;
102125
}
103126

104127
export function completedOutboundAuditTerminals(params: {
@@ -109,34 +132,9 @@ export function completedOutboundAuditTerminals(params: {
109132
const indexed = outcomesByPayload(params.payloadOutcomes);
110133
return Array.from({ length: params.payloadCount }, (_, payloadIndex) => {
111134
const history = indexed.get(payloadIndex) ?? [];
112-
const latest = history.at(-1);
113-
if (hasUnknownAdapterSideEffect(history)) {
114-
return {
115-
payloadIndex,
116-
terminal: { outcome: "unknown", failureStage: "platform_send" },
117-
};
118-
}
119-
if (latest?.status === "sent") {
120-
return {
121-
payloadIndex,
122-
terminal: {
123-
outcome: "sent",
124-
results: latest.results,
125-
...(latest.deliveryKind ? { deliveryKind: latest.deliveryKind } : {}),
126-
},
127-
};
128-
}
129-
if (latest?.status === "suppressed") {
130-
if (latest.reason === "adapter_returned_no_identity") {
131-
return {
132-
payloadIndex,
133-
terminal: { outcome: "unknown", failureStage: "platform_send" },
134-
};
135-
}
136-
return {
137-
payloadIndex,
138-
terminal: { outcome: "suppressed", reasonCode: latest.reason },
139-
};
135+
const recordedTerminal = projectRecordedOutboundAuditTerminal(history);
136+
if (recordedTerminal) {
137+
return { payloadIndex, terminal: recordedTerminal };
140138
}
141139
// Core delivery reports every original payload, including normalization
142140
// suppressions. The single-payload fallback supports legacy recovery senders.
@@ -159,35 +157,11 @@ export function failedOutboundAuditTerminals(params: {
159157
const indexed = outcomesByPayload(params.payloadOutcomes);
160158
return Array.from({ length: params.payloadCount }, (_, payloadIndex) => {
161159
const history = indexed.get(payloadIndex) ?? [];
162-
const latest = history.at(-1);
163-
if (hasUnknownAdapterSideEffect(history)) {
164-
return {
165-
payloadIndex,
166-
terminal: { outcome: "unknown", failureStage: "platform_send" },
167-
};
168-
}
169-
if (latest?.status === "sent") {
170-
return {
171-
payloadIndex,
172-
terminal: {
173-
outcome: "sent",
174-
results: latest.results,
175-
...(latest.deliveryKind ? { deliveryKind: latest.deliveryKind } : {}),
176-
},
177-
};
178-
}
179-
if (latest?.status === "suppressed") {
180-
if (latest.reason === "adapter_returned_no_identity") {
181-
return {
182-
payloadIndex,
183-
terminal: { outcome: "unknown", failureStage: "platform_send" },
184-
};
185-
}
186-
return {
187-
payloadIndex,
188-
terminal: { outcome: "suppressed", reasonCode: latest.reason },
189-
};
160+
const recordedTerminal = projectRecordedOutboundAuditTerminal(history);
161+
if (recordedTerminal) {
162+
return { payloadIndex, terminal: recordedTerminal };
190163
}
164+
const latest = history.at(-1);
191165
const failedResults = latest?.status === "failed" ? (latest.results ?? []) : [];
192166
const payloadResults = failedResults.length > 0 ? failedResults : sentResults(history);
193167
const fallbackResults = params.payloadCount === 1 ? params.results : [];

0 commit comments

Comments
 (0)