Skip to main content

Module snapshot

Module snapshot 

Source
Expand description

Save and restore VM instance state. Save and restore VM instance state.

This module provides Instance::save_state and Instance::restore_state for pausing execution at bar N and resuming from bar N+1 later.

§Server-side best practices

In a server deployment, each running script typically processes thousands of historical bars before reaching the live feed. Replaying all historical bars on every restart is expensive. Snapshots let you checkpoint the VM state after the historical replay, then reload it instantly on the next start.

Cold start
  │
  ├─ Build Instance (InstanceBuilder)
  ├─ let mut handle = instance.run(symbol, timeframe)
  ├─ while let Some(e) = handle.next_event().await { … }
  ├─ handle.save_state() → Vec<u8>   (or instance.run_to_end() then save_state())
  ├─ Persist the bytes (database, object storage, local disk, …)
  └─ Continue feeding live bars

Warm restart
  │
  ├─ Load the persisted bytes
  ├─ let mut instance = Instance::restore_state(&bytes)?
  │       .with_data_provider(provider).build()?;
  └─ instance.run_to_end() — automatically resumes from the next bar

§When to save

The current bar must be confirmed before saving — save_state() returns SnapshotError::UnconfirmedBar otherwise. Save once after the last confirmed bar and resave whenever you want to advance the checkpoint.

§Candlestick data

Candlestick data is not included in the snapshot. When run() is called on a restored instance, the VM automatically passes last_bar_time + 1 to the data provider so that only new bars are fetched.

§Versioning and invalidation

Snapshots embed a format version (SNAPSHOT_VERSION) and the compiled Program. A snapshot is only valid for the exact binary that created it: a new Navi release, a changed script, or modified inputs all require discarding the snapshot and replaying history from scratch.

A simple invalidation strategy: store the snapshot alongside a hash of the Pine source (or the compiled program bytes). On startup, compare the hash; if it differs, delete the snapshot and do a full cold replay.

§Example

use navi_vm::{Instance, snapshot::SnapshotError};

// --- Cold start: replay history and checkpoint ---
let mut instance = build_instance(script, symbol_info, timeframe)
    .run_to_end(symbol, timeframe)
    .await?;
let snapshot: Vec<u8> = instance.save_state()?;  // bar must be confirmed
persist_to_storage(&snapshot);

// --- Warm restart: restore and continue ---
let bytes: Vec<u8> = load_from_storage();
let instance = Instance::restore_state(&bytes)?
    .with_data_provider(provider)
    .build()?
    .run_to_end(symbol, timeframe)
    .await?;  // auto-resumes

Structs§

RestoreBuilder
Builder returned by Instance::restore_state for configuring optional parameters before completing the restore.

Enums§

SnapshotError
Errors that can occur during snapshot save/restore.