test(orchestrator): end-to-end integration tests for conversation persistence#1174
test(orchestrator): end-to-end integration tests for conversation persistence#1174geoffjay merged 2 commits intoissue-1162from
Conversation
… persistence
Adds tests/conversation_persistence.rs with 26 integration tests covering:
- Storage layer: since/until cursor filtering, combined time windows,
ascending ordering, session isolation, cross-agent delete isolation,
all-event-type round-trips, and metadata round-trips.
- REST API: GET /agents/{id}/conversation (events, limit/has_more,
event_type filter, session filter, after/before cursors, 404, empty),
GET summary, single-event retrieval with wrong-agent/unknown-id 404s,
DELETE /agents/{id}/conversation (204, 404, cross-agent isolation,
idempotent), and count accuracy.
Also adds DELETE /agents/{id}/conversation endpoint (204 No Content) to
api.rs and urlencoding dev-dependency to Cargo.toml.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This change is part of the following stack: Change managed by git-spice. |
geoffjay
left a comment
There was a problem hiding this comment.
Review: test(orchestrator): end-to-end integration tests for conversation persistence
Verdict: Approved. The DELETE endpoint implementation is clean and the 26 tests are thorough. All concerns are either informational or tied to parent PR fixes that must land before this merges.
✅ DELETE /agents/{id}/conversation — correct
async fn delete_agent_conversation(
State(state): State<ApiState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, ApiError> {
state.manager.get_agent(&id).await?.ok_or(ApiError::NotFound)?;
state.manager.agent_storage()
.delete_conversation_events_for_agent(id).await
.map_err(ApiError::Internal)?;
Ok(StatusCode::NO_CONTENT)
}- Agent existence check ✅
- Delegates to existing idempotent storage method ✅
- 204 No Content ✅
- Route combined on the existing
/conversationpath with correct Axum.delete()syntax ✅
✅ Test structure — solid throughout
NullBackendcorrectly implements allExecutionBackendtrait methods — tests compile without external dependencies ✅- Each test constructs its own
TempDir+ fresh migrated database — no shared state between tests ✅ build_app()drives the full Axum router viatower::ServiceExt::oneshot— exercises real routing, real serialization, real storage ✅urlencodingcorrectly handles RFC 3339 timestamps in query strings (:needs encoding) ✅
Coverage breakdown:
| Area | Tests |
|---|---|
since / until cursor filtering |
3 (individual + combined window) |
Ordering guarantee (ASC by created_at) |
1 |
| Session isolation | 1 |
| Cross-agent delete isolation (storage) | 1 |
| All 8 event-type variants round-trip | 1 |
| JSON metadata round-trip | 1 |
GET /conversation (basic, limit, event_type, session, after, before, 404, empty) |
8 |
GET /conversation/summary (counts + 404) |
2 |
GET /conversation/{event_id} (found, wrong-agent 404, not-found 404) |
3 |
DELETE /conversation (clears, 404, cross-agent isolation, idempotent) |
4 |
| count matches list length | 1 |
Stack note — deeply blocked
This PR is stacked on issue-1162, which depends on issue-1161 (PR #1170, needs-rework) → issue-1159 (PR #1167, needs-rework). None of the parent PRs can merge yet. No action needed on this PR until the parent chain is repaired.
🟡 Session filter tests don't catch the pagination bug flagged in #1170
test_storage_session_isolation has a comment that explicitly documents the in-memory approach:
// Filter in application layer as the API does.
let session_1: Vec<_> = all.iter().filter(|e| e.session_number == 1).collect();test_api_get_conversation_session_filter inserts 5 total events and uses the default limit (100), so all 5 are fetched before the in-memory retain. The test passes — but a variant with a small limit would fail under the current implementation. Once PR #1170 is fixed to push the session filter to the DB, add:
// After #1170 fix: session filter works correctly when limit < total events
async fn test_api_get_conversation_session_filter_under_limit() {
// insert 50 session-0 events + 3 session-1 events
// request ?session=1&limit=2 → should return 2 with has_more=true
}This test would currently fail; record as a post-fix TODO.
🟡 Minor scope note — DELETE handler belongs in #1170
delete_agent_conversation and its route registration are production code added in a test PR. They're correct and the co-location with the DELETE tests is pragmatic, but they would more naturally live alongside the other conversation endpoints in PR #1170.
Adds 26 integration tests in tests/conversation_persistence.rs covering the storage layer (cursor filtering, ordering, session isolation, all event types) and REST API (GET/DELETE conversation endpoints, pagination, 404 paths). Also implements the missing DELETE /agents/{id}/conversation endpoint (204 No Content) needed by the acceptance criteria.
Closes #1165