Skip to main content

vdsl_sync/infra/
transfer_store.rs

1//! TransferStore — Transfer永続化トレイト。
2//!
3//! 配送記録の永続化を抽象化する。
4//! Transfer CRUD + クエリ + 集計 + pruning。
5
6use async_trait::async_trait;
7use chrono::{DateTime, Utc};
8
9use crate::domain::location::LocationId;
10use crate::domain::transfer::{Transfer, TransferState};
11use crate::infra::error::InfraError;
12
13/// DB集約クエリの1行。dest×state別のファイル数カウント。
14#[derive(Debug, Clone)]
15pub struct TransferStatRow {
16    pub src: LocationId,
17    pub dest: LocationId,
18    pub state: TransferState,
19    pub error_kind: Option<String>,
20    pub attempt: u32,
21    pub file_count: usize,
22}
23
24/// Transfer永続化。
25///
26/// 実装: [`super::sqlite::SqliteSyncStore`] (feature = "sqlite")
27#[async_trait]
28pub trait TransferStore: Send + Sync {
29    /// Transferを保存。
30    async fn insert_transfer(&self, transfer: &Transfer) -> Result<(), InfraError>;
31
32    /// Transfer状態を更新(start/complete/fail後に呼ぶ)。
33    async fn update_transfer(&self, transfer: &Transfer) -> Result<(), InfraError>;
34
35    /// 特定destのQueued Transfer一覧。
36    ///
37    /// 各file_idの最新Transferのみ返す(古いリトライは除外)。
38    async fn queued_transfers(&self, dest: &LocationId) -> Result<Vec<Transfer>, InfraError>;
39
40    /// 特定ファイルの最新Transfer(dest別)。
41    ///
42    /// 各destについて最新のTransferのみ返す。
43    /// FileView構築時にPresenceView導出に使用。
44    async fn latest_transfers_by_file(&self, file_id: &str) -> Result<Vec<Transfer>, InfraError>;
45
46    /// Failed Transfer一覧(最新のみ)。
47    async fn failed_transfers(&self) -> Result<Vec<Transfer>, InfraError>;
48
49    /// 完了済み古いTransferを削除。削除件数を返す。
50    ///
51    /// 履歴肥大化防止用。各file_id×destの最新は保持される。
52    async fn prune_completed(&self, before: DateTime<Utc>) -> Result<usize, InfraError>;
53
54    /// Queued状態のTransfer件数を返す。進捗表示用。
55    async fn count_queued(&self) -> Result<usize, InfraError>;
56
57    /// InFlight状態のTransferをCancelledに遷移。
58    ///
59    /// プロセス再起動時にInFlightのまま残った孤児transferを終端状態にする。
60    /// Cancelledは終端状態 — 再実行されない。必要であれば新しいTransferを作成する。
61    /// 返り値はキャンセルした件数。
62    async fn cancel_orphaned_inflight(&self) -> Result<usize, InfraError>;
63
64    /// 指定Transfer IDに依存するBlocked TransferをQueuedに遷移させる。
65    ///
66    /// Transfer完了時に呼び出し、依存チェーンの次ホップを実行可能にする。
67    /// 返り値はunblockした件数。
68    async fn unblock_dependents(&self, completed_transfer_id: &str) -> Result<usize, InfraError>;
69
70    /// 全destのQueued/Blocked Transfer一覧(最新のみ)。
71    ///
72    /// `status()` のpending_entries構築用。dest指定なしで全pendingを返す。
73    async fn all_pending_transfers(&self) -> Result<Vec<Transfer>, InfraError>;
74
75    /// Transfer状態の集約統計。
76    ///
77    /// 最新Transfer(file_id×dest別)をsrc, dest, state, error_kind, attemptでGROUP BYし、
78    /// ファイル数カウントを返す。`status()`のN+1クエリ問題を解消するための集約メソッド。
79    async fn transfer_stats(&self) -> Result<Vec<TransferStatRow>, InfraError>;
80
81    /// Location別のPresent file数。
82    ///
83    /// 各locationについて、srcとして送出した or completedとして到達したdistinct file数を返す。
84    /// UNIONでsrc/completed-destを統合し、同一location×file_idの重複を排除する。
85    async fn present_counts_by_location(
86        &self,
87    ) -> Result<std::collections::HashMap<LocationId, usize>, InfraError>;
88}