ffastdb 0.0.21
ffastdb: ^0.0.21 copied to clipboard
A high-performance, pure-Dart embedded NoSQL database with B-Tree indexes, WAL crash recovery, and reactive queries.
0.0.21 #
Bug Fixes (Index Corruption & Startup Reliability) #
- CRITICAL — Bug #1: Fixed
addSortedIndexandaddBitmaskIndexoverwriting already-loaded indexes with empty instances. Both methods now useputIfAbsentso that a persisted index loaded from disk by_loadIndexes()is preserved. The direct assignment caused every startup after the first to return empty query results and permanently corrupt the on-disk index. - GRAVE — Bug #2: Fixed race condition in
openDatabasewhereFfastDb.instancebecame accessible before secondary indexes were registered. Indexes are now passed intoFfastDb.init()and registered beforeopen()is called, so_loadIndexes()can match serialized blobs to the correct type and the singleton is never exposed in a half-initialized state. - GRAVE — Bug #3: Fixed
_loadIndexes()silently ignoring an index-type change between startups (e.g.HashIndex→SortedIndex). If the on-disk type differs from the pre-registered type the blob is now discarded; the index is rebuilt with the correct type via_rebuildSecondaryIndexes(), preventing silent O(n log n) degradation of range queries. - MODERATE — Bug #4: Fixed a single corrupt document aborting the entire startup.
_rebuildSecondaryIndexes()now wraps eachfindByIdcall in a try/catch; corrupt documents are skipped and will be cleaned up on the nextcompact(). - GRAVE — Bug #5a: Fixed O(n) memory allocation on every
startsWithquery withHashIndex._StartsWithConditionnow calls the newHashIndex.filterKeys()method, which iterates buckets without sorting or copying the full index, reducing per-query allocation from O(n) to O(k) where k is the number of matching documents. - GRAVE — Bug #5b: Changed the default
autoCompactThresholdfrom0(never compact) todouble.minPositive(compact as soon as any dead document exists). This prevents the WAL file from growing unboundedly and eliminates the associated RAM spike on startup caused by replaying months of historical writes.
0.0.20 #
Bug Fixes (Web Memory Crash) #
- CRITICAL (Web/IndexedDB): Rewrote
IndexedDbStorageStrategywith chunked incremental flush. Data is now stored as 64 KB chunks in IndexedDB;flush()only writes the chunks modified since the last flush. Previously everyinsert()/update()/delete()copied the entire database buffer (e.g. 50 MB) from Dart to JavaScript, causing peak memory of ~3× the DB size per flush and OOM crashes on large databases. Peak memory per flush is now O(64 KB) instead of O(DB size). - Web/IndexedDB: Backward-compatible migration — databases stored in the old single-key format (
<name>_buffer) are loaded transparently and migrated to the chunked format on the nextflush(). - Web/IndexedDB:
truncate()now cleans up orphan chunk keys in IndexedDB on the next flush, preventing stale data aftercompact(). - MemoryStorageStrategy:
truncate()now reclaims the backingUint8Listwhen the used size shrinks by more than 512 KB (matching the existing fix inWebStorageStrategyandIndexedDbStorageStrategy). Previously a database that grew to 64 MB and was compacted to 5 MB still held the 64 MB buffer in RAM. - Core: Eliminated redundant
storage.flush()calls in_insertImpl()and_updateImpl()whendataStorageis null (single-file mode). On web this avoided creating an unnecessary second IndexedDB transaction per operation. - Web: Reduced default
cacheCapacityinopenDatabase()from 256 to 64 pages (1 MB → 256 KB). On web the entire database is already in RAM, so a large LRU page cache is redundant overhead.
0.0.19 #
Bug Fixes (Memory) #
- OOM fix -
insertAll: Documents are now serialized and written to storage one at a time instead of accumulating all serializedUint8Listobjects in RAM before writing. For large batches (e.g. 100K × 1KB docs) this eliminates ~100MB of peak heap usage. - B-Tree node cache: Reduced
_nodeCacheCapacityfrom 4096 to 512 deserialized nodes, cutting the in-memory node object overhead from ~16MB to ~2MB. Hot nodes remain fast via the underlying LRU page cache. - BitmaskIndex: Default
maxDocIdreduced from 1,048,576 (128KB per bitset) to 65,536 (8KB per bitset). The index still grows automatically via_grow()when document IDs exceed the initial capacity, so behaviour is unchanged for large datasets. _BatchStateenum: Removed the now-unused state-machine enum that was part of the old two-passinsertAllimplementation.
0.0.18 #
Bug Fixes & Code Quality #
- Web/LocalStorage: Fixed
Uint8Listnot found compile error by adding missingdart:typed_dataimport (caused incomplete package analysis and 0/50 static analysis score on pub.dev). - Static analysis: Resolved all
lib/warnings and infos: removed unuseddart:js_interopimport, fixedreturn nullinvoidmethod, replacedLinkedHashMap()with collection literal, addedlibrary;directive toopen_database.dart, madeFieldConditionpublic (was_FieldCondition), fixed doc-comment angle brackets, and improvedprefer_is_emptyusage.
0.0.17 #
Bug Fixes (Web Memory) #
- Web/IndexedDB:
flush()now skips the IndexedDB put when no data has changed since the last flush (_dirtyflag). Eliminates redundant writes that fired 2-3× perinsert()/update()/delete()whenneedsExplicitFlushis true. - Web/IndexedDB:
flush()no longer creates an intermediate Dartsublist()copy of the buffer. A zero-copy typed-data view (buffer.asUint8List) is used instead, reducing the peak RAM during flush from 3× to 2× the database size. - Web/IndexedDB & WebStorageStrategy:
truncate()now releases the backingUint8Listwhen the used size shrinks by more than 512 KB (e.g. aftercompact()). Previously the oversized buffer was retained in RAM until the page reloaded. - Web/LocalStorage: Added
_dirtyflag (same flush-deduplication as IndexedDB) and overrides for bothwrite()andwriteSync(). - Web/LocalStorage:
flush()now catchesQuotaExceededError(the ~5 MBlocalStoragelimit) and throws a descriptiveStateErrorthat suggests switching touseIndexedDb: true, instead of silently losing data.
0.0.15 #
Bug Fixes #
- Web: Fixed
Function converted via 'toJS' contains invalid typescompiler error inIndexedDbStorageStrategyby removing an invalidasynckeyword from a JS interop closure.
0.0.14 #
Critical Bug Fixes #
- CRITICAL: Fixed
openDatabase()unconditionally callingFfastDb.disposeInstance()at the start of every call. This caused"Bad state: Cannot perform operations on a closed database"errors when multiple code paths (e.g., a BLoC and a repository) calledffastdb.init()concurrently during app startup. The function now reuses the live instance if one is already open. - CRITICAL (Web): Fixed
IndexedDbStorageStrategyusing the hardcoded key'db_buffer'for all database instances. Opening two databases (e.g.,'users'and'products') caused their data to collide in the same IndexedDB slot. Each database name now gets its own isolated key ('${name}_buffer').
New Features #
QueryBuilder.find()— executes a query and returns the full document list directly. No more manualfindByIdloop. Use viadb.query().where('field').equals('value').find().QueryBuilder.findFirst()— returns the first matching document ornull, resolving only one document ID for efficiency.QueryBuilder.count()— returns the count of matching documents with an O(1) hot path for simple equality queries on indexed fields (reads the index bucket size directly).FastDB.isOpengetter — exposes whether the database instance is currently usable.
Improvements #
- Improved error message for closed-database operations: now explains the three most common
causes and how to recover, instead of the previous generic
"Cannot perform operations...". EncryptedStorageStrategydoc comment updated with a clear security warning: it uses a Vigenère-style XOR cipher (obfuscation, not cryptographic-grade encryption). Guidance for using AES-256-GCM viaencrypt/pointycastleis included.- Barrel export (
package:ffastdb/ffastdb.dart) now includesEncryptedStorageStrategyand the platform-appropriate storage strategy (IoStorageStrategyon native,IndexedDbStorageStrategyon web) — no more imports of internalsrc/paths.
0.0.13 #
- solve wasm issues
0.0.12 #
- Fig minors issues
0.0.11 (unreleased) #
Critical Bug fixes #
- CRITICAL: Fixed database corruption on Android/iOS caused by using
FileMode.append. On mobile platforms,FileMode.appendignoressetPosition()calls and forces all writes to the end of the file, corrupting B-tree nodes that need to be updated at specific offsets. Now usesFileMode.writewhich correctly respects random-access writes.
API Changes #
- Restored public
FastDB()constructor for non-singleton use cases (benchmarks, multiple instances). For most applications, continue usingFfastDb.init()with the singleton pattern.
0.0.10 #
- fix package compatibility
0.0.9 #
- add meta
- fix library versions
0.0.8 #
- Fix Garbage collector issue
- Fix Firebase problems
0.0.7 #
- fix unsupported type fallbacks
0.0.6 #
- add serializable
0.0.5 #
- fix firebase bugs
0.0.4 #
- Fix persistence bug
0.0.3 #
- Fixed web bug
0.0.2 #
Bug fixes #
- Fixed corrupted documents being read silently from disk without checksum validation.
- Fixed database getting stuck when a batch insert fails halfway through.
- Fixed
compact()not actually freeing disk space in single-file mode. - Fixed index values greater than 2 billion being corrupted after a restart.
- Fixed memory growing unboundedly after many deletes or updates.
- Fixed nested
transaction()calls silently corrupting rollback state — now throws a clear error. - Fixed calling
beginTransaction()twice discarding pending writes silently — now throws a clear error. - Fixed
watch()streams accumulating in memory after all listeners are gone. - Fixed registering two adapters with the same
typeIdsilently overwriting the first one — now throws an error.
New features #
DateTimeis now supported natively — no more manual conversion needed.
Improvements #
- Queries are noticeably faster: the query planner no longer runs each condition twice to estimate cost.
startsWith()is now much faster on sorted indexes (uses a range scan instead of scanning everything).
0.0.1 #
- Pure Dart DB
- Type Adapters
- B-Tree primary index
- Multiplatform storage
- Index persistence
- Hash Index
- Sorted Index
- Bitmask Index
- CRUD Operations
- WAL crash recovery
- Transactions
- Schema migrations
- Fluent query builder
- Aggregations
- Reactive watchers
- Auto-compact
- First version