feat: record memory usage (#12761)

This commit is contained in:
jif-oai
2026-02-25 13:48:40 +00:00
committed by GitHub
parent 5441130e0a
commit e4bfa763f6
7 changed files with 254 additions and 24 deletions
+99
View File
@@ -3124,6 +3124,105 @@ VALUES (?, ?, ?, ?, ?)
let _ = tokio::fs::remove_dir_all(codex_home).await;
}
#[tokio::test]
async fn record_stage1_output_usage_updates_usage_metadata() {
let codex_home = unique_temp_dir();
let runtime = StateRuntime::init(codex_home.clone(), "test-provider".to_string(), None)
.await
.expect("initialize runtime");
let thread_a = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("thread id a");
let thread_b = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("thread id b");
let missing = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("missing id");
let owner = ThreadId::from_string(&Uuid::new_v4().to_string()).expect("owner id");
runtime
.upsert_thread(&test_thread_metadata(
&codex_home,
thread_a,
codex_home.join("workspace-a"),
))
.await
.expect("upsert thread a");
runtime
.upsert_thread(&test_thread_metadata(
&codex_home,
thread_b,
codex_home.join("workspace-b"),
))
.await
.expect("upsert thread b");
let claim_a = runtime
.try_claim_stage1_job(thread_a, owner, 100, 3600, 64)
.await
.expect("claim stage1 a");
let token_a = match claim_a {
Stage1JobClaimOutcome::Claimed { ownership_token } => ownership_token,
other => panic!("unexpected stage1 claim outcome for a: {other:?}"),
};
assert!(
runtime
.mark_stage1_job_succeeded(thread_a, token_a.as_str(), 100, "raw a", "sum a", None)
.await
.expect("mark stage1 succeeded a")
);
let claim_b = runtime
.try_claim_stage1_job(thread_b, owner, 101, 3600, 64)
.await
.expect("claim stage1 b");
let token_b = match claim_b {
Stage1JobClaimOutcome::Claimed { ownership_token } => ownership_token,
other => panic!("unexpected stage1 claim outcome for b: {other:?}"),
};
assert!(
runtime
.mark_stage1_job_succeeded(thread_b, token_b.as_str(), 101, "raw b", "sum b", None)
.await
.expect("mark stage1 succeeded b")
);
let updated_rows = runtime
.record_stage1_output_usage(&[thread_a, thread_a, thread_b, missing])
.await
.expect("record stage1 output usage");
assert_eq!(updated_rows, 3);
let row_a =
sqlx::query("SELECT usage_count, last_usage FROM stage1_outputs WHERE thread_id = ?")
.bind(thread_a.to_string())
.fetch_one(runtime.pool.as_ref())
.await
.expect("load stage1 usage row a");
let row_b =
sqlx::query("SELECT usage_count, last_usage FROM stage1_outputs WHERE thread_id = ?")
.bind(thread_b.to_string())
.fetch_one(runtime.pool.as_ref())
.await
.expect("load stage1 usage row b");
assert_eq!(
row_a
.try_get::<i64, _>("usage_count")
.expect("usage_count a"),
2
);
assert_eq!(
row_b
.try_get::<i64, _>("usage_count")
.expect("usage_count b"),
1
);
let last_usage_a = row_a.try_get::<i64, _>("last_usage").expect("last_usage a");
let last_usage_b = row_b.try_get::<i64, _>("last_usage").expect("last_usage b");
assert_eq!(last_usage_a, last_usage_b);
assert!(last_usage_a > 0);
let _ = tokio::fs::remove_dir_all(codex_home).await;
}
#[tokio::test]
async fn mark_stage1_job_succeeded_enqueues_global_consolidation() {
let codex_home = unique_temp_dir();
+37
View File
@@ -49,6 +49,43 @@ WHERE kind = ? OR kind = ?
Ok(())
}
/// Record usage for cited stage-1 outputs.
///
/// Each thread id increments `usage_count` by one and sets `last_usage` to
/// the current Unix timestamp. Missing rows are ignored.
pub async fn record_stage1_output_usage(
&self,
thread_ids: &[ThreadId],
) -> anyhow::Result<usize> {
if thread_ids.is_empty() {
return Ok(0);
}
let now = Utc::now().timestamp();
let mut tx = self.pool.begin().await?;
let mut updated_rows = 0;
for thread_id in thread_ids {
updated_rows += sqlx::query(
r#"
UPDATE stage1_outputs
SET
usage_count = COALESCE(usage_count, 0) + 1,
last_usage = ?
WHERE thread_id = ?
"#,
)
.bind(now)
.bind(thread_id.to_string())
.execute(&mut *tx)
.await?
.rows_affected() as usize;
}
tx.commit().await?;
Ok(updated_rows)
}
/// Selects and claims stage-1 startup jobs for stale threads.
///
/// Query behavior: