fix(agent): log save_or_update as an Update WAL record
A save_or_update that hit an existing record was logged as a plain Save, so replaying the WAL appended a duplicate instead of updating in place. It is now logged as WalEntryType::Update (0x04) carrying the target index, and replay applies it with cache.update(). The WAL header version goes 3 -> 4 for the benefit of older binaries: they don't know record type 0x04, would read it as a torn tail and truncate it and everything after it. An unknown header version makes them refuse the file instead. The framing is otherwise identical, so v3 files are read by the same code and upgraded in place on open (the header is outside the CRC chain). Also drop the redundant WAL truncate that several callers ran straight after flush(), which already truncates. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
943b9141e3
commit
d4f2d3e7b5
@@ -629,7 +629,7 @@ impl HDF5Memory {
|
||||
if let Some(existing_idx) = self.cache.find_by_tags(&entry.tags) {
|
||||
if let Some(ref mut w) = self.wal {
|
||||
let wal_entry = wal::WalEntry {
|
||||
entry_type: wal::WalEntryType::Save,
|
||||
entry_type: wal::WalEntryType::Update,
|
||||
timestamp: entry.timestamp,
|
||||
chunk: entry.chunk.clone(),
|
||||
embedding: entry.embedding.clone(),
|
||||
@@ -637,6 +637,7 @@ impl HDF5Memory {
|
||||
session_id: entry.session_id.clone(),
|
||||
tags: entry.tags.clone(),
|
||||
tombstone_index: None,
|
||||
update_index: Some(existing_idx),
|
||||
};
|
||||
w.append_save(&wal_entry)?;
|
||||
}
|
||||
@@ -668,9 +669,6 @@ impl HDF5Memory {
|
||||
.is_none_or(|w| w.pending_count() as usize > self.config.wal_max_entries);
|
||||
if needs_flush {
|
||||
self.flush()?;
|
||||
if let Some(ref mut w) = self.wal {
|
||||
w.truncate()?;
|
||||
}
|
||||
}
|
||||
return Ok(existing_idx);
|
||||
}
|
||||
@@ -691,6 +689,7 @@ impl AgentMemory for HDF5Memory {
|
||||
session_id: entry.session_id.clone(),
|
||||
tags: entry.tags.clone(),
|
||||
tombstone_index: None,
|
||||
update_index: None,
|
||||
};
|
||||
w.append_save(&wal_entry)?;
|
||||
}
|
||||
@@ -716,9 +715,6 @@ impl AgentMemory for HDF5Memory {
|
||||
.is_none_or(|w| w.pending_count() as usize > self.config.wal_max_entries);
|
||||
if needs_flush {
|
||||
self.flush()?;
|
||||
if let Some(ref mut w) = self.wal {
|
||||
w.truncate()?;
|
||||
}
|
||||
}
|
||||
Ok(idx)
|
||||
}
|
||||
@@ -892,9 +888,6 @@ impl HDF5Memory {
|
||||
*w *= d;
|
||||
}
|
||||
self.flush()?;
|
||||
if let Some(ref mut w) = self.wal {
|
||||
w.truncate()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -906,9 +899,6 @@ impl HDF5Memory {
|
||||
/// Explicit WAL merge: flush .h5, truncate WAL.
|
||||
pub fn flush_wal(&mut self) -> Result<()> {
|
||||
self.flush()?;
|
||||
if let Some(ref mut w) = self.wal {
|
||||
w.truncate()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user