blob: 2094207bbe064f0b0c580146c41cb3498205782f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# `write_report` commits the two artifacts non-atomically
**Origin:** split out of PR #3840, surfaced by its second review round. Delete this file
when its own PR lands.
```python
md = render_report(doc) + '\n'
report_dir.mkdir(parents=True, exist_ok=True)
(report_dir / REPORT_JSON).write_text(json.dumps(doc, indent=2) + '\n')
(report_dir / REPORT_MD).write_text(md, encoding='utf-8')
```
Rendering before writing closed the *render-failure* case: a raise can no longer commit a
sidecar the markdown contradicts. It does not close the *interrupted-between-writes* case. A
kill between those two lines leaves the pair disagreeing — and this runs on the containment
path, on the way to `os._exit`, on a rig whose jobs get cancelled by the GitHub job ceiling.
**What remains:** write both to temp files, then `os.replace` both. The window shrinks from
two full writes to two renames, and neither file is ever observed half-written. `os.replace`
is atomic per file on POSIX; the pair is still not transactional, which is acceptable and
should be said in the docstring rather than implied away.
Worth pairing with a test that kills between the writes — or, more practically, one that
asserts no partial file is ever visible by checking the temp-then-rename shape directly.
## Why it was split out
A durability edge, not a wrong verdict. PR #3840 closed the render-failure half of this
(nothing is written until the markdown renders); the interrupted-between-writes half needs
a temp-then-rename and is better reviewed on its own.
|