Final completeness by time window: ranges keep their posting span, release_final() over blocks of done ranges
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3d24db5565
commit
ce43099188
12 files changed
+259
-9
No files matched your search
@@ -78,6 +78,9 @@ pub struct Batch {
|
||||
pub from: i64,
|
||||
pub next: i64,
|
||||
pub headers: u64,
|
||||
/// postedLow / postedHigh: the batch's posting times without the earliest and latest 1% (postedSpan).
|
||||
pub posted_low: Option<i64>,
|
||||
pub posted_high: Option<i64>,
|
||||
pub releases: Vec<ReleaseChunk>,
|
||||
pub samples: Vec<(ReleaseChunk, &'static str, String)>,
|
||||
pub candidates: Vec<Candidate>,
|
||||
@@ -277,6 +280,16 @@ fn first_track(text: &str) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
/// postedSpan: posting times without the earliest and latest 1% (floor(n / 100) at each end).
|
||||
pub fn posted_span(mut dates: Vec<i64>) -> (Option<i64>, Option<i64>) {
|
||||
if dates.is_empty() {
|
||||
return (None, None);
|
||||
}
|
||||
dates.sort_unstable();
|
||||
let k = dates.len() / 100;
|
||||
(Some(dates[k]), Some(dates[dates.len() - 1 - k]))
|
||||
}
|
||||
|
||||
/// nameBesideQuotes (lib/headers/subject.ts): a file name elsewhere when the quoted text has no extension.
|
||||
pub fn name_beside_quotes(quoted: &str, before_counter: &str) -> Option<String> {
|
||||
if has_extension(quoted) {
|
||||
@@ -633,6 +646,8 @@ pub struct RangeIndexer {
|
||||
count_order: Vec<(&'static str, String)>,
|
||||
completed: FxHashMap<String, Vec<Vec<Seg>>>,
|
||||
completed_order: Vec<String>,
|
||||
/// Posting times of this batch's segments (posted_span at take).
|
||||
dates: Vec<i64>,
|
||||
}
|
||||
|
||||
impl RangeIndexer {
|
||||
@@ -653,6 +668,7 @@ impl RangeIndexer {
|
||||
count_order: Vec::new(),
|
||||
completed: FxHashMap::default(),
|
||||
completed_order: Vec::new(),
|
||||
dates: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,6 +699,7 @@ impl RangeIndexer {
|
||||
});
|
||||
}
|
||||
self.batch.headers += headers;
|
||||
self.dates.extend(segments.iter().filter_map(|s| s.posted_at));
|
||||
for owner in crossposts {
|
||||
self.count("crosspost", owner, 1, 0);
|
||||
}
|
||||
@@ -725,6 +742,7 @@ impl RangeIndexer {
|
||||
self.scanner.files.clear();
|
||||
let next = self.batch.next;
|
||||
let mut out = std::mem::replace(&mut self.batch, Batch { from: next, next, ..Default::default() });
|
||||
(out.posted_low, out.posted_high) = posted_span(std::mem::take(&mut self.dates));
|
||||
for id in self.count_order.drain(..) {
|
||||
let (articles, files) = self.counts.remove(&id).unwrap();
|
||||
out.counts.push((id.0, id.1, articles, files));
|
||||
@@ -1015,3 +1033,18 @@ mod beside_quotes_tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod posted_span_tests {
|
||||
use super::posted_span;
|
||||
|
||||
#[test]
|
||||
fn without_the_earliest_and_latest_percent() {
|
||||
assert_eq!(posted_span(vec![]), (None, None));
|
||||
let mut dates: Vec<i64> = (0..200).map(|i| 1_000_000 + i).collect();
|
||||
dates.push(5);
|
||||
dates.push(9_999_999_999);
|
||||
// 202 dates: 2 trimmed at each end, so the two wild ones go (postedSpan).
|
||||
assert_eq!(posted_span(dates), (Some(1_000_001), Some(1_000_198)));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user