Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 27x 27x 27x 27x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 67x 1x 1x 1x 66x 66x 66x 67x 67x 67x 67x 27x | /**
* FX provider.
*
* Declines a rate above its own limit and records why — the decision a real
* provider makes on every request. The branch rationale is recorded whichever
* way it goes, so F5 can show *which* branch was taken rather than only that
* the quote failed.
*
* The status is set on the reply explicitly; a returned `{status, body}` object
* would be answered with HTTP 200 by fastify and the decline would never leave
* this participant (see `payer.ts` for the full note).
*/
import {decide} from '../src/decide.ts';
import type {Participant} from './participant.ts';
export interface FxpOptions {
rate?: number;
rateLimit?: number;
/** Decline every rate, so the caller can exercise the refusal branch (fault F5). */
declineAll?: boolean;
}
export function installFxp(participant: Participant, options: FxpOptions = {}): void {
const rate = options.rate ?? 1.1;
const rateLimit = options.rateLimit ?? 1.15;
participant.app.post('/quotes', async (request, reply) => {
const traceId = participant.traceFrom(request);
const flowId = participant.flowFrom(request);
const leg = participant.legFrom(request);
const result = await participant.run(traceId, flowId, leg, () =>
participant.phase('quote', async () => {
const accepted = decide('rate-within-limit', {rate, rateLimit}, [
{
name: 'decline',
when: values =>
options.declineAll === true ||
(values.rate as number) > (values.rateLimit as number),
run: () => false,
},
{name: 'accept', when: () => true, run: () => true},
]);
if (!accepted) {
participant.logger.warn('rate declined', {rate, rateLimit});
return {status: 409, body: {reason: 'rate above provider limit'}};
}
participant.logger.info('rate published', {rate, condition: 'sha256:condition'});
return {status: 200, body: {rate, condition: 'sha256:condition'}};
}),
);
reply.status(result.status);
return result.body;
});
}
|