Moving updated-at timestamps to unique millisecond times (#17489)

To allow the ability to have guaranteed-unique cursors, we make two
important updates:
* Add new updated_at_ms and created_at_ms columns that are in
millisecond precision
* Guarantee uniqueness -- if multiple items are inserted at the same
millisecond, bump the new one by one millisecond until it becomes unique

This lets us use single-number cursors for forwards and backwards paging
through resultsets and guarantee that the cursor is a fixed point to do
(timestamp > cursor) and get new items only.

This updated implementation is backwards-compatible since multiple
appservers can be running and won't handle the previous method well.
This commit is contained in:
David de Regt
2026-04-14 11:55:34 -04:00
committed by GitHub
parent 61fe23159e
commit 4f2fc3e3fa
13 changed files with 470 additions and 167 deletions

View File

@@ -9703,7 +9703,7 @@ async fn read_updated_at(path: &Path, created_at: Option<&str>) -> Option<String
.and_then(|meta| meta.modified().ok())
.map(|modified| {
let updated_at: DateTime<Utc> = modified.into();
updated_at.to_rfc3339_opts(SecondsFormat::Secs, true)
updated_at.to_rfc3339_opts(SecondsFormat::Millis, true)
});
updated_at.or_else(|| created_at.map(str::to_string))
}
@@ -9954,6 +9954,22 @@ mod tests {
Ok(metadata)
}
#[test]
fn summary_from_thread_metadata_formats_protocol_timestamps_as_seconds() -> Result<()> {
let mut metadata =
test_thread_metadata(/*model*/ None, /*reasoning_effort*/ None)?;
metadata.created_at =
DateTime::parse_from_rfc3339("2025-09-05T16:53:11.123Z")?.with_timezone(&Utc);
metadata.updated_at =
DateTime::parse_from_rfc3339("2025-09-05T16:53:12.456Z")?.with_timezone(&Utc);
let summary = summary_from_thread_metadata(&metadata);
assert_eq!(summary.timestamp, Some("2025-09-05T16:53:11Z".to_string()));
assert_eq!(summary.updated_at, Some("2025-09-05T16:53:12Z".to_string()));
Ok(())
}
#[test]
fn merge_persisted_resume_metadata_prefers_persisted_model_and_reasoning_effort() -> Result<()>
{
@@ -10213,7 +10229,7 @@ mod tests {
let expected = ConversationSummary {
conversation_id,
timestamp: Some(timestamp.clone()),
updated_at: Some("2025-09-05T16:53:11Z".to_string()),
updated_at: Some(timestamp),
path: path.clone(),
preview: String::new(),
model_provider: "fallback".to_string(),