mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-07-10 15:59:32 +00:00
104 lines
3.1 KiB
Rust
104 lines
3.1 KiB
Rust
use serde::Serialize;
|
|
|
|
/// Coarse lifecycle state of the indexer's ingestion loop, so a client can tell
|
|
/// "still catching up" apart from "something went wrong".
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum IndexerSyncState {
|
|
/// Booted; no ingestion cycle has run yet.
|
|
Starting,
|
|
/// Streaming finalized messages toward the L1 frontier.
|
|
Syncing,
|
|
/// Drained the stream up to LIB; idle until new blocks finalize.
|
|
CaughtUp,
|
|
/// The last cycle failed (e.g. the L1 node is unreachable). See `last_error`.
|
|
Error,
|
|
}
|
|
|
|
/// Live ingestion status owned by the ingest loop: the coarse `state` plus the
|
|
/// reason when it is `Error`.
|
|
#[derive(Debug, Clone, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct IndexerSyncStatus {
|
|
pub state: IndexerSyncState,
|
|
pub last_error: Option<String>,
|
|
}
|
|
|
|
impl IndexerSyncStatus {
|
|
/// Initial status before any ingestion cycle has run.
|
|
pub(crate) const fn starting() -> Self {
|
|
Self {
|
|
state: IndexerSyncState::Starting,
|
|
last_error: None,
|
|
}
|
|
}
|
|
|
|
/// Actively streaming finalized messages toward the L1 frontier.
|
|
pub(crate) const fn syncing() -> Self {
|
|
Self {
|
|
state: IndexerSyncState::Syncing,
|
|
last_error: None,
|
|
}
|
|
}
|
|
|
|
/// Drained the stream up to LIB; idle until new blocks finalize.
|
|
pub(crate) const fn caught_up() -> Self {
|
|
Self {
|
|
state: IndexerSyncState::CaughtUp,
|
|
last_error: None,
|
|
}
|
|
}
|
|
|
|
/// The last cycle failed; `reason` explains why.
|
|
pub(crate) const fn error(reason: String) -> Self {
|
|
Self {
|
|
state: IndexerSyncState::Error,
|
|
last_error: Some(reason),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Full status snapshot returned to callers (FFI/RPC): the live [`IndexerSyncStatus`]
|
|
/// plus the L2 tip (`indexed_block_id`) read fresh from the store at query time.
|
|
///
|
|
/// The tip is tracked by the store, not the ingest loop, so it lives here on the
|
|
/// returned snapshot rather than inside the shared [`IndexerSyncStatus`].
|
|
#[derive(Debug, Clone, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct IndexerStatus {
|
|
#[serde(flatten)]
|
|
pub sync: IndexerSyncStatus,
|
|
pub indexed_block_id: Option<u64>,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn indexer_status_serializes_to_flat_object() {
|
|
let status = IndexerStatus {
|
|
sync: IndexerSyncStatus::error("boom".to_owned()),
|
|
indexed_block_id: Some(7),
|
|
};
|
|
let value = serde_json::to_value(&status).expect("serialize");
|
|
assert_eq!(
|
|
value,
|
|
serde_json::json!({
|
|
"state": "error",
|
|
"lastError": "boom",
|
|
"indexedBlockId": 7,
|
|
})
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn caught_up_clears_error() {
|
|
let value = serde_json::to_value(IndexerSyncStatus::caught_up()).expect("serialize");
|
|
assert_eq!(
|
|
value,
|
|
serde_json::json!({ "state": "caught_up", "lastError": null })
|
|
);
|
|
}
|
|
}
|