Reconciles two independently-developed lines from base 006d3d0:
ours — M9/M10 community layers, retroactive purge + re-materialization,
signal revocation, agent capability boundaries, P1 feedback loop,
reason labels, instrumented metrics
theirs — M11/M12 cluster mode (tidal-net gRPC transport, tidal-server
cluster/scatter-gather, tidal-stress), multi-vector preference,
ANN candidate-gen, warm-tier day buckets, keyed signal snapshots
Notable semantic resolutions:
* storage::keys::Tag — both sides allocated 0x0E..0x11 for different
records. Kept theirs' 0x0E..0x1A (shipped on-disk format) and renumbered
ours to 0x1B..0x1E (CommunityMembership/Revocation/PurgeManifest/
CommunityLeave); Tag::ALL grown to 30 so the contiguity drift guard holds.
* ranking executor — took theirs' rewrite (SignalReadPlan pre-pass, keyed
SignalKey snapshots, Result-returning reads, finalize()) and re-applied
ours' M10 read suppression at the chokepoints it introduced:
single_signal_score, score_hot/trending/controversial,
CreatorEngagementRate, and the Stage-4 boost loop.
* signals::warm — theirs' day-bucket/read-time-rotation rewrite, with ours'
subtract_bucket and Clone extended to the new day tier; ours' test split
kept (warm/tests.rs, warm/proptests.rs) carrying theirs' updated bodies.
* db::signals — kept ours' contribution-logging try_cohort_attribution in
signal_dispatch.rs and theirs' event-time try_update_preference_vector;
dropped the superseded duplicates.
* db::mod / from_parts — theirs' constructors, with ours' purge/
re-materialization/revocation/community/skip-counter fields and restart
rebuilds; from_parts kept in its own file per the 600-line guideline.
* schema::validation::builders — ours' module split with theirs' expanded
tests; policy validation runs both sides' checks (read-signal lists +
profile overrides, then the zero-duration limit guard).
* feedback Unhide no longer writes a -1.0 "hide" signal: theirs' engine
rejects negative weights (spec §8). Reverses index state only, matching
every other undo action.
* SessionState::new is now the single construction path (gains
overrides_rejected/default_profile); AuditEntry gains kind on the
deserialize path, inferred from the accepted flag as before.
* Removed tidal/src/replication/tcp_transport.rs and its test: never
declared in replication/mod.rs on either branch, so it had never
compiled and nothing referenced it. Superseded by tidal-net's
GrpcTransport.
Verified: cargo clippy -p tidaldb (lib) clean; --all-targets compiles for
tidaldb/tidal-net/tidal-server/tidal-stress; 2094/2094 lib tests and the
integration suite pass except m8p3_reconcile_production's two CRDT-count
assertions, which fail identically on MERGE_HEAD (pre-existing).
tidalctl cannot build locally: its aws-sdk deps need rustc 1.91.1, local
toolchain is 1.91.0.
98 lines
3.1 KiB
Rust
98 lines
3.1 KiB
Rust
//! Shared test fixtures for the RETRIEVE executor unit tests.
|
|
//!
|
|
//! `tests.rs` and `tests_part2.rs` were split solely to keep each file under the
|
|
//! ≤ 600-line cap (`CODING_GUIDELINES` §9), but both need the SAME scaffolding:
|
|
//! a minimal schema, the built-in profile registry, an item-insertion helper,
|
|
//! and an executor constructor. Rather than copy-paste these verbatim across the
|
|
//! two modules (a DRY hazard — a fix to one fixture silently skips the other),
|
|
//! they live here once and are imported via `use super::test_support::*`.
|
|
|
|
#![allow(clippy::unwrap_used)]
|
|
|
|
use std::{sync::RwLock, time::Duration};
|
|
|
|
use roaring::RoaringBitmap;
|
|
|
|
use super::RetrieveExecutor;
|
|
use crate::{
|
|
ranking::{builtins::register_builtins, registry::ProfileRegistry},
|
|
schema::{DecaySpec, EntityKind, SchemaBuilder, Timestamp, Window},
|
|
signals::SignalLedger,
|
|
storage::indexes::{bitmap::BitmapIndex, range::RangeIndex},
|
|
};
|
|
|
|
/// Minimal item schema: the generic signal vocabulary the built-in profiles read.
|
|
pub(super) fn test_schema() -> crate::schema::Schema {
|
|
let mut builder = SchemaBuilder::new();
|
|
for sig in &["view", "like", "share", "skip", "completion"] {
|
|
let _ = builder
|
|
.signal(
|
|
sig,
|
|
EntityKind::Item,
|
|
DecaySpec::Exponential {
|
|
half_life: Duration::from_secs(7 * 24 * 3600),
|
|
},
|
|
)
|
|
.windows(&[Window::OneHour, Window::TwentyFourHours, Window::SevenDays])
|
|
.velocity(true)
|
|
.add();
|
|
}
|
|
builder.build().unwrap()
|
|
}
|
|
|
|
/// Profile registry pre-loaded with the built-in profiles.
|
|
pub(super) fn setup_registry() -> ProfileRegistry {
|
|
let mut reg = ProfileRegistry::new();
|
|
register_builtins(&mut reg).unwrap();
|
|
reg
|
|
}
|
|
|
|
/// Add an item to the in-memory indexes and universe bitmap.
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub(super) fn add_item(
|
|
category_idx: &BitmapIndex,
|
|
format_idx: &BitmapIndex,
|
|
creator_idx: &BitmapIndex,
|
|
duration_idx: &RangeIndex<u32>,
|
|
created_at_idx: &RangeIndex<u64>,
|
|
universe: &mut RoaringBitmap,
|
|
id: u64,
|
|
category: &str,
|
|
format: &str,
|
|
creator: u64,
|
|
) {
|
|
let id_u32 = id as u32;
|
|
category_idx.insert(id_u32, category);
|
|
format_idx.insert(id_u32, format);
|
|
creator_idx.insert(id_u32, creator.to_string());
|
|
duration_idx.insert(id_u32, 0u32);
|
|
created_at_idx.insert(id_u32, Timestamp::now().as_nanos());
|
|
universe.insert(id_u32);
|
|
}
|
|
|
|
/// Build an executor from test indexes.
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub(super) fn make_executor<'a>(
|
|
ledger: &'a SignalLedger,
|
|
profile_reg: &'a ProfileRegistry,
|
|
cat: &'a BitmapIndex,
|
|
fmt: &'a BitmapIndex,
|
|
creator: &'a BitmapIndex,
|
|
tag: &'a BitmapIndex,
|
|
dur: &'a RangeIndex<u32>,
|
|
ts: &'a RangeIndex<u64>,
|
|
universe: &'a RwLock<RoaringBitmap>,
|
|
) -> RetrieveExecutor<'a> {
|
|
RetrieveExecutor::new(
|
|
ledger,
|
|
profile_reg,
|
|
Some(cat),
|
|
Some(fmt),
|
|
Some(creator),
|
|
Some(tag),
|
|
Some(dur),
|
|
Some(ts),
|
|
Some(universe),
|
|
)
|
|
}
|