| ... | ... | @@ -7,7 +7,10 @@ import * as Effect from "effect/Effect"; |
| 7 | 7 | import * as Layer from "effect/Layer"; |
| 8 | 8 | import * as Schema from "effect/Schema"; |
| 9 | 9 | |
| 10 | | import type { RelayDeliveryResult } from "@t3tools/contracts/relay"; |
| 10 | import { |
| 11 | RelayDeliveryKind as RelayDeliveryKindSchema, |
| 12 | type RelayDeliveryResult, |
| 13 | } from "@t3tools/contracts/relay"; |
| 11 | 14 | |
| 12 | 15 | import { |
| 13 | 16 | sanitizeAgentActivityAggregateState, |
| ... | ... | @@ -24,10 +27,17 @@ import * as RelayConfiguration from "../Config.ts"; |
| 24 | 27 | |
| 25 | 28 | export class ApnsDeliveryQueueSendError extends Schema.TaggedErrorClass<ApnsDeliveryQueueSendError>()( |
| 26 | 29 | "ApnsDeliveryQueueSendError", |
| 27 | | { cause: Schema.Defect() }, |
| 30 | { |
| 31 | operation: Schema.Literals(["generate-job-id", "send"]), |
| 32 | jobId: Schema.NullOr(Schema.String), |
| 33 | kind: RelayDeliveryKindSchema, |
| 34 | userId: Schema.String, |
| 35 | deviceId: Schema.String, |
| 36 | cause: Schema.Defect(), |
| 37 | }, |
| 28 | 38 | ) { |
| 29 | 39 | override get message(): string { |
| 30 | | return "Failed to enqueue APNs delivery"; |
| 40 | return `Failed to enqueue APNs ${this.kind.replaceAll("_", " ")} delivery during ${this.operation} for device ${this.deviceId}.`; |
| 31 | 41 | } |
| 32 | 42 | } |
| 33 | 43 | |
| ... | ... | @@ -36,7 +46,7 @@ export type ApnsDeliveryQueueError = ApnsDeliveryQueueSendError; |
| 36 | 46 | export class ApnsDeliveryQueueSender extends Context.Service< |
| 37 | 47 | ApnsDeliveryQueueSender, |
| 38 | 48 | { |
| 39 | | readonly send: (body: SignedApnsDeliveryJob) => Effect.Effect<void, ApnsDeliveryQueueSendError>; |
| 49 | readonly send: (body: SignedApnsDeliveryJob) => Effect.Effect<void, Cloudflare.QueueSendError>; |
| 40 | 50 | } |
| 41 | 51 | >()("t3code-relay/agentActivity/ApnsDeliveryQueue/ApnsDeliveryQueueSender") {} |
| 42 | 52 | |
| ... | ... | @@ -73,7 +83,17 @@ export const make = Effect.gen(function* () { |
| 73 | 83 | }); |
| 74 | 84 | const now = yield* DateTime.now; |
| 75 | 85 | const jobId = yield* crypto.randomUUIDv4.pipe( |
| 76 | | Effect.mapError((cause) => new ApnsDeliveryQueueSendError({ cause })), |
| 86 | Effect.mapError( |
| 87 | (cause) => |
| 88 | new ApnsDeliveryQueueSendError({ |
| 89 | operation: "generate-job-id", |
| 90 | jobId: null, |
| 91 | kind: input.kind, |
| 92 | userId: input.userId, |
| 93 | deviceId: input.deviceId, |
| 94 | cause, |
| 95 | }), |
| 96 | ), |
| 77 | 97 | ); |
| 78 | 98 | yield* Effect.annotateCurrentSpan({ "relay.delivery.job_id": jobId }); |
| 79 | 99 | const payload = makeApnsDeliveryJobPayload({ |
| ... | ... | @@ -88,7 +108,19 @@ export const make = Effect.gen(function* () { |
| 88 | 108 | secret: config.apnsDeliveryJobSigningSecret, |
| 89 | 109 | payload, |
| 90 | 110 | }); |
| 91 | | yield* sender.send(signed); |
| 111 | yield* sender.send(signed).pipe( |
| 112 | Effect.mapError( |
| 113 | (cause) => |
| 114 | new ApnsDeliveryQueueSendError({ |
| 115 | operation: "send", |
| 116 | jobId, |
| 117 | kind: input.kind, |
| 118 | userId: input.userId, |
| 119 | deviceId: input.deviceId, |
| 120 | cause, |
| 121 | }), |
| 122 | ), |
| 123 | ); |
| 92 | 124 | return { |
| 93 | 125 | deviceId: input.deviceId, |
| 94 | 126 | kind: input.kind, |
| ... | ... | @@ -110,7 +142,17 @@ export const make = Effect.gen(function* () { |
| 110 | 142 | }); |
| 111 | 143 | const now = yield* DateTime.now; |
| 112 | 144 | const jobId = yield* crypto.randomUUIDv4.pipe( |
| 113 | | Effect.mapError((cause) => new ApnsDeliveryQueueSendError({ cause })), |
| 145 | Effect.mapError( |
| 146 | (cause) => |
| 147 | new ApnsDeliveryQueueSendError({ |
| 148 | operation: "generate-job-id", |
| 149 | jobId: null, |
| 150 | kind: "push_notification", |
| 151 | userId: input.userId, |
| 152 | deviceId: input.deviceId, |
| 153 | cause, |
| 154 | }), |
| 155 | ), |
| 114 | 156 | ); |
| 115 | 157 | yield* Effect.annotateCurrentSpan({ "relay.delivery.job_id": jobId }); |
| 116 | 158 | const payload = makeApnsDeliveryJobPayload({ |
| ... | ... | @@ -128,7 +170,19 @@ export const make = Effect.gen(function* () { |
| 128 | 170 | secret: config.apnsDeliveryJobSigningSecret, |
| 129 | 171 | payload, |
| 130 | 172 | }); |
| 131 | | yield* sender.send(signed); |
| 173 | yield* sender.send(signed).pipe( |
| 174 | Effect.mapError( |
| 175 | (cause) => |
| 176 | new ApnsDeliveryQueueSendError({ |
| 177 | operation: "send", |
| 178 | jobId, |
| 179 | kind: "push_notification", |
| 180 | userId: input.userId, |
| 181 | deviceId: input.deviceId, |
| 182 | cause, |
| 183 | }), |
| 184 | ), |
| 185 | ); |
| 132 | 186 | return { |
| 133 | 187 | deviceId: input.deviceId, |
| 134 | 188 | kind: "push_notification" as const, |
| ... | ... | @@ -155,10 +209,9 @@ export const layerCloudflareQueues = ( |
| 155 | 209 | ApnsDeliveryQueueSender, |
| 156 | 210 | ApnsDeliveryQueueSender.of({ |
| 157 | 211 | send: (body) => |
| 158 | | sender.send(body).pipe( |
| 159 | | Effect.mapError((cause) => new ApnsDeliveryQueueSendError({ cause })), |
| 160 | | Effect.provideService(Alchemy.RuntimeContext, alchemyRuntimeContext), |
| 161 | | ), |
| 212 | sender |
| 213 | .send(body) |
| 214 | .pipe(Effect.provideService(Alchemy.RuntimeContext, alchemyRuntimeContext)), |
| 162 | 215 | }), |
| 163 | 216 | ), |
| 164 | 217 | ), |