Fix the resource release after a timeout
Your task
A Python job runs under asyncio.wait_for with a 5 second timeout, and a finally block releases its temp resource. On a timeout the job is cancelled, but cancellation only lands at the job's next await. So finally can release the resource while the job is still writing to it. The safe version waits for the job's own cleanup before it releases, using asyncio.shield to protect that wait.
An assistant wrote finalize_jobs(event_lines, shield_cleanup), which replays the lifecycle events and logs each release. It is in the editor. It has a bug. Find it and fix it.
Input and output:
event_lines: the events in order, eachop|job. The ops areacquire,cancel,cleanup_done(the job's own cleanup has finished) andrelease.shield_cleanup: true when a release waits for a cancelled job's cleanup.- Return the log in event order. Each entry is
released:<job>orunsafe_release:<job>.
Rules the tests check:
- Split a line on
|. Skip it unless it has exactly 2 parts and the job is not empty. Skip any other op. - Each job is in one of four states: not acquired, held, drained or released. Every job starts not acquired.
acquire: a job that is not acquired becomes held, and not cancelled. In any other state, nothing happens.cancel: a held job is marked cancelled. In any other state, nothing happens.cleanup_done: a held job becomes drained. If a release is waiting for it, the job becomes released at once and you logreleased:<job>. In any other state, nothing happens.releaseon a held job that is not cancelled: it becomes released. Logreleased:<job>.releaseon a held, cancelled job whenshield_cleanupis true: log nothing. The release waits for the job'scleanup_done.releaseon a held, cancelled job whenshield_cleanupis false: it becomes released at once. Logunsafe_release:<job>.releaseon a drained job: it becomes released. Logreleased:<job>.releaseon a job that is not acquired or already released: nothing happens.
Examples
finalize_jobs(event_lines: list[str], shield_cleanup: bool) -> list[str]Example 1
Input
finalize_jobs(["acquire|j1", "cleanup_done|j1", "release|j1"], True)Output
["released:j1"]Example 2
Input
finalize_jobs(["acquire|j1", "cancel|j1", "release|j1", "cleanup_done|j1"], True)Output
["released:j1"]Example 3
Input
finalize_jobs(["acquire|j1", "cancel|j1", "release|j1", "cleanup_done|j1"], False)Output
["unsafe_release:j1"]