Skip to content

feat(database-readwrite): add marko/database-readwrite package#86

Merged
markshust merged 1 commit into
developfrom
feature/database-readwrite
May 26, 2026
Merged

feat(database-readwrite): add marko/database-readwrite package#86
markshust merged 1 commit into
developfrom
feature/database-readwrite

Conversation

@markshust
Copy link
Copy Markdown
Collaborator

Summary

  • Adds marko/database-readwrite — an opt-in sibling driver package that decorates ConnectionInterface to route reads to replica connections and writes to a primary connection
  • Sticky writes (transaction-triggered + write-triggered, public resetStickyState())
  • Single-request fallback on replica failure (tries next replica on PDOException/MarkoException; throws loud ReadException when all exhausted)
  • Pluggable replica selection: RandomReplicaSelector (default) and WeightedReplicaSelector
  • Additive changes to marko/database: new ConnectionFactoryInterface, new DatabaseConfig::fromArray() static factory — zero existing API changes
  • Additive changes to marko/database-pgsql and marko/database-mysql: new {Driver}ConnectionFactory class + binding

Configuration

return [
    'driver' => 'readwrite',
    'connections' => [
        'write' => ['driver' => 'pgsql', 'host' => 'primary.db', /* ... */],
        'read' => [
            ['driver' => 'pgsql', 'host' => 'replica1.db', /* ... */],
            ['driver' => 'pgsql', 'host' => 'replica2.db', 'weight' => 3, /* ... */],
        ],
        'read_strategy' => 'random', // or 'weighted'
    ],
];

Test plan

  • Unit tests for ConnectionFactoryInterface, DatabaseConfig::fromArray(), PgSqlConnectionFactory, MySqlConnectionFactory
  • Unit tests for ReadWriteConnectionConfig validation (missing write, empty reads, invalid weights, unknown strategy)
  • Unit tests for RandomReplicaSelector and WeightedReplicaSelector (incl. proportional distribution)
  • Unit tests for ReadWriteConnection routing (query → replica, execute/prepare/lastInsertId → write, transaction delegation)
  • Unit tests for sticky-write state (write triggers, transaction triggers, resetStickyState, sticky persists after commit/rollback)
  • Unit tests for single-request fallback (try next replica on PDOException, throw ReadException when exhausted)
  • Module boot wiring tests (only activates with driver: 'readwrite', binds both ConnectionInterface and TransactionInterface, selector chosen by config)
  • Integration tests over pgsql and mysql config
  • Full suite: 5,366 tests pass (4 pre-existing unrelated SplitWorkflowTest failures only)
  • Docs page at docs/packages/database-readwrite.md + cross-doc updates to database.md, database-pgsql.md, database-mysql.md, .claude/architecture.md

Closes #4

🤖 Generated with Claude Code

Routes read queries to replica connections and write queries to a primary
connection, with sticky writes, single-request fallback on replica failure,
and pluggable replica selection (random default, weighted option). Closes #4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the enhancement New feature or request label May 26, 2026
@markshust markshust merged commit b5ab2c2 into develop May 26, 2026
1 check passed
@markshust markshust deleted the feature/database-readwrite branch May 26, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Read/Write connection splitting

1 participant