mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
112 lines
3.0 KiB
Rust
112 lines
3.0 KiB
Rust
//! Persist the session id between `bsk record start` and `bsk record stop`.
|
|
|
|
use std::fs;
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
use anyhow::{Context, Result};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::daemon::paths;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct RecordSessionState {
|
|
pub session_id: String,
|
|
pub started_at: String,
|
|
}
|
|
|
|
pub fn write(session_id: &str) -> Result<()> {
|
|
let path = paths::record_session_path()?;
|
|
paths::ensure_bsk_home()?;
|
|
if path.exists() {
|
|
return Err(anyhow::anyhow!(
|
|
"a recording is already in progress; run `bsk record stop` first"
|
|
));
|
|
}
|
|
let state = RecordSessionState {
|
|
session_id: session_id.to_string(),
|
|
started_at: started_at_unix_ms(),
|
|
};
|
|
let json = serde_json::to_string_pretty(&state).context("serialize record session state")?;
|
|
fs::write(&path, format!("{json}\n")).with_context(|| format!("write {}", path.display()))?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn read() -> Result<RecordSessionState> {
|
|
let path = paths::record_session_path()?;
|
|
if !path.exists() {
|
|
return Err(anyhow::anyhow!(
|
|
"no recording in progress; run `bsk record start` first"
|
|
));
|
|
}
|
|
let raw = fs::read_to_string(&path).with_context(|| format!("read {}", path.display()))?;
|
|
serde_json::from_str(&raw).with_context(|| format!("parse {}", path.display()))
|
|
}
|
|
|
|
pub fn clear() {
|
|
if let Ok(path) = paths::record_session_path() {
|
|
let _ = fs::remove_file(path);
|
|
}
|
|
}
|
|
|
|
fn started_at_unix_ms() -> String {
|
|
let ms = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_millis();
|
|
format!("{ms}")
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn with_temp_home<F: FnOnce()>(f: F) {
|
|
let _lock = crate::daemon::paths::test_env_lock();
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
unsafe {
|
|
std::env::set_var(crate::daemon::paths::BSK_HOME_ENV, tmp.path());
|
|
}
|
|
f();
|
|
clear();
|
|
unsafe {
|
|
std::env::remove_var(crate::daemon::paths::BSK_HOME_ENV);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn write_read_round_trips() {
|
|
with_temp_home(|| {
|
|
write("abcd").unwrap();
|
|
let state = read().unwrap();
|
|
assert_eq!(state.session_id, "abcd");
|
|
assert!(!state.started_at.is_empty());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn write_rejects_duplicate() {
|
|
with_temp_home(|| {
|
|
write("abcd").unwrap();
|
|
let err = write("efgh").unwrap_err();
|
|
assert!(err.to_string().contains("already in progress"));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn read_errors_when_missing() {
|
|
with_temp_home(|| {
|
|
let err = read().unwrap_err();
|
|
assert!(err.to_string().contains("no recording in progress"));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn clear_removes_state_file() {
|
|
with_temp_home(|| {
|
|
write("abcd").unwrap();
|
|
clear();
|
|
assert!(read().is_err());
|
|
});
|
|
}
|
|
}
|