mirror of
https://github.com/openai/codex.git
synced 2026-05-04 05:11:37 +03:00
chore: improve DB flushing (#13620)
This branch: * Avoid flushing DB when not necessary * Filter events for which we perfom an `upsert` into the DB * Add a dedicated update function of the `thread:updated_at` that is lighter This should significantly reduce the DB lock contention. If it is not sufficient, we can de-sync the flush of the DB for `updated_at`
This commit is contained in:
@@ -278,6 +278,19 @@ ON CONFLICT(id) DO NOTHING
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
|
||||
pub async fn touch_thread_updated_at(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
updated_at: DateTime<Utc>,
|
||||
) -> anyhow::Result<bool> {
|
||||
let result = sqlx::query("UPDATE threads SET updated_at = ? WHERE id = ?")
|
||||
.bind(datetime_to_epoch_seconds(updated_at))
|
||||
.bind(thread_id.to_string())
|
||||
.execute(self.pool.as_ref())
|
||||
.await?;
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
|
||||
pub async fn update_thread_git_info(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
@@ -436,6 +449,7 @@ ON CONFLICT(thread_id, position) DO NOTHING
|
||||
items: &[RolloutItem],
|
||||
otel: Option<&OtelManager>,
|
||||
new_thread_memory_mode: Option<&str>,
|
||||
updated_at_override: Option<DateTime<Utc>>,
|
||||
) -> anyhow::Result<()> {
|
||||
if items.is_empty() {
|
||||
return Ok(());
|
||||
@@ -451,7 +465,11 @@ ON CONFLICT(thread_id, position) DO NOTHING
|
||||
if let Some(existing_metadata) = existing_metadata.as_ref() {
|
||||
metadata.prefer_existing_git_info(existing_metadata);
|
||||
}
|
||||
if let Some(updated_at) = file_modified_time_utc(builder.rollout_path.as_path()).await {
|
||||
let updated_at = match updated_at_override {
|
||||
Some(updated_at) => Some(updated_at),
|
||||
None => file_modified_time_utc(builder.rollout_path.as_path()).await,
|
||||
};
|
||||
if let Some(updated_at) = updated_at {
|
||||
metadata.updated_at = updated_at;
|
||||
}
|
||||
// Keep the thread upsert before dynamic tools to satisfy the foreign key constraint:
|
||||
@@ -649,6 +667,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::runtime::test_support::test_thread_metadata;
|
||||
use crate::runtime::test_support::unique_temp_dir;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::GitInfo;
|
||||
use codex_protocol::protocol::SessionMeta;
|
||||
use codex_protocol::protocol::SessionMetaLine;
|
||||
@@ -735,7 +754,7 @@ mod tests {
|
||||
})];
|
||||
|
||||
runtime
|
||||
.apply_rollout_items(&builder, &items, None, None)
|
||||
.apply_rollout_items(&builder, &items, None, None, None)
|
||||
.await
|
||||
.expect("apply_rollout_items should succeed");
|
||||
|
||||
@@ -793,7 +812,7 @@ mod tests {
|
||||
})];
|
||||
|
||||
runtime
|
||||
.apply_rollout_items(&builder, &items, None, None)
|
||||
.apply_rollout_items(&builder, &items, None, None, None)
|
||||
.await
|
||||
.expect("apply_rollout_items should succeed");
|
||||
|
||||
@@ -947,4 +966,95 @@ mod tests {
|
||||
assert_eq!(persisted.git_branch, None);
|
||||
assert_eq!(persisted.git_origin_url, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn touch_thread_updated_at_updates_only_updated_at() {
|
||||
let codex_home = unique_temp_dir();
|
||||
let runtime = StateRuntime::init(codex_home.clone(), "test-provider".to_string(), None)
|
||||
.await
|
||||
.expect("state db should initialize");
|
||||
let thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000791").expect("valid thread id");
|
||||
let mut metadata = test_thread_metadata(&codex_home, thread_id, codex_home.clone());
|
||||
metadata.title = "original title".to_string();
|
||||
metadata.first_user_message = Some("first-user-message".to_string());
|
||||
|
||||
runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.expect("initial upsert should succeed");
|
||||
|
||||
let touched_at = DateTime::<Utc>::from_timestamp(1_700_001_111, 0).expect("timestamp");
|
||||
let touched = runtime
|
||||
.touch_thread_updated_at(thread_id, touched_at)
|
||||
.await
|
||||
.expect("touch should succeed");
|
||||
assert!(touched);
|
||||
|
||||
let persisted = runtime
|
||||
.get_thread(thread_id)
|
||||
.await
|
||||
.expect("thread should load")
|
||||
.expect("thread should exist");
|
||||
assert_eq!(persisted.updated_at, touched_at);
|
||||
assert_eq!(persisted.title, "original title");
|
||||
assert_eq!(
|
||||
persisted.first_user_message.as_deref(),
|
||||
Some("first-user-message")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn apply_rollout_items_uses_override_updated_at_when_provided() {
|
||||
let codex_home = unique_temp_dir();
|
||||
let runtime = StateRuntime::init(codex_home.clone(), "test-provider".to_string(), None)
|
||||
.await
|
||||
.expect("state db should initialize");
|
||||
let thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000792").expect("valid thread id");
|
||||
let metadata = test_thread_metadata(&codex_home, thread_id, codex_home.clone());
|
||||
|
||||
runtime
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.expect("initial upsert should succeed");
|
||||
|
||||
let builder = ThreadMetadataBuilder::new(
|
||||
thread_id,
|
||||
metadata.rollout_path.clone(),
|
||||
metadata.created_at,
|
||||
SessionSource::Cli,
|
||||
);
|
||||
let items = vec![RolloutItem::EventMsg(EventMsg::TokenCount(
|
||||
codex_protocol::protocol::TokenCountEvent {
|
||||
info: Some(codex_protocol::protocol::TokenUsageInfo {
|
||||
total_token_usage: codex_protocol::protocol::TokenUsage {
|
||||
input_tokens: 0,
|
||||
cached_input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
reasoning_output_tokens: 0,
|
||||
total_tokens: 321,
|
||||
},
|
||||
last_token_usage: codex_protocol::protocol::TokenUsage::default(),
|
||||
model_context_window: None,
|
||||
}),
|
||||
rate_limits: None,
|
||||
},
|
||||
))];
|
||||
let override_updated_at =
|
||||
DateTime::<Utc>::from_timestamp(1_700_001_234, 0).expect("timestamp");
|
||||
|
||||
runtime
|
||||
.apply_rollout_items(&builder, &items, None, None, Some(override_updated_at))
|
||||
.await
|
||||
.expect("apply_rollout_items should succeed");
|
||||
|
||||
let persisted = runtime
|
||||
.get_thread(thread_id)
|
||||
.await
|
||||
.expect("thread should load")
|
||||
.expect("thread should exist");
|
||||
assert_eq!(persisted.tokens_used, 321);
|
||||
assert_eq!(persisted.updated_at, override_updated_at);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user