Tester un handler de compensation
Ce test vérifie le contrat entre le SDK et un adaptateur métier de libération de réservation : identifiant, reçu original, clé d'idempotence et résultat. L'adaptateur local conserve une réservation réelle en mémoire pour le test. La création d'une compensation gouvernée par le runtime est décrite dans le guide des compensations.
Installer le SDK
Terminal
touba sdk install javascript
Définir le handler
release.mjs
import {createToolHandler, createToolResult} from '@touba/sdk';
export function releaseHandler(releaseReservation) {
return createToolHandler({
toolRef:'tool:reservations/ReleaseReservation',
inputSignature:[{name:'reservation_id',type_ref:'builtin:Text'}],
outputType:'builtin:Text',
run:async ({request:reservation_id, context}) => {
const response = await releaseReservation({
reservationId:reservation_id,
originalReceipt:context.compensation.original_effect_receipt,
idempotencyKey:context.effect.effect_id,
});
return createToolResult(response.message, {
effectReceipt:context.createEffectReceipt({outcome:'applied',receipt_ref:response.receiptRef}),
compensationReceipt:context.createCompensationReceipt({result:'completed'}),
});
},
});
}
Vérifier les données et l'idempotence métier
Les métadonnées ci-dessous sont des fixtures de test. En exécution, le runtime établit le contexte et vérifie les reçus, l'autorité et les budgets.
exercise.mjs
import assert from 'node:assert/strict';
import {releaseHandler} from './release.mjs';
const reservations = new Set(['RES-42']);
const completed = new Map();
const original = {outcome:'applied', receipt_ref:'reservation:RES-42'};
let writes = 0;
const handler = releaseHandler(async ({reservationId, originalReceipt, idempotencyKey}) => {
assert.equal(reservationId,'RES-42');
assert.deepEqual(originalReceipt,original);
assert.equal(idempotencyKey,'effect:release-42');
if (!completed.has(idempotencyKey)) {
assert.equal(reservations.delete(reservationId),true); writes++;
completed.set(idempotencyKey,{message:'Released',receiptRef:'release:RES-42'});
}
return completed.get(idempotencyKey);
});
const request = {arguments:{reservation_id:'RES-42'},env:{},
compensation:{original_effect_receipt:original}, effect:{effect_id:'effect:release-42'},
createEffectReceipt:value=>value, createCompensationReceipt:value=>value};
await handler(request);
await handler(request);
assert.equal(writes,1); assert.equal(reservations.size,0);
await assert.rejects(handler({...request,arguments:{reservation_id:42}}));
assert.equal(writes,1);
console.log('COMPENSATION_HANDLER_CONTRACT_OK');
Terminal
node exercise.mjs
Résultat : COMPENSATION_HANDLER_CONTRACT_OK. Dans votre application,
remplacez l'adaptateur par celui du fournisseur et persistez ses clés
d'idempotence. Ce test de callback complète les tests de compensation runtime.