voyager 3: the window in the Rust edge
Test and deploy / test (push) Successful in 47s
Test and deploy / edge (push) Successful in 1m47s
Test and deploy / deploy (push) Skipped

The indexer finishes files and releases by posting time instead of the
range path: the frontier is the median Date of the last 1,024 plausible
dates (within 7 days of it; a run of 1,024 agreeing dates moves it), and
a release is finished, judged and written once the frontier is 24 h past
its last part, flagged edge when posted within a day of the block's start.
At the block's end the rest is written provisionally as edges for the
block merger. Files short of parts stay in their release (partial: the
store writes complete = false). Gone: fragments and the cut-off,
uploads_of (online now), check.ts and the fixture comparison; CI replays
the fixtures through edge-bench instead. The wire carries finished, edge
and partial.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Daan MeijerandClaude Fable 5.1 committed 2026-10-25 21:28:35 +01:00
1 parent 2580f20a43
commit f8cb17903b
13 files changed
+457 -413

No files matched your search

+7 -42
View File
@@ -1,7 +1,7 @@
//! A batch as the coordinator takes it (lib/edge/wire.ts toWire): JSON with
//! the TypeScript names, chunk payloads in base64.
use crate::indexer::{Batch, Candidate, Fragment, ReleaseChunk};
use crate::indexer::{Batch, Candidate, ReleaseChunk};
use base64::Engine;
use serde::Serialize;
@@ -24,6 +24,9 @@ struct WireRelease<'a> {
last_article: i64,
readable: bool,
has_par2: bool,
finished: bool,
edge: bool,
partial: bool,
payload: String,
#[serde(skip_serializing_if = "Option::is_none")]
rule: Option<&'a str>,
@@ -49,30 +52,6 @@ struct WireCount<'a> {
files: u64,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct WireFragmentRelease<'a> {
key: &'a str,
name: &'a str,
source: &'a str,
#[serde(skip_serializing_if = "Option::is_none")]
file_total: Option<i64>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct WireFragment<'a> {
file_key: &'a str,
name: &'a str,
poster: &'a str,
subject: &'a str,
total_parts: u32,
groups: &'a [String],
release: Option<WireFragmentRelease<'a>>,
posted_at: Option<i64>,
segments: Vec<(u32, &'a str, i64, i64)>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct WireBatch<'a> {
@@ -85,7 +64,6 @@ struct WireBatch<'a> {
samples: Vec<WireRelease<'a>>,
candidates: Vec<WireCandidate<'a>>,
counts: Vec<WireCount<'a>>,
fragments: Vec<WireFragment<'a>>,
}
fn release<'a>(r: &'a ReleaseChunk, rule: Option<(&'a str, &'a str)>) -> WireRelease<'a> {
@@ -106,6 +84,9 @@ fn release<'a>(r: &'a ReleaseChunk, rule: Option<(&'a str, &'a str)>) -> WireRel
last_article: r.last_article,
readable: r.readable,
has_par2: r.has_par2,
finished: r.finished,
edge: r.edge,
partial: r.partial,
payload: base64::engine::general_purpose::STANDARD.encode(&r.payload),
rule: rule.map(|(rule, _)| rule),
rule_key: rule.map(|(_, key)| key),
@@ -116,21 +97,6 @@ fn candidate(c: &Candidate) -> WireCandidate<'_> {
WireCandidate { release_key: &c.release_key, upload: c.upload, kind: c.kind, message_id: &c.message_id, file: &c.file }
}
fn fragment(f: &Fragment) -> WireFragment<'_> {
WireFragment {
file_key: &f.file_key,
name: &f.name,
poster: &f.poster,
subject: &f.subject,
total_parts: f.total_parts,
groups: &f.groups,
// A named file always has a release; fileTotal only when truthy, as fragmentOf.
release: Some(WireFragmentRelease { key: &f.release.key, name: &f.release.name, source: f.release.source, file_total: f.release.file_total_truthy() }),
posted_at: f.posted_at,
segments: f.segments.iter().map(|(n, id, bytes, article)| (*n, id.as_str(), *bytes, *article)).collect(),
}
}
/// toWire(batch) as JSON bytes.
pub fn to_json(batch: &Batch) -> Vec<u8> {
let wire = WireBatch {
@@ -143,7 +109,6 @@ pub fn to_json(batch: &Batch) -> Vec<u8> {
samples: batch.samples.iter().map(|(r, rule, key)| release(r, Some((rule, key.as_str())))).collect(),
candidates: batch.candidates.iter().map(candidate).collect(),
counts: batch.counts.iter().map(|(rule, key, articles, files)| WireCount { rule, key, articles: *articles, files: *files }).collect(),
fragments: batch.fragments.iter().map(fragment).collect(),
};
serde_json::to_vec(&wire).unwrap()
}