0796928504
v2-ci / unit-tests (push) Waiting to run
- IScriptRunner.RunBatch: one EvalBatch frame per worker for every evaluation ready to run; per-item, streamed results. The default (InProcessScriptRunner) is RunAsync per item. Used by the Calculation pump (dequeue all, split at a repeated tag, publish in dequeue order), the VirtualTag seam (ScriptBatchCoalescer, no timer) and the scripted-alarm engine (whole dirty set). In process the pump and the engine stay one at a time, unchanged. - Exact per-item deadlines: the worker hands work to an idle evaluation thread or defers it (EvalResults deferred_eval_ids); the host stops that run's clock and restarts T then G when it starts (started_eval_ids). A run queued behind a runaway is neither timed out nor struck and is a victim, not the culprit, at the kill. - Scripted-alarm seam behind Scripting:Runner:Seams; unset Seams now means VirtualTag + Calculation, so alarms run out of process only when listed. Load still compiles each predicate (to PE bytes only) so a broken one fails the load; passes batch and apply in the serial order under the gate. Script faults freeze the condition BadInternalError; runner faults freeze it BadResourceUnavailable and re-evaluate on recovery; a dead worker never clears an alarm. IScriptRunnerProvider carries the runner to DriverHostActor. - Perf harness: batch throughput (RunBatch vs RunAsync x n) and alarm-pass latency (in process / batched / serial); design §12.3 records macOS + windev. On windev the serial out-of-process alarm pass misses 250 ms from ~500 alarms; batched p99 <= 53 ms at 1,000. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
27 lines
1.6 KiB
YAML
27 lines
1.6 KiB
YAML
# docker-dev/docker-compose.script-runner.yml — optional overlay: run the central pair's VirtualTag + Calculation
|
|
# scripts OUT OF PROCESS (lmxopcua#780, Scripting:Runner=OutOfProcess). The scripted-alarm seam stays in process; to
|
|
# move it too (last in the rollout, design §14 #10) add `Scripting__Runner__Seams__2: "ScriptedAlarm"` below.
|
|
#
|
|
# Up (recreates only the two central nodes with the extra env; the image must be built from a branch that has the
|
|
# runner, i.e. `docker compose -f docker-dev/docker-compose.yml build central-1` first):
|
|
# docker compose -f docker-dev/docker-compose.yml -f docker-dev/docker-compose.script-runner.yml up -d --no-deps central-1 central-2
|
|
# Back to InProcess (the default and the rollback): re-run `up -d --no-deps central-1 central-2` with the base file alone.
|
|
#
|
|
# Watch it: `docker exec <node> ps -eo pid,args | grep ScriptWorker` lists the shard workers (they start on the first
|
|
# compiled evaluation, not at boot); `/metrics` on :9000 carries otopcua_script_* (runner state, worker up/inflight,
|
|
# eval duration, compile cache); `/health/ready` carries the `script-runner` entry (Degraded at worst, never 503).
|
|
# PeCacheDir is container-local (/tmp), so a container recreate starts with a cold cache.
|
|
x-script-runner-env: &script-runner-env
|
|
Scripting__Runner: "OutOfProcess"
|
|
Scripting__Runner__Seams__0: "VirtualTag"
|
|
Scripting__Runner__Seams__1: "Calculation"
|
|
Scripting__Worker__PeCacheDir: "/tmp/otopcua-pe-cache"
|
|
|
|
services:
|
|
central-1:
|
|
environment:
|
|
<<: *script-runner-env
|
|
central-2:
|
|
environment:
|
|
<<: *script-runner-env
|