pub struct FreshnessTracker { /* private fields */ }Implementations§
Source§impl FreshnessTracker
impl FreshnessTracker
Sourcepub fn new(cache_dir: PathBuf, root: &str, threshold: Option<usize>) -> Self
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
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}Sourcepub fn new_snapshot(
cache_dir: PathBuf,
root: &str,
threshold: Option<usize>,
) -> Self
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}Sourcepub fn new_stat(
cache_dir: PathBuf,
root: &str,
threshold: Option<usize>,
) -> Self
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.
pub fn mode(&self) -> &'static str
pub fn base_generation(&self) -> u64
pub fn serving_generation(&self) -> u64
Sourcepub fn delta_size(&self) -> usize
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
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}pub fn delta_enabled(&self) -> bool
pub fn delta_base_documents(&self) -> usize
pub fn delta_upserts(&self) -> usize
pub fn delta_tombstones(&self) -> usize
Sourcepub fn last_parse_files(&self) -> usize
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
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}Sourcepub fn corpus_hash(&self) -> Option<&str>
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}pub fn last_detect_scanned(&self) -> bool
Sourcepub fn read_model(&mut self, verify: bool) -> &TrackerModel
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?
More 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}Sourcepub fn read_model_with_generation(
&mut self,
verify: bool,
) -> (u64, &TrackerModel)
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§
impl Freeze for FreshnessTracker
impl RefUnwindSafe for FreshnessTracker
impl Send for FreshnessTracker
impl Sync for FreshnessTracker
impl Unpin for FreshnessTracker
impl UnsafeUnpin for FreshnessTracker
impl UnwindSafe for FreshnessTracker
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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