Skip to content

ARTEMIS-6333 Relational Database Persistence Storage - #6838

Draft
clebertsuconic wants to merge 3 commits into
apache:mainfrom
clebertsuconic:new-storage
Draft

clebertsuconic wants to merge 3 commits into
apache:mainfrom
clebertsuconic:new-storage

Conversation

@clebertsuconic

Copy link
Copy Markdown
Contributor

Motivation:

Artemis's append-only journal delivers outstanding throughput and
is the ideal choice when fast local storage is available. However,
many cloud and containerised deployments already operate managed
relational databases and would benefit from an alternative
persistence path that leverages that existing infrastructure —
simplifying operations, backup, and disaster recovery without
giving up the broker's asynchronous, non-blocking persistence
contract.

Modifications:

Introduce a new artemis-database-storage module that implements
the full broker persistence layer on top of JDBC, wired through
the existing StorageManager / PagingManager SPIs so no
protocol or core-broker code needs to change.

Key design choices:

  • Group-commit / write-coalescing: DataManager buffers incoming
    writes and a scheduled timer flushes them in a single JDBC
    transaction, amortising the most expensive part (network
    round-trip + fsync) across many operations — the same technique
    database engines use internally (e.g. InnoDB group commit).

  • Command pattern with heterogeneous batching: each DBData
    subclass (messages, references, addresses, queues, prepared-TX,
    generic KV) dispatches itself to the correct
    BatchableStatement; a single transaction can therefore mix
    inserts and deletes across different tables atomically.

  • Worker pool with dedicated connections: multiple DataWorker
    instances, each owning its own JDBC Connection and full set of
    PreparedStatements, cycle through a pool. BorrowedWorker
    adds a lease-based model for callers that need a connection for
    an extended sequence of operations.

  • Credit-based flow control: producers are throttled via a credit
    window so the broker cannot out-run the database.

  • Async write-behind with IOCompletion callbacks: callers never
    block on commit; each data item carries storeLineUp() /
    done() / onError() callbacks, preserving the same contract
    the journal already exposes.

  • Retry with reconnect: transient SQLExceptions are retried up
    to five times with connection re-establishment between attempts.

  • Database paging: DatabasePagingManager and
    DatabasePagingStoreImpl replace file-based paging when this
    store type is selected. AddressSizeLimiter is extracted from
    PagingStoreImpl so both the file and database paths share
    address-level flow control (max size, max messages, blocking,
    page-full rejection).

  • DatabaseStorageMessageReader provides cursor-based message
    reading from the database with configurable prefetch for queue
    consumption.

  • Six database dialects are supported out of the box: PostgreSQL,
    MySQL, Oracle, DB2, MS SQL Server, and HSQLDB, each with a
    dedicated SQLProvider handling type mappings and DDL
    differences.

  • AbstractStorageManager is extracted from
    AbstractJournalStorageManager so both the journal-backed and
    database-backed managers share common bookkeeping without
    duplication.

Tests cover every layer: statement-level (insert/delete/update per
entity), worker-level (retry, flow control, borrowed-worker
lifecycle), full integration (StorageManager round-trips, real
broker boot, cross-protocol, XA / prepared transactions), and
stress (concurrent producers under sustained load).

Result:

Operators now have a choice between the journal — which remains
the highest-throughput option for local storage — and a relational
database backend that integrates naturally with managed database
services, broadening the set of environments where Artemis can be
deployed with minimal operational overhead.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

@clebertsuconic
clebertsuconic force-pushed the new-storage branch 7 times, most recently from fc29f44 to 1470bb6 Compare October 29, 2026 01:12
Motivation:

Artemis's append-only journal delivers outstanding throughput and
is the ideal choice when fast local storage is available. However,
many cloud and containerised deployments already operate managed
relational databases and would benefit from an alternative
persistence path that leverages that existing infrastructure —
simplifying operations, backup, and disaster recovery without
giving up the broker's asynchronous, non-blocking persistence
contract.

Modifications:

Introduce a new `artemis-database-storage` module that implements
the full broker persistence layer on top of JDBC, wired through
the existing `StorageManager` / `PagingManager` SPIs so no
protocol or core-broker code needs to change.

Key design choices:

- Group-commit / write-coalescing: `DataManager` buffers incoming
  writes and a scheduled timer flushes them in a single JDBC
  transaction, amortising the most expensive part (network
  round-trip + fsync) across many operations — the same technique
  database engines use internally (e.g. InnoDB group commit).

- Command pattern with heterogeneous batching: each `DBData`
  subclass (messages, references, addresses, queues, prepared-TX,
  generic KV) dispatches itself to the correct
  `BatchableStatement`; a single transaction can therefore mix
  inserts and deletes across different tables atomically.

- Worker pool with dedicated connections: multiple `DataWorker`
  instances, each owning its own JDBC `Connection` and full set of
  `PreparedStatement`s, cycle through a pool.  `BorrowedWorker`
  adds a lease-based model for callers that need a connection for
  an extended sequence of operations.

- Credit-based flow control: producers are throttled via a credit
  window so the broker cannot out-run the database.

- Async write-behind with `IOCompletion` callbacks: callers never
  block on commit; each data item carries `storeLineUp()` /
  `done()` / `onError()` callbacks, preserving the same contract
  the journal already exposes.

- Retry with reconnect: transient `SQLException`s are retried up
  to five times with connection re-establishment between attempts.

- Database paging: `DatabasePagingManager` and
  `DatabasePagingStoreImpl` replace file-based paging when this
  store type is selected. `AddressSizeLimiter` is extracted from
  `PagingStoreImpl` so both the file and database paths share
  address-level flow control (max size, max messages, blocking,
  page-full rejection).

- `DatabaseStorageMessageReader` provides cursor-based message
  reading from the database with configurable prefetch for queue
  consumption.

- Six database dialects are supported out of the box: PostgreSQL,
  MySQL, Oracle, DB2, MS SQL Server, and HSQLDB, each with a
  dedicated `SQLProvider` handling type mappings and DDL
  differences.

- `AbstractStorageManager` is extracted from
  `AbstractJournalStorageManager` so both the journal-backed and
  database-backed managers share common bookkeeping without
  duplication.

Tests cover every layer: statement-level (insert/delete/update per
entity), worker-level (retry, flow control, borrowed-worker
lifecycle), full integration (StorageManager round-trips, real
broker boot, cross-protocol, XA / prepared transactions), and
stress (concurrent producers under sustained load).

Result:

Operators now have a choice between the journal — which remains
the highest-throughput option for local storage — and a relational
database backend that integrates naturally with managed database
services, broadening the set of environments where Artemis can be
deployed with minimal operational overhead.

Assisted-By: Claude Opus 4.6 <noreply@anthropic.com>
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