Distinguish turn-start thread persistence (#37926)

## What changed

- Add `PersistContext` to the thread-store persistence contract so stores can
  identify persistence requested immediately before model sampling. A
  `TurnStart` request may be enqueued in the background when later flush and
  shutdown operations fence it and report any failure; all other persistence
  remains synchronous.
- Use the turn-start context only for the initial input of a regular turn, while
  admission acknowledgments, steered input, and other persistence paths keep
  the standard durability behavior.
- Flush pending metadata before turn-start persistence and ensure shutdown is
  still attempted if that metadata update fails.

## Testing

- Verify that developer instructions and user input are persisted before the
  model request completes for a default paginated-history thread.

GitOrigin-RevId: 162f0ec796a61aebe66ca0b909fbcccec3047b85
This commit is contained in:
Bryan Ashley authored and copyberry committed 2026-08-11 03:35:45 +00:00
1 parent f8821d85eb
commit 722784e936
24 files changed
+289 -75

No files matched your search

+13 -5
View File
@@ -54,6 +54,7 @@ use crate::ListThreadsParams;
use crate::ListTurnsParams;
use crate::LoadThreadHistoryParams;
use crate::MoveThreadToSectionParams;
use crate::PersistContext;
use crate::PrepareForkParams;
use crate::PreparedFork;
use crate::ReadThreadByRolloutPathParams;
@@ -400,7 +401,11 @@ impl ThreadStore for LocalThreadStore {
Box::pin(async move { live_writer::append_items(self, params).await })
}
fn persist_thread(&self, thread_id: ThreadId) -> ThreadStoreFuture<'_, ()> {
fn persist_thread(
&self,
thread_id: ThreadId,
_context: PersistContext,
) -> ThreadStoreFuture<'_, ()> {
Box::pin(async move { live_writer::persist_thread(self, thread_id).await })
}
@@ -615,7 +620,7 @@ mod tests {
.await
.expect("append live item");
store
.persist_thread(thread_id)
.persist_thread(thread_id, PersistContext::Standard)
.await
.expect("persist live thread");
store
@@ -843,7 +848,10 @@ mod tests {
)
.await
.expect("create live thread with inherited context");
live_thread.persist().await.expect("persist thread");
live_thread
.persist(PersistContext::Standard)
.await
.expect("persist thread");
let inherited_metadata = runtime
.get_thread(thread_id)
.await
@@ -1277,7 +1285,7 @@ mod tests {
.await
.expect("append initial item");
first_store
.persist_thread(thread_id)
.persist_thread(thread_id, PersistContext::Standard)
.await
.expect("persist initial thread");
first_store
@@ -1337,7 +1345,7 @@ mod tests {
.await
.expect("create live thread");
primary
.persist_thread(thread_id)
.persist_thread(thread_id, PersistContext::Standard)
.await
.expect("persist thread for resume");
let rollout_path = primary