ReaxDB class final

A ReaxDB database instance.

The single write pipeline (class invariant)

EVERY mutation this class performs — put, putBatch, delete, deleteBatch, typed collection writes, query-driven update/delete, TTL reclamation and post-commit maintenance for transactions — flows through one private method, _applyMutations. That method applies, in this exact order:

  1. build the write ops: the document/value op plus every secondary index op returned by IndexManager.buildIndexOps;
  2. StorageEngine.writeBatch(ops) — the WAL append inside it is the DURABILITY POINT; nothing observable happens before it succeeds;
  3. optional durability escalation for a per-write sync override;
  4. cache update or invalidation (plaintext record envelopes only, never ciphertext, and never before step 2 — a failed write can therefore never leave a phantom cache entry);
  5. change-event publication on the ChangeStreamHub.

No other code path in this library writes to the storage engine on behalf of a user mutation. Transactions are the one two-phase case: the transaction manager owns the atomic batch (steps 1-2 for the document values), and this class runs index maintenance, cache invalidation and event publication from the returned CommitResult immediately afterwards. Index updates for transactional writes are therefore durable in a second batch that follows the commit, not in the same one; see MIGRATION.md.

Key space

Keys are UTF-8 byte strings. Byte 0x00 is reserved as the first byte of ReaxDB's internal key space (secondary index postings and index metadata), so a user key must not start with it; such keys are rejected with InvalidKeyException. Documents addressed by the query layer use the collection:id key shape.

Available extensions

Properties

cacheStats → CacheStatistics
Live cache statistics.
no setter
changes → ReactiveStream
A ReactiveStream over every change in the database.
no setter
changeStream → Stream<DatabaseChangeEvent>
The ReaxDB 1.x stream of every change event.
no setter
encryptionInfo → Map<String, dynamic>
Metadata describing the EFFECTIVE encryption configuration.
no setter
hashCode → int
The hash code for this object.
no setterinherited
isClosed → bool
Whether close has completed.
no setter
keepsInMemory → bool
Whether this database was opened with keepInMemory: true.
no setter
logger → ReaxLogger
This database's logger. Closed by close.
no setter
path → String
Absolute path of the database directory.
no setter
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
schemaVersion → int
Schema version currently recorded in the database header.
no setter
storageStats → StorageStats
Live storage engine counters.
no setter
syncMode → SyncMode
Default durability level applied to writes.
no setter
transactionStats → TransactionStats
Live transaction statistics.
no setter

Methods

changePassphrase(String newPassphrase, {int iterations = KeyDerivation.defaultIterations}) → Future<ReaxDB>
Changes the passphrase of a database encrypted with EncryptionConfig.aes256FromPassphrase, or encrypts a database that was not, and returns it opened with the new passphrase. See rekey.
close() → Future<void>
Closes the database.
collection<T>(String name, {required T fromJson(Map<String, dynamic> json), required Map<String, dynamic> toJson(T value)}) → ReaxCollection<T>
Returns a typed view of name that stores instances of T.
compact() → Future<void>
Compacts the on-disk tables, reclaiming space from overwritten and deleted keys.
compareAndSwap<T>(String key, T? expectedValue, T newValue, {Duration? ttl, DateTime? expiresAt}) → Future<bool>
Atomically sets key to newValue only if it currently holds expectedValue, returning whether the swap happened.
createIndex(String collection, List<String> fields) → Future<void>
Creates a secondary index over fields of collection and backfills it from existing documents. A single-element list creates a plain index; two or more fields create a compound index in that significance order.
delete(String key, {SyncMode? sync}) → Future<void>
Removes key. Deleting an absent key is a no-op that still emits an event, because the post-state (absent) is what observers care about.
deleteBatch(List<String> keys, {SyncMode? sync}) → Future<void>
Removes every key in keys in one atomic batch.
dropIndex(String collection, List<String> fields) → Future<void>
Drops the index over fields of collection.
exists(String key) → Future<bool>
Whether a live (non-expired) entry exists for key.
exportTo(String archivePath, {EncryptionConfig encryption = const EncryptionConfig.none()}) → Future<int>
Writes a consistent snapshot of this database to archivePath.
flush() → Future<void>
Persists the in-memory write buffer to disk and checkpoints the WAL.
get<T>(String key) → Future<T?>
Reads the value stored under key, or null when absent or expired.
getBatch<T>(List<String> keys) → Future<Map<String, T?>>
Reads several keys, returning null for those absent or expired.
getDatabaseInfo() → Future<DatabaseInfo>
The ReaxDB 1.x name for info.
getEncryptionInfo() → Map<String, dynamic>
The ReaxDB 1.x name for encryptionInfo.
getPerformanceStats() → Map<String, dynamic>
Performance counters, in the shape 1.x used.
getStatistics() → Future<Map<String, dynamic>>
The ReaxDB 1.x name for statistics.
getSync<T>(String key) → T?
Reads key synchronously, or null when absent or expired.
hasIndex(String collection, String field) → bool
Whether an index exists whose leading field is field.
info() → Future<DatabaseInfo>
Returns a description of this database.
keys({String? prefix, int? limit, bool reverse = false}) → Stream<String>
Streams keys in order, optionally restricted to those starting with prefix. Values are not decoded.
listIndexes([String? collection]) → List<IndexDefinition>
All index definitions, optionally restricted to collection.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
purgeExpired() → Future<int>
Removes every entry whose TTL has elapsed and returns how many were reclaimed. Expired entries already read as absent; this reclaims their storage eagerly instead of waiting for the next read of each key.
put(String key, Object? value, {Duration? ttl, DateTime? expiresAt, SyncMode? sync}) → Future<void>
Stores value under key.
putBatch(Map<String, Object?> entries, {Duration? ttl, DateTime? expiresAt, SyncMode? sync}) → Future<void>
Stores every pair of entries in one atomic batch.
query(String collection) → QueryBuilder
Returns a query builder over the documents of collection.
range<T>(String startKey, String endKey, {int? limit, bool reverse = false}) → Future<List<ReaxEntry<T>>>
Returns the entries with keys in [startKey, endKey).
rekey(EncryptionConfig newEncryption) → Future<ReaxDB>
Re-encrypts every value with newEncryption and returns the database opened with it. This instance is closed.
scan<T>({String? startKey, String? endKey, int? limit, bool reverse = false}) → Stream<ReaxEntry<T>>
Streams entries in key order.
scanPrefix<T>(String prefix, {int? limit, bool reverse = false}) → Stream<ReaxEntry<T>>
Streams every entry whose key starts with prefix.
statistics() → Map<String, dynamic>
Aggregated live statistics for cache, storage and transactions.
stream(String keyPattern) → Stream<DatabaseChangeEvent>
The ReaxDB 1.x name for watch.
toString() → String
A string representation of this object.
inherited
transaction<T>(Future<T> body(ReaxTransaction tx), {IsolationLevel? isolationLevel, int maxAttempts = 3}) → Future<T>
Runs body in an ACID transaction, committing on success.
watch(String pattern) → Stream<DatabaseChangeEvent>
Streams change events whose key matches pattern.
watchCollection(String collection) → Stream<DatabaseChangeEvent>
Streams change events for the documents of collection.
watchKey(String key) → Stream<DatabaseChangeEvent>
Streams change events for exactly key.
watchPattern(String pattern) → ReactiveStream
The ReaxDB 1.x name for watch, as a ReactiveStream.
watchPrefix(String prefix) → Stream<DatabaseChangeEvent>
Streams change events for keys starting with prefix.
watchQuery(QueryBuilder query, {Duration debounce = const Duration(milliseconds: 50), bool distinct = true}) → Stream<List<Map<String, dynamic>>>

Available on ReaxDB, provided by the ReaxWatchQuery extension

Runs query now and again after every change to its collection.
where(String collection, String field, Object? value) → Future<List<Map<String, dynamic>>>
Shorthand for an equality query over collection.

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

closeAll() → Future<void>
Closes every database open in this isolate. Intended for tests.
encodeKey(String key) → Uint8List
Encodes a user key, rejecting the reserved internal key space.
importFrom({required String archivePath, required String path, EncryptionConfig encryption = const EncryptionConfig.none(), EncryptionConfig? archiveEncryption, SyncMode syncMode = SyncMode.full, bool overwrite = false}) → Future<ReaxDB>
Restores the archive at archivePath into a database at path.
inspect1x(String path) → Future<LegacyDatabaseInfo?>
Describes the ReaxDB 1.x database at path, or null when path is not one (it is already a 2.0 database, empty, or unrecognised).
migrateFrom1x({required String sourcePath, String? targetPath, String? legacyEncryptionKey, EncryptionConfig encryption = const EncryptionConfig.none(), void onProgress(int migrated, int total)?}) → Future<MigrationReport>
Migrates the ReaxDB 1.x database at sourcePath into a 2.0 database.
open({required String path, EncryptionConfig encryption = const EncryptionConfig.none(), SyncMode syncMode = SyncMode.full, int memtableSizeBytes = 4 * 1024 * 1024, int cacheMaxEntries = 10000, int cacheMaxMemoryBytes = 64 * 1024 * 1024, Duration? cacheDefaultTtl, int changeStreamBufferSize = ChangeStreamHub.defaultMaxBufferedEvents, bool keepInMemory = false, LogLevel logLevel = LogLevel.warning, List<LogOutput>? logOutputs, String? loggerName, IsolationLevel defaultIsolationLevel = IsolationLevel.readCommitted, Duration lockTimeout = const Duration(seconds: 10), int schemaVersion = 1, FutureOr<void> onUpgrade(int from, int to, ReaxDB db)?, LegacyMigrationMode legacyMigration = LegacyMigrationMode.detect, String? legacyEncryptionKey, DatabaseConfig? config, String? encryptionKey}) → Future<ReaxDB>
Opens (or creates) the database stored in the directory path.
openLegacy(String name, {DatabaseConfig? config, String? encryptionKey, String? path, LegacyMigrationMode legacyMigration = LegacyMigrationMode.detect, String? legacyEncryptionKey}) → Future<ReaxDB>
The ReaxDB 1.x open call shape: a positional database name plus config, encryptionKey and path.
quickStart(String name) → Future<SimpleReaxDB>
The ReaxDB 1.x shortcut for simple.
simple(String name, {String? path, EncryptionConfig encryption = const EncryptionConfig.none(), SyncMode syncMode = SyncMode.full, bool encrypted = false}) → Future<SimpleReaxDB>
Opens a database with a simplified API and safe defaults.

Constants

archiveMagic → const int
Magic header of a ReaxDB export archive: "RXDB".
archiveVersion → const int
Format version of the export archive written by exportTo. importFrom also restores version 1 archives written by 2.0.
headerFileName → const String
Name of the database header file inside a database directory.
lockFileName → const String
Name of the on-disk lock file inside a database directory.