Phase 7 Stream A.2 — compile cache + per-evaluation timeout wrapper #178
Reference in New Issue
Block a user
Delete Branch "phase-7-stream-a2-cache-timeout"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Second of 3 increments within Stream A. Two independent resilience primitives that Streams B + C will compose with the base
ScriptEvaluator.CompiledScriptCache<TContext, TResult>ConcurrentDictionary<string, Lazy<ScriptEvaluator>>withExecutionAndPublicationmode — concurrent callers never double-compileCount/Clear/Containsexposed for diagnostics + testsTimedScriptEvaluator<TContext, TResult>ScriptRunnerexecutes synchronously on the calling thread for CPU-bound scripts, returning an already-completed Task before the caller can register a timeout. Fix: push evaluation throughTask.Runso the caller's thread is free to wait and the timeout reliably fires.CancellationTokentakes precedence over timeout so shutdown paths seeOperationCanceledExceptionrather than a misclassifiedScriptTimeoutExceptionScriptTimeoutExceptioncarries the configured timeout and diagnostic message pointing the operator atctx.Loggeroutput + tuning pathsTests — 48/48 green (29 from A.1 + 19 new)
CompiledScriptCacheTests(10) — first compile, dedupe, different-source, whitespace sensitivity, cached evaluator still runs, failed compile eviction, Clear, concurrent compile dedupe, separate TContext/TResult cache isolation, null rejectionTimedScriptEvaluatorTests(9) — fast completes, CPU-bound throws ScriptTimeoutException, caller cancel > timeout precedence, default 250ms per plan, zero/negative timeout rejected, null rejections, user exceptions unwrapped, diagnostic message shapeNext
Stream A.3 closes out Stream A: dedicated
scripts-*.logSerilog rolling sink with structured-property filtering + companion-WARN enricher to the main log.