Make seconv conversion cancellation-aware and serialize global state - #109
Make seconv conversion cancellation-aware and serialize global state#109Blackspirits wants to merge 7 commits into
Conversation
Blackspirits
left a comment
There was a problem hiding this comment.
Independent adversarial re-check: conversion remains backwards-compatible through an optional CancellationToken, the CLI now forwards its token, caller cancellation is rethrown through every converter error boundary, and conversion runs are serialized while libse/seconv still mutate process-global settings. Cancellation around synchronous legacy/native work is cooperative rather than pre-emptive, which is documented in the PR. Full CI #34788562083 passed restore, build and the complete solution suite on the first run; SeConvTests reported 476 passed, 2 skipped and 0 failed, and UITests 5,151 passed, 9 skipped and 0 failed. Retry was not used. No blocker identified. Keep draft; no merge performed.
Blackspirits
left a comment
There was a problem hiding this comment.
Final adversarial re-check on f83e307: cancellation is propagated through the converter and caller cancellation escapes every conversion error boundary. The final correction also avoids checking for cancellation after a completed synchronous write/extraction, so an already-produced output is not reported as cancelled and accidentally retried. CI #34791238162 passed restore/build. SeConvTests (476/2/0), LibUiLogicTests (873/0/0) and LibSETests (2008/0/0) passed on the first run. The first UITests run had one failure in NativeKeymapShiftDeleteCutTests.Delete_WithoutShift_StillJustDeletes_InTheSyntaxTextEditor, a UI/keymap test outside all three changed seconv files; the fresh-process retry passed UITests 5151/9/0 and the entire suite. This is consistent with an unrelated UI flake, not a #109 regression. No blocker identified. Keep draft; no merge performed.
Summary
This is prerequisite hardening for long-lived/concurrent callers such as the proposed
seconv mcpserver.SubtitleConvertercurrently mutates process-wide state during a run:Configuration.Settings.General.CurrentFrameRatewhile loading frame-based formats;SpellCheckConfigdelegates for Fix Common Errors/OCR;AutoTranslateRunner.A CLI invocation normally has only one conversion, but a long-lived server can invoke multiple converters concurrently and cross-contaminate those globals.
The converter also had no effective cancellation contract: Spectre passes a
CancellationTokentoConvertCommand, but the command discarded it, and translation was explicitly invoked withCancellationToken.None.This change:
SubtitleConverterruns behind a process-wide async gate while conversion still depends on mutable global libse state;CancellationTokentoConvertAsyncwithout breaking existing callers;Task.Run, and auto-translation;Scope / limitation
Cancellation is cooperative. Synchronous legacy/native helpers without a token cannot be pre-empted inside the call; cancellation is observed before those stages and between work units. A completed synchronous write is not retroactively reported as cancelled, avoiding retry ambiguity after side effects already exist. The serialization gate is intentionally conservative until the remaining process-global settings become per-conversion state.
Validation
c77c4b428649ce7030e6cf218b4d7c384b955232SubtitleConverter.cs,ConvertCommand.cs, one focused cancellation testf83e30793665214f054f411feb0c2254b8b68d8aNativeKeymapShiftDeleteCutTests.Delete_WithoutShift_StillJustDeletes_InTheSyntaxTextEditorAI assistance: ChatGPT was used to audit seconv cancellation propagation and concurrency hazards exposed by long-lived MCP callers.