Skip to main content

lattice_embed/backfill/
types.rs

1//! Defines migration-time routing decisions and backfill configuration.
2//!
3//! The routing configuration separates query and write model selection so a completed
4//! cutover can retain source writes during its rollback window.
5//!
6//! See [docs/backfill.md](../../docs/backfill.md) for the routing contract and defaults.
7
8use serde::{Deserialize, Serialize};
9
10use crate::model::EmbeddingModel;
11
12/// Routing decision for an embedding request during migration.
13///
14/// Determines which model should handle an embedding operation based on
15/// the current migration state and the nature of the request.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum EmbeddingRoute {
18    /// Use the current (legacy) model -- no migration active or migration
19    /// incomplete for this operation type.
20    Legacy,
21    /// Use the new (target) model -- migration complete or sufficient
22    /// progress for query routing.
23    Target,
24    /// Embed with both models (dual-write) -- during active migration
25    /// for new documents to ensure both indexes stay current.
26    DualWrite,
27}
28
29/// Phase of the migration lifecycle for routing decisions.
30///
31/// Distinguishes between normal operation, active migration, and the
32/// post-cutover rollback window where dual-writing continues to enable
33/// safe rollback without data loss.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub enum RoutingPhase {
37    /// Normal operation, no migration active.
38    Stable,
39    /// Active migration in progress.
40    Migrating,
41    /// Post-cutover rollback window (still dual-writing).
42    ///
43    /// During this phase, queries use the target model but writes go to
44    /// both models. This enables instant rollback without losing atoms
45    /// created after cutover.
46    RollbackWindow,
47}
48
49/// Configuration for embedding request routing.
50///
51/// Query and write selections are separate so a rollback window can preserve source writes.
52/// See [docs/backfill.md](../../docs/backfill.md) for how each phase is represented.
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct EmbeddingRoutingConfig {
55    /// Which model to query against.
56    pub query_model: EmbeddingModel,
57    /// Which models to write to (may be multiple for dual-write).
58    pub write_models: Vec<EmbeddingModel>,
59    /// Current routing phase.
60    pub phase: RoutingPhase,
61    /// Migration ID if in migration/rollback phase.
62    pub migration_id: Option<String>,
63}
64
65/// Configuration for the backfill coordinator.
66///
67/// Controls batch sizing, caller-managed concurrency, routing, and rollback timing.
68/// See [docs/backfill.md](../../docs/backfill.md) for default values and policy semantics.
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct BackfillConfig {
71    /// Batch size for backfill operations.
72    pub batch_size: usize,
73    /// Maximum concurrent backfill batches.
74    pub max_concurrent: usize,
75    /// Whether new documents should be dual-written during migration.
76    pub dual_write: bool,
77    /// Raw progress threshold at which query routing may choose the target model.
78    pub target_query_threshold: f64,
79    /// Seconds to retain both write models after a completed cutover.
80    pub rollback_window_secs: u64,
81}
82
83impl Default for BackfillConfig {
84    fn default() -> Self {
85        Self {
86            batch_size: 100,
87            max_concurrent: 4,
88            dual_write: true,
89            target_query_threshold: 0.8,
90            rollback_window_secs: 86400, // 24 hours
91        }
92    }
93}