All files / core/blong-gogo/src/orchestrator/common dispatch.ts

100% Statements 56/56
100% Branches 12/12
100% Functions 4/4
100% Lines 56/56

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 571x 1x 1x 1x 1x 97x 97x 97x 97x 97x 97x 97x 6x 6x 97x 365x 365x 365x 365x 365x 365x 365x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 361x 335x 361x 361x 361x 365x 97x  
import {orchestrator, type IMeta} from '@feasibleone/blong/types';
import {legName, recordedCall} from '../../lib.ts';
import {declareCall, namespaceOf} from '../../semanticContext.ts';
 
export default orchestrator<{destination?: string; appendNamespace?: string}>(({remote}) => ({
    activation: {
        default: {
            type: 'dispatch',
        },
    },
    start() {
        super.connect();
        return super.start();
    },
    async exec(...params: unknown[]) {
        // Support both `destination` (slash-based routing, auto-stripped by methodPath)
        // and `appendNamespace` (dot-based prefix, stripped via stripNamespace on receiver).
        const destination = this.config.destination;
        const appendNamespace = this.config.appendNamespace;
        const prefix = destination ?? appendNamespace;
        const separator = destination ? '/' : '.';
        if (prefix && params.length > 1) {
            const $meta = params.pop() as IMeta;
            if ($meta?.method) {
                const forwarded = prefix + separator + $meta.method;
                // The hop this orchestrator makes is a call of the flow like any other, so
                // it is declared and recorded exactly as a proxied call is. Both halves are
                // needed: the declaration names the call, and the record is the evidence the
                // ledger reads. A leg nobody wrote a record inside is one it only ever hears
                // about from the callee's receipt, and the diagram then says so ("received,
                // no caller was observed") instead of drawing the arrow.
                //
                // The caller is the namespace this orchestrator answers for, not the process:
                // the dispatcher is shared by every namespace that has one, so the process
                // name would credit the hop to whichever namespace happened to be served
                // alongside it.
                //
                // The leg is spelled as every other leg is, `<caller>.<target>.<method>`:
                // slash routing is the wire form only, and a `/` in an id is flattened to `-`
                // by the leg grammar, which would hide the target the arrow names.
                const declared = legName(forwarded);
                const forward = async (): Promise<unknown[] | undefined> =>
                    (await recordedCall(this, declared, () =>
                        remote.dispatch(...params, {...$meta, method: forwarded}),
                    )) as unknown[] | undefined;
                const dispatched = await declareCall(
                    namespaceOf($meta.method),
                    declared,
                    forward,
                    $meta,
                );
                return dispatched?.[0];
            }
        }
    },
}));