update: entry hash chain と session_head mutex を撤廃
- HashedEntry / EntryHash / compute_hash / build_chain 撤去、JSONL は 1 行 1 LogEntry - SessionOrigin.at_hash → at_turn_index (TurnEnd 由来) に置換 - Pod 側 SessionHead mutex を ArcSwap<SessionId> + AtomicUsize の SessionState に置換 - ensure_head_or_fork は store の entry count と writer の append tally で判定 - session-store から sha2 / hex 依存、pod から parking_lot 依存を削除
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
use llm_worker::WorkerResult;
|
||||
use llm_worker::llm_client::types::{Item, RequestConfig};
|
||||
use session_store::{
|
||||
FsStore, LogEntry, Store, TraceEntry, build_chain, collect_state, new_session_id,
|
||||
};
|
||||
use session_store::{FsStore, LogEntry, Store, TraceEntry, collect_state, new_session_id};
|
||||
|
||||
#[test]
|
||||
fn round_trip_write_and_read() {
|
||||
@@ -10,7 +8,7 @@ fn round_trip_write_and_read() {
|
||||
let store = FsStore::new(dir.path()).unwrap();
|
||||
let id = new_session_id();
|
||||
|
||||
let raw = vec![
|
||||
let entries = vec![
|
||||
LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: Some("You are helpful.".into()),
|
||||
@@ -37,31 +35,21 @@ fn round_trip_write_and_read() {
|
||||
result: WorkerResult::Finished,
|
||||
},
|
||||
];
|
||||
let entries = build_chain(&raw);
|
||||
|
||||
// Write entries one by one
|
||||
for entry in &entries {
|
||||
store.append(id, entry).unwrap();
|
||||
}
|
||||
|
||||
// Read back
|
||||
let read_back = store.read_all(id).unwrap();
|
||||
assert_eq!(read_back.len(), entries.len());
|
||||
|
||||
// Verify hashes survived round-trip
|
||||
for (orig, read) in entries.iter().zip(read_back.iter()) {
|
||||
assert_eq!(orig.hash, read.hash);
|
||||
assert_eq!(orig.prev_hash, read.prev_hash);
|
||||
}
|
||||
|
||||
// Replay and verify state
|
||||
let state = collect_state(&read_back);
|
||||
assert_eq!(state.system_prompt.as_deref(), Some("You are helpful."));
|
||||
assert_eq!(state.config.max_tokens, Some(1024));
|
||||
assert_eq!(state.history.len(), 2);
|
||||
assert_eq!(state.turn_count, 1);
|
||||
assert!(!state.last_run_interrupted);
|
||||
assert!(state.head_hash.is_some());
|
||||
assert_eq!(state.entries_count, entries.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -70,7 +58,7 @@ fn create_session_writes_all_entries() {
|
||||
let store = FsStore::new(dir.path()).unwrap();
|
||||
let id = new_session_id();
|
||||
|
||||
let entries = build_chain(&[LogEntry::SessionStart {
|
||||
let entries = [LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
@@ -80,7 +68,7 @@ fn create_session_writes_all_entries() {
|
||||
],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
}]);
|
||||
}];
|
||||
|
||||
store.create_session(id, &entries).unwrap();
|
||||
let read_back = store.read_all(id).unwrap();
|
||||
@@ -100,25 +88,17 @@ fn list_sessions_returns_newest_first() {
|
||||
std::thread::sleep(std::time::Duration::from_millis(2));
|
||||
let id2 = new_session_id();
|
||||
|
||||
let entries1 = build_chain(&[LogEntry::SessionStart {
|
||||
let entry = LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
}]);
|
||||
let entries2 = build_chain(&[LogEntry::SessionStart {
|
||||
ts: 1001,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
}]);
|
||||
};
|
||||
|
||||
store.append(id1, &entries1[0]).unwrap();
|
||||
store.append(id2, &entries2[0]).unwrap();
|
||||
store.append(id1, &entry).unwrap();
|
||||
store.append(id2, &entry).unwrap();
|
||||
|
||||
let sessions = store.list_sessions().unwrap();
|
||||
assert_eq!(sessions.len(), 2);
|
||||
@@ -134,15 +114,19 @@ fn exists_returns_correct_state() {
|
||||
|
||||
assert!(!store.exists(id).unwrap());
|
||||
|
||||
let entries = build_chain(&[LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
}]);
|
||||
store.append(id, &entries[0]).unwrap();
|
||||
store
|
||||
.append(
|
||||
id,
|
||||
&LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(store.exists(id).unwrap());
|
||||
}
|
||||
@@ -163,18 +147,20 @@ fn trace_entries_in_separate_file() {
|
||||
let store = FsStore::new(dir.path()).unwrap();
|
||||
let id = new_session_id();
|
||||
|
||||
// Write a log entry
|
||||
let entries = build_chain(&[LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
}]);
|
||||
store.append(id, &entries[0]).unwrap();
|
||||
store
|
||||
.append(
|
||||
id,
|
||||
&LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
config: RequestConfig::default(),
|
||||
history: vec![],
|
||||
forked_from: None,
|
||||
compacted_from: None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Write a trace entry
|
||||
let trace = TraceEntry {
|
||||
ts: 1500,
|
||||
turn: 0,
|
||||
@@ -194,12 +180,12 @@ fn trace_entries_in_separate_file() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_head_hash_returns_last_entry_hash() {
|
||||
fn read_entry_count_matches_append_tally() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let store = FsStore::new(dir.path()).unwrap();
|
||||
let id = new_session_id();
|
||||
|
||||
let entries = build_chain(&[
|
||||
let entries = [
|
||||
LogEntry::SessionStart {
|
||||
ts: 1000,
|
||||
system_prompt: None,
|
||||
@@ -212,12 +198,11 @@ fn read_head_hash_returns_last_entry_hash() {
|
||||
ts: 2000,
|
||||
segments: vec![protocol::Segment::text("Hello")],
|
||||
},
|
||||
]);
|
||||
];
|
||||
|
||||
for entry in &entries {
|
||||
store.append(id, entry).unwrap();
|
||||
}
|
||||
|
||||
let head = store.read_head_hash(id).unwrap();
|
||||
assert_eq!(head.as_ref(), Some(&entries[1].hash));
|
||||
assert_eq!(store.read_entry_count(id).unwrap(), entries.len());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user