/** * Which engine runs a config, and why. * * The router behind `mode="disk"` — the default — and the reason it gives for * its choice, which `check` prints and a run repeats when an engine asked for by * name hands the config to another. Kept apart from the renderer that consults * it: the reasons are read by people, and the rules are the part every * implementation has to agree on. */ import type { SequenceSpec } from '../sequence/index.js'; import type { EngineId, EngineSelection } from './render.js'; /** * The engine a run uses, and why — for `check`, and for the note a run prints * when an engine asked for by name hands the config to another. */ export interface EngineChoice { readonly engine: EngineId; readonly why: string; /** Engine 3 was asked for and engine 1 runs the config instead. */ readonly downgraded?: boolean; } /** How each engine is named next to its number. */ export declare const ENGINE_LABELS: Readonly>; /** Resolve a selection to a concrete engine, routing `disk` mode by config. */ export declare function resolveRenderEngine(selection: EngineSelection, specs: readonly SequenceSpec[], envUniqGroups: readonly (readonly string[])[]): EngineId; /** * The engine a selection resolves to, and the reason in words. * * Engine 3 asked for by name runs a config the disk route sends to engine 1 on * engine 1, and says so. It always did that, silently, at the last moment — the * lazy build refused and the in-memory engine took over — which left nothing * for `check` to report and, past the row count where a run splits itself into * threads, handed each worker a refusal it had no way to take over from: three * of the five implementations exited 1 there. Deciding it here, before the run, * is the same answer every implementation can give. */ export declare function explainRenderEngine(selection: EngineSelection, specs: readonly SequenceSpec[], envUniqGroups: readonly (readonly string[])[]): EngineChoice; /** One line for `check`: the engine, its name, and the reason. */ export declare function describeEngineChoice(choice: EngineChoice): string; /** Any `` — the network-backed generator. */ export declare function specsUseHttp(specs: readonly SequenceSpec[]): boolean; /** * True if any sequence is a column DERIVED from another column. * * `running`, `stat` and a date offset are built in declaration order out of * columns that already exist, and the streaming builder refuses each by name. * * `formula` is NOT in this list, and the difference is the whole point: it reads * only its OWN row, so it streams — see the formula case in `stream-build.ts`. * `running` needs every row before this one and `stat` needs every row at all, * which is not a gap in the streaming builder but what those two constructs * mean. A date offset needs only its own row too and could join `formula` once * its instant-column bookkeeping is taught to resolve lazily. Before this existed the refusal was left to the build, * which worked single-threaded — the auto-routed disk mode caught it and fell * back to the in-memory engine — and then died above the row count where the * run goes parallel, because each worker gets a FORCED streaming engine with * nowhere to fall back to. The message it printed was the worst part: "run * without a forced streaming engine", to a user who had forced nothing. * * Measured on 0.2.1, before this line: a 200,000-row config with `running`, * with `stat`, with ``, and with `formula` all produced a * full file at 5,000 rows and exited 1 at 200,000. Three of those four are * SHIPPED features. * * So the decision moves here, where it is static and both paths see the same * answer — exactly the reasoning `specsUseUnstreamableSwitchPercent` already * carries, applied to the case it did not cover. */ export declare function specsUseDerivedColumn(specs: readonly SequenceSpec[]): boolean; /** * Any sequence whose `parent=` names a sequence but not one of its VALUES. * * `parent="Country.US"` is a filter the streaming engines can evaluate a row at a * time: the row either drew `US` or it did not. `parent="Country"` asks a different * question — "the rows where Country produced anything at all" — and answering it * needs the parent's finished column, which is exactly what streaming does not have. * The condition is kept identical to `domainOf` in `sequence/stream-build.ts`, which * is the code that would otherwise refuse it mid-run. */ export declare function specsUseBareParent(specs: readonly SequenceSpec[]): boolean; /** * True if the config needs Engine 3 rather than Engine 2 for disk mode — i.e. * it uses something Engine 2 can't do lazily: ANY `uniq`, a parent-child whose * parent isn't a finite text sequence, or an `advanced_regex` weighted choice * `(?%{…})` (exact percentages need the whole column). Everything else (exact * %, switch, distinct, text parent-child) streams fine on Engine 2. * * `uniq` is here in full, and that is a deliberate cost. A group REARRANGES the * columns it covers — every column keeps its multiset, so every declared share * survives — and that cannot be decided a row at a time. Engine 2 could only * offer a different answer: a mixed-radix bijection over the whole combination * space, which is uniform over combinations and discards the values actually * drawn. Two engines, two datasets from one seed. Sending uniq to Engine 3 * costs a uniq config the lazy path and buys back one answer everywhere. */ export declare function needsExactEngine(specs: readonly SequenceSpec[], envUniqGroups: readonly (readonly string[])[]): boolean; //# sourceMappingURL=engine-route.d.ts.map