Skip to content

fix: address remaining review findings — storage bugs, test coverage, and correctness issues#5

Merged
simonovic86 merged 3 commits intomainfrom
claude/practical-archimedes
Mar 10, 2026
Merged

fix: address remaining review findings — storage bugs, test coverage, and correctness issues#5
simonovic86 merged 3 commits intomainfrom
claude/practical-archimedes

Conversation

@simonovic86
Copy link
Owner

Summary

This PR addresses all remaining issues identified in the codebase audit, including critical bugs in storage layer, missing event recording, test coverage gaps, and API correctness issues.

Bugs Fixed

  • CancelByTag missing EventCancelled: Now records EventCancelled event in history (executor_api.go)
  • Postgres Find() ignores tag filters: Tags now properly translated to SQL WHERE conditions (storage/postgres.go)
  • Cleanup ignores DEAD_LETTER status: Dead-lettered commands now properly cleaned up in SQLite/Postgres (storage/sqlite.go, storage/postgres.go)
  • Workflow example duplicate Add call: Removed redundant Add(), properly set sequence via WithSequence() (examples/workflow/main.go)
  • NewFunc doc references wrong method: Fixed docstring to reference executor.Register() instead of nonexistent executor.Handle() (func.go)
  • Shutdown timeout returns nil: Stop() now returns error when shutdown times out (executor.go)
  • ContinueSequence shallow-copies data: Now uses deepCopyMap for nested map safety (instance.go)
  • FindPending doesn't filter by ReadyAt: All storage implementations (Memory, SQLite, Postgres) now filter ready_at <= now (storage/*.go)

Test Coverage Added

  • Dashboard API (322 lines): Tests for all 6+ HTTP endpoints — stats, commands, health, retry, cancel, history, index
  • DLQ functionality (197 lines): Tests for ReplayFromDLQ(), FindDeadLettered(), PurgeDLQ()
  • Middleware chains (152 lines): Tests for execution order, short-circuit, context passing
  • Rate limiter (265 lines): Tests for per-command limits, global limits, blocking acquire, concurrent access, middleware integration
  • Graceful shutdown (125 lines): Tests for timeout, double-stop, stop-before-start, add-after-stop
  • Polling worker mode (147 lines): Tests for basic execution, shutdown, retry on error
  • AddMany & CancelByTag (142 lines): Tests for bulk operations, partial failure, event recording
  • Stuck command recovery (144 lines): Tests for recovery of old commands, skip of recent commands, permanent commands
  • HookedStorage (224 lines): Tests for AfterCreate, AfterUpdate, AfterDelete, OnError, nil hooks

Refactoring

  • ROADMAP.md: Updated to mark all fixed issues as DONE

Impact

  • Fixes data consistency issues in SQLite and Postgres storage
  • Ensures event history completeness for audit trails
  • Significantly improves test coverage (1859 lines of new tests)
  • All critical path bugs now addressed

… and correctness issues

Fix bugs across all three storage backends (Memory, SQLite, Postgres):
- FindPending now filters by ReadyAt <= now to avoid returning commands not yet ready
- SQLite implements QueryableStorage with full Find() method including tag filtering
- Postgres Find() supports tag filters via JSONB contains operator
- Cleanup includes DEAD_LETTER status in all storage backends
- Fix missing argNum++ after CreatedBefore in Postgres Find
- Remove duplicate compile-time assertion in sqlite.go

Fix correctness issues in core:
- CancelByTag now records EventCancelled in command history
- ContinueSequence uses deepCopyMap to prevent shared nested references
- Stop() returns error on shutdown timeout instead of nil
- Workflow example consolidated duplicate Add call

Fix documentation:
- NewFunc doc corrected to reference executor.Register()

Add comprehensive test coverage for previously untested subsystems:
- Rate limiter (per-command, global, blocking, stats, concurrency)
- HookedStorage (AfterCreate, AfterUpdate, AfterDelete, OnError, nil hooks)
- Dead Letter Queue (move to DLQ, FindDeadLettered, ReplayFromDLQ, PurgeDLQ)
- Middleware chains (execution order, short-circuit, context passing)
- Graceful shutdown (timeout, double-stop, stop before start, add after stop)
- AddMany and CancelByTag (partial failure, event recording)
- Dashboard API (all HTTP endpoints via httptest)
- Stuck command recovery and permanent commands
- Polling worker mode (basic execution, shutdown, retry)

Update ROADMAP.md to reflect all completed items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5422b0b921

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +706 to +707
if query.Offset > 0 {
offsetClause = fmt.Sprintf("OFFSET %d", query.Offset)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard OFFSET with LIMIT in SQLite Find queries

When query.Offset > 0 and query.Limit == 0, this builds SQL with a standalone OFFSET clause (... ORDER BY ... OFFSET n), which SQLite rejects with a syntax error. That makes offset-only pagination fail for the new QueryableStorage implementation, even though the same query shape works in memory/postgres backends. Adding an implicit LIMIT -1 (or requiring Limit when Offset is set) would keep pagination behavior consistent and prevent runtime query failures.

Useful? React with 👍 / 👎.

for k, v := range i.Data {
data[k] = v
// Deep copy data to prevent shared nested references
data := deepCopyMap(i.Data)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid JSON copy when continuing sequence data

Switching ContinueSequence to deepCopyMap causes a JSON marshal/unmarshal round-trip on every chained command payload, which coerces non-JSON-native Go values (for example int64 precision-sensitive numbers, custom types, or time.Time) into different runtime types. This is a regression for in-memory execution paths that previously preserved exact value types across sequence steps, and can break handlers that rely on type assertions or high-precision numeric data.

Useful? React with 👍 / 👎.

simonovic86 and others added 2 commits March 10, 2026 20:56
…aveat

- Guard OFFSET with implicit LIMIT -1 in SQLite Find() to prevent
  syntax errors when offset is used without an explicit limit
- Add doc comment to ContinueSequence noting the JSON round-trip type
  coercion tradeoff (consistent with Clone() and storage serialization)
- Revert ROADMAP.md test coverage checkmarks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removes the final argNum++ after CreatedBefore in Postgres Find(),
which is never read again and flagged by golangci-lint (ineffassign).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@simonovic86 simonovic86 merged commit 9b50045 into main Mar 10, 2026
3 checks passed
@simonovic86 simonovic86 deleted the claude/practical-archimedes branch March 10, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant