refactor(audit): implement async audit recording to unblock event pipeline #1279

Merged
freemo merged 1 commits from feature/async-audit-recording into master 2026-04-02 17:00:54 +00:00

1 Commits

Author SHA1 Message Date
freemo 5cc9b67a3b refactor(audit): implement async audit recording to unblock event pipeline
CI / lint (pull_request) Failing after 18s
CI / quality (pull_request) Successful in 44s
CI / unit_tests (pull_request) Failing after 6s
CI / integration_tests (pull_request) Failing after 1s
CI / e2e_tests (pull_request) Failing after 1s
CI / build (pull_request) Failing after 2s
CI / security (pull_request) Successful in 1m5s
CI / helm (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 3m57s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
Implements a write-behind queue with a background daemon thread in
AuditService so that record() returns immediately without blocking the
calling domain operation on a synchronous SQLite INSERT + COMMIT.

Changes:
- AuditService: add _writer_loop(), _write_payload(), flush() methods
  and a write-behind queue (queue.Queue) with a background thread.
  record() enqueues the payload and returns a placeholder entry with
  id=-1 in async mode; the background thread persists entries in order.
  close() calls flush() to drain the queue before closing the session,
  ensuring no data loss under normal operation.
- Async mode is only active when the service owns its session (no
  injected session), because SQLite connections are thread-local.
  Tests that inject a session automatically fall back to sync mode.
- Settings: add audit_async (default True) and audit_queue_maxsize
  (default 10000) fields with env-var aliases.
- Existing tests updated to use audit_async=False (sync mode) via
  injected sessions — behaviour is unchanged.
- New BDD feature: features/async_audit_recording.feature with 20
  scenarios covering non-blocking record(), flush(), close(), context
  manager, ordering guarantees, sync fallback, and settings defaults.

Ordering guarantees (best-effort):
  Entries are written in enqueue order by the single background thread.
  created_at timestamps are set at enqueue time so they reflect the
  logical event time regardless of write latency.

Backward compatibility:
  The public API of AuditService is unchanged. Callers that need the
  real database id immediately should use audit_async=False or call
  flush() after record(). The placeholder id=-1 signals pending
  persistence.

ISSUES CLOSED: #718
2026-04-02 08:42:33 +00:00