Skip to content

Commit a56496c

Browse files
Annotate relay error spans with schema fields (pingdotgg#2976)
1 parent b76f161 commit a56496c

20 files changed

Lines changed: 744 additions & 232 deletions

infra/relay/src/agentActivity/AgentActivityRows.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { RelayAgentActivityState } from "@t3tools/contracts/relay";
22
import { RelayAgentActivityState as RelayAgentActivityStateSchema } from "@t3tools/contracts/relay";
33
import * as Context from "effect/Context";
4-
import * as Data from "effect/Data";
54
import * as DateTime from "effect/DateTime";
65
import * as Effect from "effect/Effect";
76
import { cast } from "effect/Function";
@@ -13,23 +12,32 @@ import { and, desc, eq, isNull } from "drizzle-orm";
1312
import { RelayDb } from "../db.ts";
1413
import { relayAgentActivityRows, relayEnvironmentLinks } from "../persistence/schema.ts";
1514

16-
export class AgentActivityRowUpsertPersistenceError extends Data.TaggedError(
15+
export class AgentActivityRowUpsertPersistenceError extends Schema.TaggedErrorClass<AgentActivityRowUpsertPersistenceError>()(
1716
"AgentActivityRowUpsertPersistenceError",
18-
)<{
19-
readonly cause: unknown;
20-
}> {}
17+
{ cause: Schema.Defect() },
18+
) {
19+
override get message(): string {
20+
return "Failed to persist agent activity state";
21+
}
22+
}
2123

22-
export class AgentActivityRowDeletePersistenceError extends Data.TaggedError(
24+
export class AgentActivityRowDeletePersistenceError extends Schema.TaggedErrorClass<AgentActivityRowDeletePersistenceError>()(
2325
"AgentActivityRowDeletePersistenceError",
24-
)<{
25-
readonly cause: unknown;
26-
}> {}
26+
{ cause: Schema.Defect() },
27+
) {
28+
override get message(): string {
29+
return "Failed to delete agent activity state";
30+
}
31+
}
2732

28-
export class AgentActivityRowListPersistenceError extends Data.TaggedError(
33+
export class AgentActivityRowListPersistenceError extends Schema.TaggedErrorClass<AgentActivityRowListPersistenceError>()(
2934
"AgentActivityRowListPersistenceError",
30-
)<{
31-
readonly cause: unknown;
32-
}> {}
35+
{ cause: Schema.Defect() },
36+
) {
37+
override get message(): string {
38+
return "Failed to list agent activity state";
39+
}
40+
}
3341

3442
export interface AgentActivityRowsShape {
3543
readonly upsert: (input: {

infra/relay/src/agentActivity/ApnsClient.ts

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,13 @@ import * as NodeCrypto from "node:crypto";
22

33
import type { RelayAgentActivityAggregateState } from "@t3tools/contracts/relay";
44
import * as Context from "effect/Context";
5-
import * as Data from "effect/Data";
65
import * as Effect from "effect/Effect";
76
import * as Encoding from "effect/Encoding";
87
import * as Layer from "effect/Layer";
98
import * as Option from "effect/Option";
109
import * as Redacted from "effect/Redacted";
1110
import * as Schema from "effect/Schema";
12-
import {
13-
Headers,
14-
HttpClient,
15-
HttpClientRequest,
16-
type HttpBody,
17-
type HttpClientError,
18-
} from "effect/unstable/http";
11+
import { Headers, HttpClient, HttpClientRequest } from "effect/unstable/http";
1912
import type { ApnsCredentials } from "../Config.ts";
2013
import type { ApnsNotificationPayload } from "./apnsDeliveryJobs.ts";
2114

@@ -45,18 +38,39 @@ export interface ApnsDeliveryResult {
4538
readonly apnsId: string | null;
4639
}
4740

48-
export class ApnsSigningError extends Data.TaggedError("ApnsSigningError")<{
49-
readonly phase: "encoding" | "signing";
50-
readonly cause: unknown;
51-
}> {}
41+
export class ApnsSigningError extends Schema.TaggedErrorClass<ApnsSigningError>()(
42+
"ApnsSigningError",
43+
{
44+
phase: Schema.Literals(["encoding", "signing"]),
45+
cause: Schema.Defect(),
46+
},
47+
) {
48+
override get message(): string {
49+
return `Failed during APNs JWT ${this.phase}`;
50+
}
51+
}
5252

53-
export class ApnsHttpRequestError extends Data.TaggedError("ApnsHttpRequestError")<{
54-
readonly cause: HttpClientError.HttpClientError | HttpBody.HttpBodyError;
55-
}> {}
53+
export class ApnsHttpRequestError extends Schema.TaggedErrorClass<ApnsHttpRequestError>()(
54+
"ApnsHttpRequestError",
55+
{
56+
cause: Schema.Defect(),
57+
},
58+
) {
59+
override get message(): string {
60+
return "APNs HTTP request failed";
61+
}
62+
}
5663

57-
export class ApnsInvalidResponseError extends Data.TaggedError("ApnsInvalidResponseError")<{
58-
readonly cause: unknown;
59-
}> {}
64+
export class ApnsInvalidResponseError extends Schema.TaggedErrorClass<ApnsInvalidResponseError>()(
65+
"ApnsInvalidResponseError",
66+
{
67+
cause: Schema.Defect(),
68+
},
69+
) {
70+
override get message(): string {
71+
return "APNs returned an invalid response";
72+
}
73+
}
6074

6175
export type ApnsError = ApnsSigningError | ApnsHttpRequestError | ApnsInvalidResponseError;
6276

infra/relay/src/agentActivity/ApnsDeliveries.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
RelayAgentAwarenessPreferences as RelayAgentAwarenessPreferencesSchema,
1010
} from "@t3tools/contracts/relay";
1111
import * as Context from "effect/Context";
12-
import * as Data from "effect/Data";
1312
import * as DateTime from "effect/DateTime";
1413
import * as Effect from "effect/Effect";
1514
import * as Layer from "effect/Layer";
@@ -74,9 +73,16 @@ export type ApnsDeliveryError =
7473
| LiveActivities.LiveActivityTargetListPersistenceError
7574
| LiveActivities.LiveActivityDeliveryMarkPersistenceError;
7675

77-
export class ApnsDeliveryJobClaimInFlight extends Data.TaggedError("ApnsDeliveryJobClaimInFlight")<{
78-
readonly sourceJobId: string;
79-
}> {}
76+
export class ApnsDeliveryJobClaimInFlight extends Schema.TaggedErrorClass<ApnsDeliveryJobClaimInFlight>()(
77+
"ApnsDeliveryJobClaimInFlight",
78+
{
79+
sourceJobId: Schema.String,
80+
},
81+
) {
82+
override get message(): string {
83+
return `APNs delivery job '${this.sourceJobId}' is already in flight`;
84+
}
85+
}
8086

8187
const decodeRelayAgentActivityAggregateStateJson = Schema.decodeUnknownOption(
8288
Schema.fromJsonString(RelayAgentActivityAggregateStateSchema),

infra/relay/src/agentActivity/ApnsDeliveryQueue.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import * as Alchemy from "alchemy";
22
import * as Cloudflare from "alchemy/Cloudflare";
33
import * as Crypto from "effect/Crypto";
44
import * as Context from "effect/Context";
5-
import * as Data from "effect/Data";
65
import * as DateTime from "effect/DateTime";
76
import * as Effect from "effect/Effect";
87
import * as Layer from "effect/Layer";
8+
import * as Schema from "effect/Schema";
99

1010
import type { RelayDeliveryResult } from "@t3tools/contracts/relay";
1111

@@ -22,9 +22,14 @@ import {
2222
} from "./apnsDeliveryJobs.ts";
2323
import * as RelayConfiguration from "../Config.ts";
2424

25-
export class ApnsDeliveryQueueSendError extends Data.TaggedError("ApnsDeliveryQueueSendError")<{
26-
readonly cause: unknown;
27-
}> {}
25+
export class ApnsDeliveryQueueSendError extends Schema.TaggedErrorClass<ApnsDeliveryQueueSendError>()(
26+
"ApnsDeliveryQueueSendError",
27+
{ cause: Schema.Defect() },
28+
) {
29+
override get message(): string {
30+
return "Failed to enqueue APNs delivery";
31+
}
32+
}
2833

2934
export type ApnsDeliveryQueueError = ApnsDeliveryQueueSendError;
3035

infra/relay/src/agentActivity/DeliveryAttempts.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import * as Context from "effect/Context";
2-
import * as Data from "effect/Data";
32
import * as DateTime from "effect/DateTime";
43
import * as Effect from "effect/Effect";
54
import * as Layer from "effect/Layer";
65
import * as Option from "effect/Option";
76
import { and, eq, isNull } from "drizzle-orm";
87
import * as Crypto from "effect/Crypto";
8+
import * as Schema from "effect/Schema";
99

1010
import { RelayDb } from "../db.ts";
1111
import { relayDeliveryAttempts } from "../persistence/schema.ts";
1212

13-
export class DeliveryAttemptRecordPersistenceError extends Data.TaggedError(
13+
export class DeliveryAttemptRecordPersistenceError extends Schema.TaggedErrorClass<DeliveryAttemptRecordPersistenceError>()(
1414
"DeliveryAttemptRecordPersistenceError",
15-
)<{
16-
readonly cause: unknown;
17-
}> {}
15+
{ cause: Schema.Defect() },
16+
) {
17+
override get message(): string {
18+
return "Failed to persist APNs delivery attempt";
19+
}
20+
}
1821

1922
export interface DeliveryAttemptInput {
2023
readonly userId: string | null;

infra/relay/src/agentActivity/Devices.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,42 @@ import type {
33
RelayDeviceRegistrationRequest,
44
} from "@t3tools/contracts/relay";
55
import * as Context from "effect/Context";
6-
import * as Data from "effect/Data";
76
import * as DateTime from "effect/DateTime";
87
import * as Effect from "effect/Effect";
98
import * as Layer from "effect/Layer";
9+
import * as Schema from "effect/Schema";
1010
import { and, eq } from "drizzle-orm";
1111
import { sql } from "drizzle-orm";
1212

1313
import { RelayDb } from "../db.ts";
1414
import { relayLiveActivities, relayMobileDevices } from "../persistence/schema.ts";
1515

16-
export class DeviceRegistrationPersistenceError extends Data.TaggedError(
16+
export class DeviceRegistrationPersistenceError extends Schema.TaggedErrorClass<DeviceRegistrationPersistenceError>()(
1717
"DeviceRegistrationPersistenceError",
18-
)<{
19-
readonly cause: unknown;
20-
}> {}
18+
{ cause: Schema.Defect() },
19+
) {
20+
override get message(): string {
21+
return "Failed to persist mobile device registration";
22+
}
23+
}
2124

22-
export class DeviceUnregistrationPersistenceError extends Data.TaggedError(
25+
export class DeviceUnregistrationPersistenceError extends Schema.TaggedErrorClass<DeviceUnregistrationPersistenceError>()(
2326
"DeviceUnregistrationPersistenceError",
24-
)<{
25-
readonly cause: unknown;
26-
}> {}
27+
{ cause: Schema.Defect() },
28+
) {
29+
override get message(): string {
30+
return "Failed to unregister mobile device";
31+
}
32+
}
2733

28-
export class DeviceListPersistenceError extends Data.TaggedError("DeviceListPersistenceError")<{
29-
readonly cause: unknown;
30-
}> {}
34+
export class DeviceListPersistenceError extends Schema.TaggedErrorClass<DeviceListPersistenceError>()(
35+
"DeviceListPersistenceError",
36+
{ cause: Schema.Defect() },
37+
) {
38+
override get message(): string {
39+
return "Failed to list mobile devices";
40+
}
41+
}
3142

3243
export interface DevicesShape {
3344
readonly register: (input: {

infra/relay/src/agentActivity/LiveActivities.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import type {
55
} from "@t3tools/contracts/relay";
66
import { RelayAgentActivityAggregateState as RelayAgentActivityAggregateStateSchema } from "@t3tools/contracts/relay";
77
import * as Context from "effect/Context";
8-
import * as Data from "effect/Data";
98
import * as DateTime from "effect/DateTime";
109
import * as Effect from "effect/Effect";
1110
import { cast } from "effect/Function";
@@ -16,23 +15,32 @@ import { and, eq, sql } from "drizzle-orm";
1615
import { RelayDb } from "../db.ts";
1716
import { relayLiveActivities, relayMobileDevices } from "../persistence/schema.ts";
1817

19-
export class LiveActivityRegistrationPersistenceError extends Data.TaggedError(
18+
export class LiveActivityRegistrationPersistenceError extends Schema.TaggedErrorClass<LiveActivityRegistrationPersistenceError>()(
2019
"LiveActivityRegistrationPersistenceError",
21-
)<{
22-
readonly cause: unknown;
23-
}> {}
20+
{ cause: Schema.Defect() },
21+
) {
22+
override get message(): string {
23+
return "Failed to persist Live Activity registration";
24+
}
25+
}
2426

25-
export class LiveActivityTargetListPersistenceError extends Data.TaggedError(
27+
export class LiveActivityTargetListPersistenceError extends Schema.TaggedErrorClass<LiveActivityTargetListPersistenceError>()(
2628
"LiveActivityTargetListPersistenceError",
27-
)<{
28-
readonly cause: unknown;
29-
}> {}
29+
{ cause: Schema.Defect() },
30+
) {
31+
override get message(): string {
32+
return "Failed to list Live Activity delivery targets";
33+
}
34+
}
3035

31-
export class LiveActivityDeliveryMarkPersistenceError extends Data.TaggedError(
36+
export class LiveActivityDeliveryMarkPersistenceError extends Schema.TaggedErrorClass<LiveActivityDeliveryMarkPersistenceError>()(
3237
"LiveActivityDeliveryMarkPersistenceError",
33-
)<{
34-
readonly cause: unknown;
35-
}> {}
38+
{ cause: Schema.Defect() },
39+
) {
40+
override get message(): string {
41+
return "Failed to persist Live Activity delivery state";
42+
}
43+
}
3644

3745
export interface DeviceRow {
3846
readonly user_id: string;

infra/relay/src/agentActivity/apnsDeliveryJobs.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as NodeCrypto from "node:crypto";
22

33
import { RelayAgentActivityAggregateState, type RelayDeliveryKind } from "@t3tools/contracts/relay";
44
import { stableStringify } from "@t3tools/shared/relaySigning";
5-
import * as Data from "effect/Data";
65
import * as DateTime from "effect/DateTime";
76
import * as Option from "effect/Option";
87
import * as Redacted from "effect/Redacted";
@@ -50,13 +49,23 @@ export const SignedApnsDeliveryJob = Schema.Struct({
5049
});
5150
export type SignedApnsDeliveryJob = typeof SignedApnsDeliveryJob.Type;
5251

53-
export class ApnsDeliveryJobInvalid extends Data.TaggedError("ApnsDeliveryJobInvalid")<{
54-
readonly message: string;
55-
}> {}
56-
57-
export class ApnsDeliveryJobExpired extends Data.TaggedError("ApnsDeliveryJobExpired")<{
58-
readonly expiresAt: string;
59-
}> {}
52+
export class ApnsDeliveryJobInvalid extends Schema.TaggedErrorClass<ApnsDeliveryJobInvalid>()(
53+
"ApnsDeliveryJobInvalid",
54+
{
55+
message: Schema.String,
56+
},
57+
) {}
58+
59+
export class ApnsDeliveryJobExpired extends Schema.TaggedErrorClass<ApnsDeliveryJobExpired>()(
60+
"ApnsDeliveryJobExpired",
61+
{
62+
expiresAt: Schema.String,
63+
},
64+
) {
65+
override get message(): string {
66+
return `APNs delivery job expired at ${this.expiresAt}`;
67+
}
68+
}
6069

6170
export type ApnsDeliveryJobVerificationError = ApnsDeliveryJobInvalid | ApnsDeliveryJobExpired;
6271

infra/relay/src/auth/DpopProofs.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
import * as Context from "effect/Context";
2-
import * as Data from "effect/Data";
32
import * as DateTime from "effect/DateTime";
43
import * as Effect from "effect/Effect";
54
import * as Layer from "effect/Layer";
5+
import * as Schema from "effect/Schema";
66
import * as HttpApiError from "effect/unstable/httpapi/HttpApiError";
77
import { lt } from "drizzle-orm";
88

99
import { verifyDpopProof } from "@t3tools/shared/dpop";
1010
import { RelayDb } from "../db.ts";
1111
import { relayDpopProofs } from "../persistence/schema.ts";
1212

13-
export class DpopProofReplayPersistenceError extends Data.TaggedError(
13+
export class DpopProofReplayPersistenceError extends Schema.TaggedErrorClass<DpopProofReplayPersistenceError>()(
1414
"DpopProofReplayPersistenceError",
15-
)<{
16-
readonly cause: unknown;
17-
}> {}
15+
{
16+
cause: Schema.Defect(),
17+
},
18+
) {
19+
override get message(): string {
20+
return "Failed to persist DPoP proof replay state";
21+
}
22+
}
1823

1924
export interface DpopProofReplayShape {
2025
readonly verifyAndConsume: (input: {

0 commit comments

Comments
 (0)