You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(examples)!: adopt v8 idioms — tag constants, object-pattern narrowing, match folds
- client matchers use exported tag constants and tagPatterns bundles
- ContractError discrimination via the { errorName } object pattern
- workflow error handling via match({ ok, errCases, defect }) with rethrow-on-defect
- fix README link to the examples overview
log.error(`Payment declined for order ${order.orderId}: ${failure.data.reason}`);
167
+
168
+
awaitactivities.sendNotification({
169
+
customerId: order.customerId,
170
+
subject: "Order Failed",
171
+
message: `We're sorry, but your order ${order.orderId} could not be processed. Your payment was declined (${failure.data.reason}).`,
172
+
});
173
+
174
+
// Rethrow as this workflow's own declared contract error: the
175
+
// execution fails with `ApplicationFailure(type: "PaymentDeclined")`
176
+
// and the typed client rehydrates it into a `ContractError`.
177
+
// oxlint-disable-next-line unthrown/no-throw -- sanctioned ApplicationFailure model: `throw context.errors.X(...)` is how a workflow fails terminally with a typed contract error (CLAUDE.md rule 2 exception)
178
+
throwcontext.errors.PaymentDeclined(
179
+
{reason: failure.data.reason},
180
+
{cause: failure},
181
+
);
182
+
})
183
+
// Cancellation rides the modeled Err channel — mapping it to a
184
+
// "failed" order would complete the workflow instead of honoring
185
+
// the cancel. Re-raise it so the execution ends `Cancelled`.
log.error(`Payment activity failed for order ${order.orderId}: ${failure.message}`);
192
+
return{
193
+
orderId: order.orderId,
194
+
status: "failed"asconst,
195
+
failureReason: "Payment could not be processed",
196
+
errorCode: "PAYMENT_UNAVAILABLE",
197
+
};
198
+
}),
151
199
// Unmodeled failure (a bug, not an anticipated outcome) — rethrow at
152
200
// the edge so Temporal surfaces the Workflow Task failure.
153
-
// oxlint-disable-next-line unthrown/no-throw -- defect-cause rethrow at the edge: an unmodeled failure must surface as a Workflow Task failure
154
-
throwpaymentResult.cause;
155
-
}
156
-
constfailure=paymentResult.error;
157
-
158
-
switch(failure._tag){
159
-
case"@temporal-contract/ContractError": {
160
-
// The only declared error on `processPayment` is PaymentDeclined,
161
-
// so `failure.data` is typed `{ reason: string }`.
162
-
log.error(`Payment declined for order ${order.orderId}: ${failure.data.reason}`);
163
-
164
-
awaitactivities.sendNotification({
165
-
customerId: order.customerId,
166
-
subject: "Order Failed",
167
-
message: `We're sorry, but your order ${order.orderId} could not be processed. Your payment was declined (${failure.data.reason}).`,
168
-
});
169
-
170
-
// Rethrow as this workflow's own declared contract error: the
171
-
// execution fails with `ApplicationFailure(type: "PaymentDeclined")`
172
-
// and the typed client rehydrates it into a `ContractError`.
173
-
// oxlint-disable-next-line unthrown/no-throw -- sanctioned ApplicationFailure model: `throw context.errors.X(...)` is how a workflow fails terminally with a typed contract error (CLAUDE.md rule 2 exception)
// Non-critical: the order is already shipped, so even an unmodeled
281
+
// notification failure is only worth a warning.
282
+
defect: (cause)=>{
283
+
log.warn(`Failed to send confirmation notification: ${cause}`);
284
+
},
244
285
});
245
-
}catch(error){
246
-
// Cancellation must propagate — swallowing it here would leave the
247
-
// workflow running after a cancel request.
248
-
if(isCancellation(error)){
249
-
// oxlint-disable-next-line unthrown/no-throw -- cancellation rethrow: swallowing a CancelledFailure would leave the workflow running after a cancel request
250
-
throwerror;
251
-
}
252
-
// Non-critical: log but continue
253
-
log.warn(`Failed to send confirmation notification: ${error}`);
0 commit comments