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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Deleting day files older than the retention window.
//!
//! Why: DOC-73 §4.3 calls for a "day-rotated NDJSON log, rotated and
//! retained" — without a bound, an idle console accumulates one file per day
//! forever. This module is the bound: applied once at [`super::DurableLog::
//! open`] (in case files piled up while console was down) and again on every
//! rotation.
//! What: [`files_to_delete`] is the pure decision (testable without a
//! filesystem): given the retained day files and today's date, which ones
//! fall outside `retain_days`. [`enforce_retention`] lists, decides, and
//! deletes, then returns the survivors sorted ascending — the caller (the
//! writer task) uses that to recompute [`super::recovery::earliest_seq`]
//! without a second directory listing.
//! Test: `super::tests::files_to_delete_keeps_exactly_retain_days`,
//! `super::tests::files_to_delete_keeps_everything_within_the_window`,
//! `super::tests::enforce_retention_deletes_only_the_expired_files`.
use Path;
use ;
use LogError;
use ;
/// Which of `files` fall outside the most recent `retain_days` calendar days
/// counting back from `today` (inclusive of `today`).
///
/// `retain_days == 0` is treated as `1` — a retention window of zero would
/// delete every file including the one still being written, which is never
/// the intent of a caller passing zero (most likely a misconfigured value,
/// not "keep nothing").
///
/// Test: `super::tests::files_to_delete_keeps_exactly_retain_days`,
/// `super::tests::files_to_delete_keeps_everything_within_the_window`.
pub
/// List `dir`, delete every file [`files_to_delete`] names, and return the
/// survivors sorted ascending by date.
///
/// # Errors
///
/// [`LogError::Io`] if the directory cannot be listed, or a file that
/// [`files_to_delete`] named cannot be removed. A file already gone by the
/// time the delete runs (`NotFound`) is not an error — another retention pass
/// or an operator could have removed it first, and the end state is what this
/// function is asked to guarantee.
///
/// Test: `super::tests::enforce_retention_deletes_only_the_expired_files`.
pub async