feat: complete Epic 1 production foundation

This commit is contained in:
2026-08-25 01:24:11 +03:00
parent 767428436d
commit 182bde8ac0
298 changed files with 35719 additions and 5299 deletions
@@ -1,8 +1,10 @@
use crank_registry::{
CreateInvocationLogRequest, InvocationHistoryLossCategory, InvocationHistoryWriteOutcome,
ListInvocationLogsQuery, UsageBucket, UsageQuery,
};
use sqlx::Row;
use super::common::{TestDatabase, test_invocation_log};
use super::common::{TestDatabase, test_invocation_log, test_operation, test_workspace_id};
#[tokio::test]
async fn invocation_history_write_returns_typed_loss_without_error_details() {
@@ -29,3 +31,115 @@ async fn invocation_history_write_returns_typed_loss_without_error_details() {
);
database.cleanup().await;
}
#[tokio::test]
#[ignore = "production-size query-plan evidence: inserts 1,000,000 invocation_logs rows"]
async fn production_size_invocation_history_queries_stay_bounded() {
let database = TestDatabase::new().await;
let registry = database.registry().await;
let pool = database.raw_pool().await;
let operation = test_operation("op_history_scale", 1, crank_core::OperationStatus::Draft);
registry
.create_operation(&test_workspace_id(), &operation, None)
.await
.unwrap();
sqlx::query(
r#"
insert into invocation_logs (
id, workspace_id, operation_id, operation_version, source, level, status,
tool_name, message, request_id, trace_id, status_code, duration_ms,
error_kind, execution_stage, execution_error_code, retryability, outcome_certainty,
request_preview_json, response_preview_json, created_at
)
select
'log_scale_' || series::text,
'ws_default',
'op_history_scale',
1,
'admin_test_run',
'info',
case when series % 10 = 0 then 'error' else 'ok' end,
'scale_tool',
'scale invocation',
'018f0000-0000-7000-8000-' || lpad(series::text, 12, '0'),
'0af7651916cd43dd8448eb211c80319c',
case when series % 10 = 0 then 500 else 200 end,
20 + (series % 250),
null,
'runtime',
case when series % 10 = 0 then 'runtime_internal' else null end,
'never',
'certain',
'{"input":"bounded"}'::jsonb,
'{"ok":true}'::jsonb,
'2026-03-25T00:00:00Z'::timestamptz + (series || ' seconds')::interval
from generate_series(1, 1000000) as series
"#,
)
.execute(&pool)
.await
.unwrap();
let page = registry
.list_invocation_logs(ListInvocationLogsQuery {
workspace_id: &test_workspace_id(),
level: None,
status: None,
outcome_group: None,
search_text: None,
source: None,
operation_id: Some(&operation.id),
agent_id: None,
created_after: Some("2026-03-25T00:00:00Z"),
created_before: Some("2026-04-06T00:00:00Z"),
cursor_created_at: None,
cursor_id: None,
limit: 101,
})
.await
.unwrap();
assert_eq!(page.len(), 101);
let summary = registry
.summarize_usage(UsageQuery {
workspace_id: &test_workspace_id(),
period: crank_core::UsagePeriod::Last7Days,
source: None,
created_after: "2026-03-25T00:00:00Z",
created_before: "2026-04-06T00:00:00Z",
bucket: UsageBucket::Day,
})
.await
.unwrap();
assert_eq!(summary.rollup.calls_total, 1_000_000);
let explain = sqlx::query(
r#"
explain
select id
from invocation_logs
where workspace_id = 'ws_default'
and operation_id = 'op_history_scale'
and created_at >= '2026-03-25T00:00:00Z'::timestamptz
and created_at < '2026-04-06T00:00:00Z'::timestamptz
order by created_at desc, id desc
limit 101
"#,
)
.fetch_all(&pool)
.await
.unwrap()
.into_iter()
.map(|row| row.get::<String, _>(0))
.collect::<Vec<_>>()
.join("\n");
assert!(
explain.contains("Index Scan") || explain.contains("Bitmap Index Scan"),
"{explain}"
);
assert!(!explain.contains("Seq Scan"), "{explain}");
database.cleanup().await;
}