* implemented stubbed IGraphContextService methods * feat: wire graph communication updates in ipc, mcp and cli * fix: fix call graph recall and add profiling coverage to graph calls sites * fix: fixes for work where we added agent navigation to graph tooling * fix(corpus): clean FTS and KG orphans on document delete * fix(repair): clean orphans, honor cancellation, surface stats * fix(rm): order content removal before metadata/KG delete. keep manifest while content is still referenced * fix(daemon): seed built-in content extractor for readiness * chore(cli): remove dead stubs and unwired helpers * feat(search): named-collection scoping + provable relevance gate * fix(refactor): rm dead stubs, inline simd, add proto/metrics tests * chore: rm dead interfaces/enums, consolidate guards, add tests * refactor: rm dr vaporware, collapse download handlers, clean list flags * docs: rm stale testing investigation logs * fix: address Copilot review findings from PR #50 - relationship_ops: return existing id when INSERT OR IGNORE skips - document_crud_ops: propagate FTS5 cleanup error (was silent skip) - builtin_text_content_extractor: unsigned char cast for tolower, add cctype - mcp_server download_jobs: validate job_id for status/cancel actions - list_command tests: unsigned char cast for isspace, add cctype include
81 lines
3.2 KiB
C++
81 lines
3.2 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
|
|
#include <yams/storage/sqlite_retry.h>
|
|
|
|
#include <sqlite3.h>
|
|
|
|
#include <chrono>
|
|
#include <string_view>
|
|
|
|
TEST_CASE("SQLite retry policy classifies transient lock failures", "[storage][sqlite][retry]") {
|
|
using namespace yams::storage::sqlite_retry;
|
|
|
|
CHECK(isBusyOrLocked(SQLITE_BUSY));
|
|
CHECK(isBusyOrLocked(SQLITE_LOCKED));
|
|
CHECK_FALSE(isBusyOrLocked(SQLITE_CONSTRAINT));
|
|
CHECK_FALSE(isBusyOrLocked(SQLITE_OK));
|
|
|
|
CHECK(isBusyOrLockedMessage("database is locked"));
|
|
CHECK(isBusyOrLockedMessage("SQLITE_BUSY: writer busy"));
|
|
CHECK_FALSE(isBusyOrLockedMessage("constraint failed"));
|
|
}
|
|
|
|
TEST_CASE("SQLite retry policy only retries FOREIGN KEY constraint failures",
|
|
"[storage][sqlite][retry]") {
|
|
using namespace yams::storage::sqlite_retry;
|
|
|
|
CHECK(isTransientConstraintMessage("FOREIGN KEY constraint failed"));
|
|
CHECK(isTransientConstraintMessage(
|
|
"Failed to execute statement: FOREIGN KEY constraint failed [SQL: INSERT ...]"));
|
|
|
|
CHECK_FALSE(isTransientConstraintMessage("UNIQUE constraint failed: documents.sha256_hash"));
|
|
CHECK_FALSE(isTransientConstraintMessage("NOT NULL constraint failed: documents.id"));
|
|
CHECK_FALSE(isTransientConstraintMessage("CHECK constraint failed: positive_size"));
|
|
CHECK_FALSE(isTransientConstraintMessage("constraint failed"));
|
|
CHECK_FALSE(isTransientConstraintMessage("database is locked"));
|
|
}
|
|
|
|
TEST_CASE("SQLite retry policy bounds exponential retry attempts", "[storage][sqlite][retry]") {
|
|
using namespace yams::storage::sqlite_retry;
|
|
|
|
const BusyRetryPolicy policy{3, std::chrono::milliseconds{7}};
|
|
CHECK(canRetry(SQLITE_BUSY, 0, policy));
|
|
CHECK(canRetry(SQLITE_LOCKED, 1, policy));
|
|
CHECK_FALSE(canRetry(SQLITE_BUSY, 2, policy));
|
|
CHECK_FALSE(canRetry(SQLITE_CONSTRAINT, 0, policy));
|
|
|
|
#if YAMS_LIBSQL_BACKEND
|
|
CHECK((metadataStatementPolicy().maxRetries == 2));
|
|
CHECK((vectorWritePolicy().maxRetries == 3));
|
|
#else
|
|
CHECK((metadataStatementPolicy().maxRetries == 3));
|
|
CHECK((vectorWritePolicy().maxRetries == 5));
|
|
#endif
|
|
}
|
|
|
|
TEST_CASE("SQLite retry policy tunes document update metadata bursts", "[storage][sqlite][retry]") {
|
|
using namespace yams::storage::sqlite_retry;
|
|
|
|
const auto readPolicy = metadataRepositoryQueryRetryPolicy("read", "client_search");
|
|
CHECK((readPolicy.maxRetries == 3));
|
|
CHECK((readPolicy.baseDelayMs == 25));
|
|
CHECK((readPolicy.maxDelayMs == 500));
|
|
|
|
const auto defaultWritePolicy =
|
|
metadataRepositoryQueryRetryPolicy("write", "bench_set_metadata_batch");
|
|
CHECK((defaultWritePolicy.maxRetries == 5));
|
|
CHECK((defaultWritePolicy.baseDelayMs == 25));
|
|
CHECK((defaultWritePolicy.maxDelayMs == 500));
|
|
|
|
const auto documentUpdatePolicy =
|
|
metadataRepositoryQueryRetryPolicy("write", "app_document_update_metadata");
|
|
CHECK((documentUpdatePolicy.maxRetries == 7));
|
|
CHECK((documentUpdatePolicy.baseDelayMs == 10));
|
|
CHECK((documentUpdatePolicy.maxDelayMs == 200));
|
|
|
|
const auto downloadMetadataPolicy =
|
|
metadataRepositoryQueryRetryPolicy("write", "app_download_metadata_burst");
|
|
CHECK((downloadMetadataPolicy.maxRetries == 2));
|
|
CHECK((downloadMetadataPolicy.baseDelayMs == 5));
|
|
CHECK((downloadMetadataPolicy.maxDelayMs == 10));
|
|
}
|