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

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

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 57 581x 1x 1x 1x 1x 81x 81x 81x 81x 81x 81x 81x 6x 6x 81x 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 361x 335x 361x 361x 361x 365x 81x  
import {orchestrator, type IMeta} from '@feasibleone/blong/types';
import {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 the method the forwarded call reaches its destination with — the
                // wire name, slash and all (`db/gateway.bundle.find`): that is the method the
                // callee strips back to, and a label that dotted it would no longer be the name
                // the call was made by. Who made it is stated beside the method, not inside it.
                const declared = 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];
            }
        }
    },
}));