| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-08-30 | 4.8 kB | |
| v5.2.0 source code.tar.gz | 2026-08-30 | 955.2 kB | |
| v5.2.0 source code.zip | 2026-08-30 | 2.0 MB | |
| Totals: 3 Items | 2.9 MB | 0 | |
New Features
nitrite-bridge— inspect a running Nitrite database from a desktop client. The Nitrite adapter for thedbinspectwire protocol: collections and handed-in repositories as browsable stores, schema inferred by sampling documents and always flagged as inferred, paging overFindOptionsskip/limit/orderBy, the JSON filter DSL, and watch over Nitrite's collection subscription. The engine-neutral core it plugs into isorg.dizitart:dbinspect-bridge, which has no database in its dependency tree at all.- Row editing is behind
allowWrite, and whole-storesnapshotbehindallowSnapshot— bothfalseunless the embedding application asks, and absent from the reported capabilities while they are. A row is addressed by_id; an update is partial;changes: 0means the row was not there._idinside an update'svaluesis refused, because Nitrite merges an update document and it would rewrite the identity of the row it just matched. regexis off unlessallowRegexis set, and length-capped with a nested-quantifier check when it is on.java.util.regexbacktracks and a match cannot be interrupted, so the default is the mitigation that matters.- Every client-supplied store name is resolved against the set the adapter reported.
Nitrite.getCollectioncreates a collection that does not exist, so an unchecked name would let a paired client make one; writes go through the same allow-list. -
The module is deliberately absent from the reactor
<modules>:dbinspect-bridgeis not on Maven Central until the dbinspect release, so a build of a clean checkout would fail on it. Build it on its own, withdbinspect-bridgeinstalled locally. -
The bridge can open a transaction (
docs/PROTOCOL.md§3.1). A transaction is a second adapter over the same database rather than a mode on the first, so one connection's uncommitted documents can never reach another connection's reads. Nitrite's transaction lives above the storage engine — aTransactionStorebuffers the writes and a journal replays them on commit — so this works identically on MVStore, RocksDB and in memory. capabilities.transactionsfollowsallowWrite: that flag is the permission, this reports what the engine can undo. The transactional twin reports itfalse, because Nitrite does not nest one.listStorescounts through the transaction, since a total that left out the rows the person just staged is not read-your-own-writes.
Performance
- Paging a collection no longer costs every row before the page -
find(filter, skipBy(n).limit(m))now advances the storage iterator without decoding what it passes over. BoundedStreamskipped by callingnext()on the iterator beneath it, and that iterator is below the document layer: it deserialised every skipped document in order to throw it away. Page latency was therefore linear in the page number - about 9 µs per skipped row on both persistent stores - so a 50 000-row collection paged at 200 rows took 3 ms for the first page and 350 ms for the two-hundredth. It is an ordinary browse, not an edge case.- New
SkippableIterator, implemented by the storage-level iterators that can do better and by nothing else.BoundedStreamuses it when it is there and falls back to the loop when it is not, so a stream that has to look at a document to know whether to skip it - a collection-scan filter, a blocking sort - is unaffected and still correct. - MVStore descends the tree by index. An MVStore page records how many entries sit beneath it, so
MVMap.getKey(n)is a O(log n) descent rather than a scan; the skip seeks with it and continues from a cursor. Measured over 50 000 rows, 200 to a page: p95 583.9 ms → 5.8 ms, and the first and last pages now cost the same 0.1 ms. - RocksDB steps the native iterator. There is no seek-by-index to use, but the decode is what a skipped row actually cost; advancing past one is now a memcmp inside the block the iterator is already on. p95 3.8 ms over the same 50 000 rows.
- An index scan skips its own id set the same way, without the map lookup and decode
next()would have paid for each row.
Issue Fixes
- Fix the index dirty marker not being persisted (#1281)
markDirty()flippedisDirtyon theIndexMetathatget()returned and never put it back, so nothing told the store the entry had changed and the new value was not guaranteed to be written. BothbeginIndexing()andendIndexing()go through it, so the marker was unreliable in both directions: an index left half-built by a crash could come back reading as clean, and a completed one could stay marked dirty and be rebuilt on the first write after every open.