Skip to main content

FreshnessTracker

Struct FreshnessTracker 

Source
pub struct FreshnessTracker { /* private fields */ }

Implementations§

Source§

impl FreshnessTracker

Source

pub fn new(cache_dir: PathBuf, root: &str, threshold: Option<usize>) -> Self

Production S1 freshness: immutable base plus cumulative delta.

Examples found in repository?
examples/p6_scale.rs (line 58)
44fn main() {
45    let args: Vec<String> = std::env::args().collect();
46    if args.len() < 4 || !matches!(args[1].as_str(), "snapshot" | "delta") {
47        eprintln!("usage: p6_scale <snapshot|delta> <corpus> <cache-dir> [iterations]");
48        std::process::exit(2);
49    }
50    let mode = &args[1];
51    let root = PathBuf::from(&args[2]);
52    let cache = PathBuf::from(&args[3]);
53    let iterations: usize = args.get(4).and_then(|v| v.parse().ok()).unwrap_or(7);
54    let root_text = root.to_string_lossy().into_owned();
55    let file_count = rac_engine::walk::find_markdown_files(&root_text, true).len();
56    let threshold = file_count.saturating_add(iterations).saturating_add(10);
57    let mut tracker = if mode == "delta" {
58        FreshnessTracker::new(cache.clone(), &root_text, Some(threshold))
59    } else {
60        FreshnessTracker::new_snapshot(cache.clone(), &root_text, Some(threshold))
61    };
62
63    let cold_ms = timed_read(&mut tracker, true);
64    let warm_ms: Vec<f64> = (0..iterations)
65        .map(|_| timed_read(&mut tracker, false))
66        .collect();
67
68    let target = first_markdown(&root);
69    let original = fs::read(&target).expect("read mutation target");
70    let mut edited = original.clone();
71    edited.extend_from_slice(b"\n<!-- p6-scale-edit -->\n");
72    let mut edit_ms = Vec::new();
73    for _ in 0..iterations {
74        fs::write(&target, &edited).expect("write edit");
75        edit_ms.push(timed_read(&mut tracker, true));
76        fs::write(&target, &original).expect("restore edit");
77        timed_read(&mut tracker, true);
78    }
79
80    let added = root.join("p6-scale-added.md");
81    let added_text = "---\nschema_version: 1\nid: RAC-Z9SCAE000001\ntype: decision\n---\n# Scale Probe\n\n## Context\n\nBenchmark.\n\n## Decision\n\nMeasure.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n";
82    let mut add_ms = Vec::new();
83    let mut delete_ms = Vec::new();
84    for _ in 0..iterations {
85        fs::write(&added, added_text).expect("write added probe");
86        add_ms.push(timed_read(&mut tracker, true));
87        fs::remove_file(&added).expect("remove added probe");
88        delete_ms.push(timed_read(&mut tracker, true));
89    }
90
91    let renamed = target.with_extension("p6-scale-renamed.md");
92    let mut rename_ms = Vec::new();
93    for _ in 0..iterations {
94        fs::rename(&target, &renamed).expect("rename probe");
95        rename_ms.push(timed_read(&mut tracker, true));
96        fs::rename(&renamed, &target).expect("restore rename probe");
97        timed_read(&mut tracker, true);
98    }
99
100    let mut compact_tracker = if mode == "delta" {
101        FreshnessTracker::new(cache.join("compact"), &root_text, Some(1))
102    } else {
103        FreshnessTracker::new_snapshot(cache.join("compact"), &root_text, Some(1))
104    };
105    timed_read(&mut compact_tracker, true);
106    fs::write(&target, &edited).expect("write compaction edit");
107    let compact_ms = timed_read(&mut compact_tracker, true);
108    fs::write(&target, &original).expect("restore compaction edit");
109
110    let summary = json!({
111        "warm": distribution(&warm_ms),
112        "edit": distribution(&edit_ms),
113        "add": distribution(&add_ms),
114        "delete": distribution(&delete_ms),
115        "rename": distribution(&rename_ms),
116    });
117    let output: Value = json!({
118        "schema_version": "1",
119        "mode": mode,
120        "corpus": root_text,
121        "files": file_count,
122        "iterations": iterations,
123        "cold_ms": cold_ms,
124        "warm_ms": warm_ms,
125        "edit_ms": edit_ms,
126        "add_ms": add_ms,
127        "delete_ms": delete_ms,
128        "rename_ms": rename_ms,
129        "compact_ms": compact_ms,
130        "summary": summary,
131        "last_parse_files": tracker.last_parse_files(),
132        "delta_size": tracker.delta_size(),
133    });
134    println!("{}", serde_json::to_string_pretty(&output).unwrap());
135}
More examples
Hide additional examples
examples/p6_soak.rs (lines 121-125)
102fn main() {
103    let args: Vec<String> = std::env::args().collect();
104    if args.len() < 3 {
105        eprintln!("usage: p6_soak <corpus> <cache-root> [rounds]");
106        std::process::exit(2);
107    }
108    let corpus = PathBuf::from(&args[1]);
109    let cache_root = PathBuf::from(&args[2]);
110    let rounds: usize = args
111        .get(3)
112        .and_then(|value| value.parse().ok())
113        .unwrap_or(3);
114    let root = corpus.to_string_lossy().into_owned();
115    let mutation_cache = cache_root.join("mutation");
116    let referee_root = cache_root.join("referees");
117    let _ = fs::remove_dir_all(&cache_root);
118    fs::create_dir_all(&cache_root).expect("create soak cache");
119    assert_valid(&root);
120
121    let mut tracker = FreshnessTracker::new(
122        mutation_cache.clone(),
123        &root,
124        Some(rounds.saturating_mul(16).saturating_add(100)),
125    );
126    certify_generation(
127        &mut tracker,
128        true,
129        &root,
130        &mutation_cache,
131        &referee_root,
132        "cold",
133    );
134    let mut warm_reads = 0;
135    for _ in 0..100 {
136        tracker.read_model(false);
137        warm_reads += 1;
138    }
139
140    let target = first_markdown(&corpus);
141    let original = fs::read(&target).expect("read mutation target");
142    let mut transitions = 0;
143    for round in 0..rounds {
144        let mut edited = original.clone();
145        edited.extend_from_slice(format!("\n<!-- p6-soak-{round} -->\n").as_bytes());
146        fs::write(&target, &edited).expect("write edit");
147        certify_generation(
148            &mut tracker,
149            true,
150            &root,
151            &mutation_cache,
152            &referee_root,
153            &format!("round-{round}-edit"),
154        );
155        assert_eq!(tracker.last_parse_files(), 1);
156        transitions += 1;
157
158        fs::write(&target, &original).expect("restore edit");
159        certify_generation(
160            &mut tracker,
161            true,
162            &root,
163            &mutation_cache,
164            &referee_root,
165            &format!("round-{round}-restore"),
166        );
167        assert_eq!(tracker.last_parse_files(), 1);
168        transitions += 1;
169
170        let added = corpus.join(format!("p6-soak-added-{round}.md"));
171        let added_text = format!(
172            "---\nschema_version: 1\nid: RAC-Z9SCAE{round:06}\ntype: decision\n---\n# Soak {round}\n\n## Context\n\nBounded soak.\n\n## Decision\n\nCertify.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n"
173        );
174        fs::write(&added, added_text).expect("write added artifact");
175        certify_generation(
176            &mut tracker,
177            true,
178            &root,
179            &mutation_cache,
180            &referee_root,
181            &format!("round-{round}-add"),
182        );
183        assert_eq!(tracker.last_parse_files(), 1);
184        transitions += 1;
185
186        fs::remove_file(&added).expect("delete added artifact");
187        certify_generation(
188            &mut tracker,
189            true,
190            &root,
191            &mutation_cache,
192            &referee_root,
193            &format!("round-{round}-delete"),
194        );
195        assert_eq!(tracker.last_parse_files(), 0);
196        transitions += 1;
197
198        let renamed = target.with_extension(format!("soak-{round}.md"));
199        fs::rename(&target, &renamed).expect("rename target");
200        certify_generation(
201            &mut tracker,
202            true,
203            &root,
204            &mutation_cache,
205            &referee_root,
206            &format!("round-{round}-rename"),
207        );
208        assert_eq!(tracker.last_parse_files(), 1);
209        transitions += 1;
210        fs::rename(&renamed, &target).expect("restore target name");
211        certify_generation(
212            &mut tracker,
213            true,
214            &root,
215            &mutation_cache,
216            &referee_root,
217            &format!("round-{round}-rename-back"),
218        );
219        assert_eq!(tracker.last_parse_files(), 1);
220        transitions += 1;
221    }
222
223    let compaction_cache = cache_root.join("compaction");
224    let compaction_referees = cache_root.join("compaction-referees");
225    let mut compact = FreshnessTracker::new(compaction_cache.clone(), &root, Some(1));
226    certify_generation(
227        &mut compact,
228        true,
229        &root,
230        &compaction_cache,
231        &compaction_referees,
232        "compact-cold",
233    );
234    let mut edited = original.clone();
235    edited.extend_from_slice(b"\n<!-- p6-soak-compaction -->\n");
236    fs::write(&target, &edited).expect("write compaction edit");
237    certify_generation(
238        &mut compact,
239        true,
240        &root,
241        &compaction_cache,
242        &compaction_referees,
243        "compact-edit",
244    );
245    assert_eq!(compact.last_parse_files(), 1);
246    assert_eq!(compact.delta_size(), 0);
247    fs::write(&target, &original).expect("write first post-compaction edit");
248    certify_generation(
249        &mut compact,
250        true,
251        &root,
252        &compaction_cache,
253        &compaction_referees,
254        "compact-post-edit",
255    );
256    assert_eq!(compact.last_parse_files(), 1);
257    assert_eq!(compact.delta_size(), 0);
258    assert_valid(&root);
259
260    println!(
261        "{}",
262        serde_json::to_string_pretty(&json!({
263            "schema_version": "1",
264            "files": rac_engine::walk::find_markdown_files(&root, true).len(),
265            "rounds": rounds,
266            "warm_reads": warm_reads,
267            "certified_transitions": transitions + 3,
268            "valid": true,
269            "deterministic": true,
270            "fresh": true,
271            "cache_no_cache_equal": true,
272            "persisted_segments_byte_equal": true,
273            "post_compaction_parse_files": compact.last_parse_files(),
274        }))
275        .unwrap()
276    );
277}
Source

pub fn new_snapshot( cache_dir: PathBuf, root: &str, threshold: Option<usize>, ) -> Self

Explicit rollback path retained for the first S1 soak release.

Examples found in repository?
examples/p6_scale.rs (line 60)
44fn main() {
45    let args: Vec<String> = std::env::args().collect();
46    if args.len() < 4 || !matches!(args[1].as_str(), "snapshot" | "delta") {
47        eprintln!("usage: p6_scale <snapshot|delta> <corpus> <cache-dir> [iterations]");
48        std::process::exit(2);
49    }
50    let mode = &args[1];
51    let root = PathBuf::from(&args[2]);
52    let cache = PathBuf::from(&args[3]);
53    let iterations: usize = args.get(4).and_then(|v| v.parse().ok()).unwrap_or(7);
54    let root_text = root.to_string_lossy().into_owned();
55    let file_count = rac_engine::walk::find_markdown_files(&root_text, true).len();
56    let threshold = file_count.saturating_add(iterations).saturating_add(10);
57    let mut tracker = if mode == "delta" {
58        FreshnessTracker::new(cache.clone(), &root_text, Some(threshold))
59    } else {
60        FreshnessTracker::new_snapshot(cache.clone(), &root_text, Some(threshold))
61    };
62
63    let cold_ms = timed_read(&mut tracker, true);
64    let warm_ms: Vec<f64> = (0..iterations)
65        .map(|_| timed_read(&mut tracker, false))
66        .collect();
67
68    let target = first_markdown(&root);
69    let original = fs::read(&target).expect("read mutation target");
70    let mut edited = original.clone();
71    edited.extend_from_slice(b"\n<!-- p6-scale-edit -->\n");
72    let mut edit_ms = Vec::new();
73    for _ in 0..iterations {
74        fs::write(&target, &edited).expect("write edit");
75        edit_ms.push(timed_read(&mut tracker, true));
76        fs::write(&target, &original).expect("restore edit");
77        timed_read(&mut tracker, true);
78    }
79
80    let added = root.join("p6-scale-added.md");
81    let added_text = "---\nschema_version: 1\nid: RAC-Z9SCAE000001\ntype: decision\n---\n# Scale Probe\n\n## Context\n\nBenchmark.\n\n## Decision\n\nMeasure.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n";
82    let mut add_ms = Vec::new();
83    let mut delete_ms = Vec::new();
84    for _ in 0..iterations {
85        fs::write(&added, added_text).expect("write added probe");
86        add_ms.push(timed_read(&mut tracker, true));
87        fs::remove_file(&added).expect("remove added probe");
88        delete_ms.push(timed_read(&mut tracker, true));
89    }
90
91    let renamed = target.with_extension("p6-scale-renamed.md");
92    let mut rename_ms = Vec::new();
93    for _ in 0..iterations {
94        fs::rename(&target, &renamed).expect("rename probe");
95        rename_ms.push(timed_read(&mut tracker, true));
96        fs::rename(&renamed, &target).expect("restore rename probe");
97        timed_read(&mut tracker, true);
98    }
99
100    let mut compact_tracker = if mode == "delta" {
101        FreshnessTracker::new(cache.join("compact"), &root_text, Some(1))
102    } else {
103        FreshnessTracker::new_snapshot(cache.join("compact"), &root_text, Some(1))
104    };
105    timed_read(&mut compact_tracker, true);
106    fs::write(&target, &edited).expect("write compaction edit");
107    let compact_ms = timed_read(&mut compact_tracker, true);
108    fs::write(&target, &original).expect("restore compaction edit");
109
110    let summary = json!({
111        "warm": distribution(&warm_ms),
112        "edit": distribution(&edit_ms),
113        "add": distribution(&add_ms),
114        "delete": distribution(&delete_ms),
115        "rename": distribution(&rename_ms),
116    });
117    let output: Value = json!({
118        "schema_version": "1",
119        "mode": mode,
120        "corpus": root_text,
121        "files": file_count,
122        "iterations": iterations,
123        "cold_ms": cold_ms,
124        "warm_ms": warm_ms,
125        "edit_ms": edit_ms,
126        "add_ms": add_ms,
127        "delete_ms": delete_ms,
128        "rename_ms": rename_ms,
129        "compact_ms": compact_ms,
130        "summary": summary,
131        "last_parse_files": tracker.last_parse_files(),
132        "delta_size": tracker.delta_size(),
133    });
134    println!("{}", serde_json::to_string_pretty(&output).unwrap());
135}
Source

pub fn new_stat( cache_dir: PathBuf, root: &str, threshold: Option<usize>, ) -> Self

Force the authoritative stat rung. Used by fallback/parity tests and remains the behavior on platforms without a synchronous watcher.

Source

pub fn mode(&self) -> &'static str

Source

pub fn base_generation(&self) -> u64

Source

pub fn serving_generation(&self) -> u64

Source

pub fn delta_size(&self) -> usize

Examples found in repository?
examples/p6_scale.rs (line 132)
44fn main() {
45    let args: Vec<String> = std::env::args().collect();
46    if args.len() < 4 || !matches!(args[1].as_str(), "snapshot" | "delta") {
47        eprintln!("usage: p6_scale <snapshot|delta> <corpus> <cache-dir> [iterations]");
48        std::process::exit(2);
49    }
50    let mode = &args[1];
51    let root = PathBuf::from(&args[2]);
52    let cache = PathBuf::from(&args[3]);
53    let iterations: usize = args.get(4).and_then(|v| v.parse().ok()).unwrap_or(7);
54    let root_text = root.to_string_lossy().into_owned();
55    let file_count = rac_engine::walk::find_markdown_files(&root_text, true).len();
56    let threshold = file_count.saturating_add(iterations).saturating_add(10);
57    let mut tracker = if mode == "delta" {
58        FreshnessTracker::new(cache.clone(), &root_text, Some(threshold))
59    } else {
60        FreshnessTracker::new_snapshot(cache.clone(), &root_text, Some(threshold))
61    };
62
63    let cold_ms = timed_read(&mut tracker, true);
64    let warm_ms: Vec<f64> = (0..iterations)
65        .map(|_| timed_read(&mut tracker, false))
66        .collect();
67
68    let target = first_markdown(&root);
69    let original = fs::read(&target).expect("read mutation target");
70    let mut edited = original.clone();
71    edited.extend_from_slice(b"\n<!-- p6-scale-edit -->\n");
72    let mut edit_ms = Vec::new();
73    for _ in 0..iterations {
74        fs::write(&target, &edited).expect("write edit");
75        edit_ms.push(timed_read(&mut tracker, true));
76        fs::write(&target, &original).expect("restore edit");
77        timed_read(&mut tracker, true);
78    }
79
80    let added = root.join("p6-scale-added.md");
81    let added_text = "---\nschema_version: 1\nid: RAC-Z9SCAE000001\ntype: decision\n---\n# Scale Probe\n\n## Context\n\nBenchmark.\n\n## Decision\n\nMeasure.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n";
82    let mut add_ms = Vec::new();
83    let mut delete_ms = Vec::new();
84    for _ in 0..iterations {
85        fs::write(&added, added_text).expect("write added probe");
86        add_ms.push(timed_read(&mut tracker, true));
87        fs::remove_file(&added).expect("remove added probe");
88        delete_ms.push(timed_read(&mut tracker, true));
89    }
90
91    let renamed = target.with_extension("p6-scale-renamed.md");
92    let mut rename_ms = Vec::new();
93    for _ in 0..iterations {
94        fs::rename(&target, &renamed).expect("rename probe");
95        rename_ms.push(timed_read(&mut tracker, true));
96        fs::rename(&renamed, &target).expect("restore rename probe");
97        timed_read(&mut tracker, true);
98    }
99
100    let mut compact_tracker = if mode == "delta" {
101        FreshnessTracker::new(cache.join("compact"), &root_text, Some(1))
102    } else {
103        FreshnessTracker::new_snapshot(cache.join("compact"), &root_text, Some(1))
104    };
105    timed_read(&mut compact_tracker, true);
106    fs::write(&target, &edited).expect("write compaction edit");
107    let compact_ms = timed_read(&mut compact_tracker, true);
108    fs::write(&target, &original).expect("restore compaction edit");
109
110    let summary = json!({
111        "warm": distribution(&warm_ms),
112        "edit": distribution(&edit_ms),
113        "add": distribution(&add_ms),
114        "delete": distribution(&delete_ms),
115        "rename": distribution(&rename_ms),
116    });
117    let output: Value = json!({
118        "schema_version": "1",
119        "mode": mode,
120        "corpus": root_text,
121        "files": file_count,
122        "iterations": iterations,
123        "cold_ms": cold_ms,
124        "warm_ms": warm_ms,
125        "edit_ms": edit_ms,
126        "add_ms": add_ms,
127        "delete_ms": delete_ms,
128        "rename_ms": rename_ms,
129        "compact_ms": compact_ms,
130        "summary": summary,
131        "last_parse_files": tracker.last_parse_files(),
132        "delta_size": tracker.delta_size(),
133    });
134    println!("{}", serde_json::to_string_pretty(&output).unwrap());
135}
More examples
Hide additional examples
examples/p6_soak.rs (line 246)
102fn main() {
103    let args: Vec<String> = std::env::args().collect();
104    if args.len() < 3 {
105        eprintln!("usage: p6_soak <corpus> <cache-root> [rounds]");
106        std::process::exit(2);
107    }
108    let corpus = PathBuf::from(&args[1]);
109    let cache_root = PathBuf::from(&args[2]);
110    let rounds: usize = args
111        .get(3)
112        .and_then(|value| value.parse().ok())
113        .unwrap_or(3);
114    let root = corpus.to_string_lossy().into_owned();
115    let mutation_cache = cache_root.join("mutation");
116    let referee_root = cache_root.join("referees");
117    let _ = fs::remove_dir_all(&cache_root);
118    fs::create_dir_all(&cache_root).expect("create soak cache");
119    assert_valid(&root);
120
121    let mut tracker = FreshnessTracker::new(
122        mutation_cache.clone(),
123        &root,
124        Some(rounds.saturating_mul(16).saturating_add(100)),
125    );
126    certify_generation(
127        &mut tracker,
128        true,
129        &root,
130        &mutation_cache,
131        &referee_root,
132        "cold",
133    );
134    let mut warm_reads = 0;
135    for _ in 0..100 {
136        tracker.read_model(false);
137        warm_reads += 1;
138    }
139
140    let target = first_markdown(&corpus);
141    let original = fs::read(&target).expect("read mutation target");
142    let mut transitions = 0;
143    for round in 0..rounds {
144        let mut edited = original.clone();
145        edited.extend_from_slice(format!("\n<!-- p6-soak-{round} -->\n").as_bytes());
146        fs::write(&target, &edited).expect("write edit");
147        certify_generation(
148            &mut tracker,
149            true,
150            &root,
151            &mutation_cache,
152            &referee_root,
153            &format!("round-{round}-edit"),
154        );
155        assert_eq!(tracker.last_parse_files(), 1);
156        transitions += 1;
157
158        fs::write(&target, &original).expect("restore edit");
159        certify_generation(
160            &mut tracker,
161            true,
162            &root,
163            &mutation_cache,
164            &referee_root,
165            &format!("round-{round}-restore"),
166        );
167        assert_eq!(tracker.last_parse_files(), 1);
168        transitions += 1;
169
170        let added = corpus.join(format!("p6-soak-added-{round}.md"));
171        let added_text = format!(
172            "---\nschema_version: 1\nid: RAC-Z9SCAE{round:06}\ntype: decision\n---\n# Soak {round}\n\n## Context\n\nBounded soak.\n\n## Decision\n\nCertify.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n"
173        );
174        fs::write(&added, added_text).expect("write added artifact");
175        certify_generation(
176            &mut tracker,
177            true,
178            &root,
179            &mutation_cache,
180            &referee_root,
181            &format!("round-{round}-add"),
182        );
183        assert_eq!(tracker.last_parse_files(), 1);
184        transitions += 1;
185
186        fs::remove_file(&added).expect("delete added artifact");
187        certify_generation(
188            &mut tracker,
189            true,
190            &root,
191            &mutation_cache,
192            &referee_root,
193            &format!("round-{round}-delete"),
194        );
195        assert_eq!(tracker.last_parse_files(), 0);
196        transitions += 1;
197
198        let renamed = target.with_extension(format!("soak-{round}.md"));
199        fs::rename(&target, &renamed).expect("rename target");
200        certify_generation(
201            &mut tracker,
202            true,
203            &root,
204            &mutation_cache,
205            &referee_root,
206            &format!("round-{round}-rename"),
207        );
208        assert_eq!(tracker.last_parse_files(), 1);
209        transitions += 1;
210        fs::rename(&renamed, &target).expect("restore target name");
211        certify_generation(
212            &mut tracker,
213            true,
214            &root,
215            &mutation_cache,
216            &referee_root,
217            &format!("round-{round}-rename-back"),
218        );
219        assert_eq!(tracker.last_parse_files(), 1);
220        transitions += 1;
221    }
222
223    let compaction_cache = cache_root.join("compaction");
224    let compaction_referees = cache_root.join("compaction-referees");
225    let mut compact = FreshnessTracker::new(compaction_cache.clone(), &root, Some(1));
226    certify_generation(
227        &mut compact,
228        true,
229        &root,
230        &compaction_cache,
231        &compaction_referees,
232        "compact-cold",
233    );
234    let mut edited = original.clone();
235    edited.extend_from_slice(b"\n<!-- p6-soak-compaction -->\n");
236    fs::write(&target, &edited).expect("write compaction edit");
237    certify_generation(
238        &mut compact,
239        true,
240        &root,
241        &compaction_cache,
242        &compaction_referees,
243        "compact-edit",
244    );
245    assert_eq!(compact.last_parse_files(), 1);
246    assert_eq!(compact.delta_size(), 0);
247    fs::write(&target, &original).expect("write first post-compaction edit");
248    certify_generation(
249        &mut compact,
250        true,
251        &root,
252        &compaction_cache,
253        &compaction_referees,
254        "compact-post-edit",
255    );
256    assert_eq!(compact.last_parse_files(), 1);
257    assert_eq!(compact.delta_size(), 0);
258    assert_valid(&root);
259
260    println!(
261        "{}",
262        serde_json::to_string_pretty(&json!({
263            "schema_version": "1",
264            "files": rac_engine::walk::find_markdown_files(&root, true).len(),
265            "rounds": rounds,
266            "warm_reads": warm_reads,
267            "certified_transitions": transitions + 3,
268            "valid": true,
269            "deterministic": true,
270            "fresh": true,
271            "cache_no_cache_equal": true,
272            "persisted_segments_byte_equal": true,
273            "post_compaction_parse_files": compact.last_parse_files(),
274        }))
275        .unwrap()
276    );
277}
Source

pub fn delta_enabled(&self) -> bool

Source

pub fn delta_base_documents(&self) -> usize

Source

pub fn delta_upserts(&self) -> usize

Source

pub fn delta_tombstones(&self) -> usize

Source

pub fn last_parse_files(&self) -> usize

Examples found in repository?
examples/p6_scale.rs (line 131)
44fn main() {
45    let args: Vec<String> = std::env::args().collect();
46    if args.len() < 4 || !matches!(args[1].as_str(), "snapshot" | "delta") {
47        eprintln!("usage: p6_scale <snapshot|delta> <corpus> <cache-dir> [iterations]");
48        std::process::exit(2);
49    }
50    let mode = &args[1];
51    let root = PathBuf::from(&args[2]);
52    let cache = PathBuf::from(&args[3]);
53    let iterations: usize = args.get(4).and_then(|v| v.parse().ok()).unwrap_or(7);
54    let root_text = root.to_string_lossy().into_owned();
55    let file_count = rac_engine::walk::find_markdown_files(&root_text, true).len();
56    let threshold = file_count.saturating_add(iterations).saturating_add(10);
57    let mut tracker = if mode == "delta" {
58        FreshnessTracker::new(cache.clone(), &root_text, Some(threshold))
59    } else {
60        FreshnessTracker::new_snapshot(cache.clone(), &root_text, Some(threshold))
61    };
62
63    let cold_ms = timed_read(&mut tracker, true);
64    let warm_ms: Vec<f64> = (0..iterations)
65        .map(|_| timed_read(&mut tracker, false))
66        .collect();
67
68    let target = first_markdown(&root);
69    let original = fs::read(&target).expect("read mutation target");
70    let mut edited = original.clone();
71    edited.extend_from_slice(b"\n<!-- p6-scale-edit -->\n");
72    let mut edit_ms = Vec::new();
73    for _ in 0..iterations {
74        fs::write(&target, &edited).expect("write edit");
75        edit_ms.push(timed_read(&mut tracker, true));
76        fs::write(&target, &original).expect("restore edit");
77        timed_read(&mut tracker, true);
78    }
79
80    let added = root.join("p6-scale-added.md");
81    let added_text = "---\nschema_version: 1\nid: RAC-Z9SCAE000001\ntype: decision\n---\n# Scale Probe\n\n## Context\n\nBenchmark.\n\n## Decision\n\nMeasure.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n";
82    let mut add_ms = Vec::new();
83    let mut delete_ms = Vec::new();
84    for _ in 0..iterations {
85        fs::write(&added, added_text).expect("write added probe");
86        add_ms.push(timed_read(&mut tracker, true));
87        fs::remove_file(&added).expect("remove added probe");
88        delete_ms.push(timed_read(&mut tracker, true));
89    }
90
91    let renamed = target.with_extension("p6-scale-renamed.md");
92    let mut rename_ms = Vec::new();
93    for _ in 0..iterations {
94        fs::rename(&target, &renamed).expect("rename probe");
95        rename_ms.push(timed_read(&mut tracker, true));
96        fs::rename(&renamed, &target).expect("restore rename probe");
97        timed_read(&mut tracker, true);
98    }
99
100    let mut compact_tracker = if mode == "delta" {
101        FreshnessTracker::new(cache.join("compact"), &root_text, Some(1))
102    } else {
103        FreshnessTracker::new_snapshot(cache.join("compact"), &root_text, Some(1))
104    };
105    timed_read(&mut compact_tracker, true);
106    fs::write(&target, &edited).expect("write compaction edit");
107    let compact_ms = timed_read(&mut compact_tracker, true);
108    fs::write(&target, &original).expect("restore compaction edit");
109
110    let summary = json!({
111        "warm": distribution(&warm_ms),
112        "edit": distribution(&edit_ms),
113        "add": distribution(&add_ms),
114        "delete": distribution(&delete_ms),
115        "rename": distribution(&rename_ms),
116    });
117    let output: Value = json!({
118        "schema_version": "1",
119        "mode": mode,
120        "corpus": root_text,
121        "files": file_count,
122        "iterations": iterations,
123        "cold_ms": cold_ms,
124        "warm_ms": warm_ms,
125        "edit_ms": edit_ms,
126        "add_ms": add_ms,
127        "delete_ms": delete_ms,
128        "rename_ms": rename_ms,
129        "compact_ms": compact_ms,
130        "summary": summary,
131        "last_parse_files": tracker.last_parse_files(),
132        "delta_size": tracker.delta_size(),
133    });
134    println!("{}", serde_json::to_string_pretty(&output).unwrap());
135}
More examples
Hide additional examples
examples/p6_soak.rs (line 155)
102fn main() {
103    let args: Vec<String> = std::env::args().collect();
104    if args.len() < 3 {
105        eprintln!("usage: p6_soak <corpus> <cache-root> [rounds]");
106        std::process::exit(2);
107    }
108    let corpus = PathBuf::from(&args[1]);
109    let cache_root = PathBuf::from(&args[2]);
110    let rounds: usize = args
111        .get(3)
112        .and_then(|value| value.parse().ok())
113        .unwrap_or(3);
114    let root = corpus.to_string_lossy().into_owned();
115    let mutation_cache = cache_root.join("mutation");
116    let referee_root = cache_root.join("referees");
117    let _ = fs::remove_dir_all(&cache_root);
118    fs::create_dir_all(&cache_root).expect("create soak cache");
119    assert_valid(&root);
120
121    let mut tracker = FreshnessTracker::new(
122        mutation_cache.clone(),
123        &root,
124        Some(rounds.saturating_mul(16).saturating_add(100)),
125    );
126    certify_generation(
127        &mut tracker,
128        true,
129        &root,
130        &mutation_cache,
131        &referee_root,
132        "cold",
133    );
134    let mut warm_reads = 0;
135    for _ in 0..100 {
136        tracker.read_model(false);
137        warm_reads += 1;
138    }
139
140    let target = first_markdown(&corpus);
141    let original = fs::read(&target).expect("read mutation target");
142    let mut transitions = 0;
143    for round in 0..rounds {
144        let mut edited = original.clone();
145        edited.extend_from_slice(format!("\n<!-- p6-soak-{round} -->\n").as_bytes());
146        fs::write(&target, &edited).expect("write edit");
147        certify_generation(
148            &mut tracker,
149            true,
150            &root,
151            &mutation_cache,
152            &referee_root,
153            &format!("round-{round}-edit"),
154        );
155        assert_eq!(tracker.last_parse_files(), 1);
156        transitions += 1;
157
158        fs::write(&target, &original).expect("restore edit");
159        certify_generation(
160            &mut tracker,
161            true,
162            &root,
163            &mutation_cache,
164            &referee_root,
165            &format!("round-{round}-restore"),
166        );
167        assert_eq!(tracker.last_parse_files(), 1);
168        transitions += 1;
169
170        let added = corpus.join(format!("p6-soak-added-{round}.md"));
171        let added_text = format!(
172            "---\nschema_version: 1\nid: RAC-Z9SCAE{round:06}\ntype: decision\n---\n# Soak {round}\n\n## Context\n\nBounded soak.\n\n## Decision\n\nCertify.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n"
173        );
174        fs::write(&added, added_text).expect("write added artifact");
175        certify_generation(
176            &mut tracker,
177            true,
178            &root,
179            &mutation_cache,
180            &referee_root,
181            &format!("round-{round}-add"),
182        );
183        assert_eq!(tracker.last_parse_files(), 1);
184        transitions += 1;
185
186        fs::remove_file(&added).expect("delete added artifact");
187        certify_generation(
188            &mut tracker,
189            true,
190            &root,
191            &mutation_cache,
192            &referee_root,
193            &format!("round-{round}-delete"),
194        );
195        assert_eq!(tracker.last_parse_files(), 0);
196        transitions += 1;
197
198        let renamed = target.with_extension(format!("soak-{round}.md"));
199        fs::rename(&target, &renamed).expect("rename target");
200        certify_generation(
201            &mut tracker,
202            true,
203            &root,
204            &mutation_cache,
205            &referee_root,
206            &format!("round-{round}-rename"),
207        );
208        assert_eq!(tracker.last_parse_files(), 1);
209        transitions += 1;
210        fs::rename(&renamed, &target).expect("restore target name");
211        certify_generation(
212            &mut tracker,
213            true,
214            &root,
215            &mutation_cache,
216            &referee_root,
217            &format!("round-{round}-rename-back"),
218        );
219        assert_eq!(tracker.last_parse_files(), 1);
220        transitions += 1;
221    }
222
223    let compaction_cache = cache_root.join("compaction");
224    let compaction_referees = cache_root.join("compaction-referees");
225    let mut compact = FreshnessTracker::new(compaction_cache.clone(), &root, Some(1));
226    certify_generation(
227        &mut compact,
228        true,
229        &root,
230        &compaction_cache,
231        &compaction_referees,
232        "compact-cold",
233    );
234    let mut edited = original.clone();
235    edited.extend_from_slice(b"\n<!-- p6-soak-compaction -->\n");
236    fs::write(&target, &edited).expect("write compaction edit");
237    certify_generation(
238        &mut compact,
239        true,
240        &root,
241        &compaction_cache,
242        &compaction_referees,
243        "compact-edit",
244    );
245    assert_eq!(compact.last_parse_files(), 1);
246    assert_eq!(compact.delta_size(), 0);
247    fs::write(&target, &original).expect("write first post-compaction edit");
248    certify_generation(
249        &mut compact,
250        true,
251        &root,
252        &compaction_cache,
253        &compaction_referees,
254        "compact-post-edit",
255    );
256    assert_eq!(compact.last_parse_files(), 1);
257    assert_eq!(compact.delta_size(), 0);
258    assert_valid(&root);
259
260    println!(
261        "{}",
262        serde_json::to_string_pretty(&json!({
263            "schema_version": "1",
264            "files": rac_engine::walk::find_markdown_files(&root, true).len(),
265            "rounds": rounds,
266            "warm_reads": warm_reads,
267            "certified_transitions": transitions + 3,
268            "valid": true,
269            "deterministic": true,
270            "fresh": true,
271            "cache_no_cache_equal": true,
272            "persisted_segments_byte_equal": true,
273            "post_compaction_parse_files": compact.last_parse_files(),
274        }))
275        .unwrap()
276    );
277}
Source

pub fn corpus_hash(&self) -> Option<&str>

Examples found in repository?
examples/p6_soak.rs (line 74)
60fn certify_generation(
61    tracker: &mut FreshnessTracker,
62    verify: bool,
63    root: &str,
64    tracker_cache: &Path,
65    referee_root: &Path,
66    stage: &str,
67) {
68    let materialized: Option<DerivedIndex> = match tracker.read_model(verify) {
69        TrackerModel::Delta(generation) => Some(generation.materialize_derived(root, true)),
70        TrackerModel::View(_) => None,
71        TrackerModel::Snapshot(_) => panic!("S1 delta soak served a snapshot at {stage}"),
72    };
73    let key = tracker
74        .corpus_hash()
75        .expect("fresh generation must have a corpus hash")
76        .to_string();
77    let candidate_cache = referee_root.join(stage).join("candidate");
78    let fresh_cache = referee_root.join(stage).join("fresh");
79    let _ = fs::remove_dir_all(&candidate_cache);
80    let _ = fs::remove_dir_all(&fresh_cache);
81
82    let fresh = build_derived_index(root, true);
83    assert!(write_store(&fresh_cache, &key, SCHEMA_VERSION, &fresh));
84    let candidate_cache = if let Some(candidate) = materialized {
85        assert!(write_store(
86            &candidate_cache,
87            &key,
88            SCHEMA_VERSION,
89            &candidate,
90        ));
91        candidate_cache.as_path()
92    } else {
93        tracker_cache
94    };
95    assert_eq!(
96        store_hashes(candidate_cache, &key),
97        store_hashes(&fresh_cache, &key),
98        "persisted segments diverged from a fresh no-cache derivation at {stage}"
99    );
100}
Source

pub fn last_detect_scanned(&self) -> bool

Source

pub fn read_model(&mut self, verify: bool) -> &TrackerModel

The current read-model, freshened through the detection ladder. An unchanged corpus returns the cached model with no re-derive.

Examples found in repository?
examples/p6_scale.rs (line 20)
18fn timed_read(tracker: &mut FreshnessTracker, verify: bool) -> f64 {
19    let start = Instant::now();
20    tracker.read_model(verify);
21    elapsed_ms(start)
22}
More examples
Hide additional examples
examples/p6_soak.rs (line 68)
60fn certify_generation(
61    tracker: &mut FreshnessTracker,
62    verify: bool,
63    root: &str,
64    tracker_cache: &Path,
65    referee_root: &Path,
66    stage: &str,
67) {
68    let materialized: Option<DerivedIndex> = match tracker.read_model(verify) {
69        TrackerModel::Delta(generation) => Some(generation.materialize_derived(root, true)),
70        TrackerModel::View(_) => None,
71        TrackerModel::Snapshot(_) => panic!("S1 delta soak served a snapshot at {stage}"),
72    };
73    let key = tracker
74        .corpus_hash()
75        .expect("fresh generation must have a corpus hash")
76        .to_string();
77    let candidate_cache = referee_root.join(stage).join("candidate");
78    let fresh_cache = referee_root.join(stage).join("fresh");
79    let _ = fs::remove_dir_all(&candidate_cache);
80    let _ = fs::remove_dir_all(&fresh_cache);
81
82    let fresh = build_derived_index(root, true);
83    assert!(write_store(&fresh_cache, &key, SCHEMA_VERSION, &fresh));
84    let candidate_cache = if let Some(candidate) = materialized {
85        assert!(write_store(
86            &candidate_cache,
87            &key,
88            SCHEMA_VERSION,
89            &candidate,
90        ));
91        candidate_cache.as_path()
92    } else {
93        tracker_cache
94    };
95    assert_eq!(
96        store_hashes(candidate_cache, &key),
97        store_hashes(&fresh_cache, &key),
98        "persisted segments diverged from a fresh no-cache derivation at {stage}"
99    );
100}
101
102fn main() {
103    let args: Vec<String> = std::env::args().collect();
104    if args.len() < 3 {
105        eprintln!("usage: p6_soak <corpus> <cache-root> [rounds]");
106        std::process::exit(2);
107    }
108    let corpus = PathBuf::from(&args[1]);
109    let cache_root = PathBuf::from(&args[2]);
110    let rounds: usize = args
111        .get(3)
112        .and_then(|value| value.parse().ok())
113        .unwrap_or(3);
114    let root = corpus.to_string_lossy().into_owned();
115    let mutation_cache = cache_root.join("mutation");
116    let referee_root = cache_root.join("referees");
117    let _ = fs::remove_dir_all(&cache_root);
118    fs::create_dir_all(&cache_root).expect("create soak cache");
119    assert_valid(&root);
120
121    let mut tracker = FreshnessTracker::new(
122        mutation_cache.clone(),
123        &root,
124        Some(rounds.saturating_mul(16).saturating_add(100)),
125    );
126    certify_generation(
127        &mut tracker,
128        true,
129        &root,
130        &mutation_cache,
131        &referee_root,
132        "cold",
133    );
134    let mut warm_reads = 0;
135    for _ in 0..100 {
136        tracker.read_model(false);
137        warm_reads += 1;
138    }
139
140    let target = first_markdown(&corpus);
141    let original = fs::read(&target).expect("read mutation target");
142    let mut transitions = 0;
143    for round in 0..rounds {
144        let mut edited = original.clone();
145        edited.extend_from_slice(format!("\n<!-- p6-soak-{round} -->\n").as_bytes());
146        fs::write(&target, &edited).expect("write edit");
147        certify_generation(
148            &mut tracker,
149            true,
150            &root,
151            &mutation_cache,
152            &referee_root,
153            &format!("round-{round}-edit"),
154        );
155        assert_eq!(tracker.last_parse_files(), 1);
156        transitions += 1;
157
158        fs::write(&target, &original).expect("restore edit");
159        certify_generation(
160            &mut tracker,
161            true,
162            &root,
163            &mutation_cache,
164            &referee_root,
165            &format!("round-{round}-restore"),
166        );
167        assert_eq!(tracker.last_parse_files(), 1);
168        transitions += 1;
169
170        let added = corpus.join(format!("p6-soak-added-{round}.md"));
171        let added_text = format!(
172            "---\nschema_version: 1\nid: RAC-Z9SCAE{round:06}\ntype: decision\n---\n# Soak {round}\n\n## Context\n\nBounded soak.\n\n## Decision\n\nCertify.\n\n## Consequences\n\nEvidence.\n\n## Status\n\nAccepted\n"
173        );
174        fs::write(&added, added_text).expect("write added artifact");
175        certify_generation(
176            &mut tracker,
177            true,
178            &root,
179            &mutation_cache,
180            &referee_root,
181            &format!("round-{round}-add"),
182        );
183        assert_eq!(tracker.last_parse_files(), 1);
184        transitions += 1;
185
186        fs::remove_file(&added).expect("delete added artifact");
187        certify_generation(
188            &mut tracker,
189            true,
190            &root,
191            &mutation_cache,
192            &referee_root,
193            &format!("round-{round}-delete"),
194        );
195        assert_eq!(tracker.last_parse_files(), 0);
196        transitions += 1;
197
198        let renamed = target.with_extension(format!("soak-{round}.md"));
199        fs::rename(&target, &renamed).expect("rename target");
200        certify_generation(
201            &mut tracker,
202            true,
203            &root,
204            &mutation_cache,
205            &referee_root,
206            &format!("round-{round}-rename"),
207        );
208        assert_eq!(tracker.last_parse_files(), 1);
209        transitions += 1;
210        fs::rename(&renamed, &target).expect("restore target name");
211        certify_generation(
212            &mut tracker,
213            true,
214            &root,
215            &mutation_cache,
216            &referee_root,
217            &format!("round-{round}-rename-back"),
218        );
219        assert_eq!(tracker.last_parse_files(), 1);
220        transitions += 1;
221    }
222
223    let compaction_cache = cache_root.join("compaction");
224    let compaction_referees = cache_root.join("compaction-referees");
225    let mut compact = FreshnessTracker::new(compaction_cache.clone(), &root, Some(1));
226    certify_generation(
227        &mut compact,
228        true,
229        &root,
230        &compaction_cache,
231        &compaction_referees,
232        "compact-cold",
233    );
234    let mut edited = original.clone();
235    edited.extend_from_slice(b"\n<!-- p6-soak-compaction -->\n");
236    fs::write(&target, &edited).expect("write compaction edit");
237    certify_generation(
238        &mut compact,
239        true,
240        &root,
241        &compaction_cache,
242        &compaction_referees,
243        "compact-edit",
244    );
245    assert_eq!(compact.last_parse_files(), 1);
246    assert_eq!(compact.delta_size(), 0);
247    fs::write(&target, &original).expect("write first post-compaction edit");
248    certify_generation(
249        &mut compact,
250        true,
251        &root,
252        &compaction_cache,
253        &compaction_referees,
254        "compact-post-edit",
255    );
256    assert_eq!(compact.last_parse_files(), 1);
257    assert_eq!(compact.delta_size(), 0);
258    assert_valid(&root);
259
260    println!(
261        "{}",
262        serde_json::to_string_pretty(&json!({
263            "schema_version": "1",
264            "files": rac_engine::walk::find_markdown_files(&root, true).len(),
265            "rounds": rounds,
266            "warm_reads": warm_reads,
267            "certified_transitions": transitions + 3,
268            "valid": true,
269            "deterministic": true,
270            "fresh": true,
271            "cache_no_cache_equal": true,
272            "persisted_segments_byte_equal": true,
273            "post_compaction_parse_files": compact.last_parse_files(),
274        }))
275        .unwrap()
276    );
277}
Source

pub fn read_model_with_generation( &mut self, verify: bool, ) -> (u64, &TrackerModel)

Freshen and return the logical corpus generation with its model. Server lifetime derived views use the generation as their invalidation key.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.