use awaken_contract::contract::message::Message;
use awaken_contract::contract::storage::{RunRecord, StorageError, ThreadRunStore};
use super::{NatsBufferedThreadStore, entry, hot_meta, keys};
pub async fn checkpoint<T: ThreadRunStore + Send + Sync + 'static>(
store: &NatsBufferedThreadStore<T>,
thread_id: &str,
messages: &[Message],
run: &RunRecord,
) -> Result<(), StorageError> {
let now = now_millis();
let seq = hot_meta::reserve_seq(&store.kv_hot, thread_id, now).await?;
let wal_entry = entry::CheckpointEntry {
thread_id: thread_id.to_string(),
run: run.clone(),
messages: messages.to_vec(),
thread_seq: seq,
written_at: now,
};
let payload = entry::encode(&wal_entry)?;
let publish_ack = store
.jetstream
.publish(keys::thread_subject(thread_id), payload)
.await
.map_err(|e| StorageError::Io(format!("publish: {e}")))?;
let ack = publish_ack
.await
.map_err(|e| StorageError::Io(format!("publish ack: {e}")))?;
let js_seq = ack.sequence;
hot_meta::cache_run_if_newer(&store.kv_hot, run, seq).await?;
hot_meta::promote_latest_seq(&store.kv_hot, thread_id, seq, js_seq, now).await?;
Ok(())
}
fn now_millis() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_millis() as u64)
.unwrap_or(0)
}