-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable the usage of withF
and withG
context for DB transactions and provide transactional iterators
#10
Conversation
In order to allow some streaming based functionality, we have to allow the creation of iterators inside the transaction. We will preserve the This means our snapshot needs to become an ordered key value structure. This means we are creating another temporary DB to be the snapshot. However I'm going to first just try with a sublevel. This would mean that there is a reserved area in the DB where transactions are working against, and this sublevel should never be used by any other places. |
The usage of the Furthermore we cannot just use snapshot sublevel, we would need to create a new sublevel for each snapshot that is bound to a transaction. Alternatively we forego using a snapshot level entirely and just use an in-memory ordered map structure, but that is its own can of worms. Most efficient would be:
|
These additional "root" sublevels can be extended to deal with automatic indexing #1 which would then supersede #2. Which would give us:
Then index sublevels can be accessed separately and managed separately. Additional relevant issue Level/subleveldown#111 Also I noticed that a |
The https://github.com/Level/abstract-level might be a good foundation for a new |
I've rolled up a bunch of issues in js-db into larger epic #11 that would be one big change to DB, that would be breaking relative to EFS and PK. So this PR will focus on just integrating |
The Furthermore the The |
The changes to
I'm creating |
I have a working prototype for the It is able to handle this sort of data:
|
Tests have been done for the transactional iterator. Now it's time to clean up the tests for the |
In this PR, we are removing the Having locks in the DB muddles the separation of responsibilities. It turns out our read-committed transactions doesn't actually need locking at all. You only need locks if you want to also prevent:
However this all depends on the end-user and their specific situation when using transactions. Sometimes they may use only simple mutexes, in other cases they need to use read/write locks, OCC, PCC... etc. So therefore locking functionality is removed from the DB. We are however using |
We now have tests for each isolation property:
And matches this table: |
withF
and withG
context to transactionswithF
and withG
context for DB transactions and provide transactional iterators
The You can use However that shouldn't be necessary either. We now expose:
And with that, the |
One issue is the difference in API between And the fact that I'm only supporting promise-API, like for |
The |
Rather than using the The APIs between This means later in #11, we should have: // root iterator at dataDb
DB.iterator(options);
// same
DB.iterator(options, []);
// down level 1
DB.iterator(options, ['level1']);
DB.iterator(options, ['level1', 'level2]);
DBTransaction.iterator(options, ['level1', 'level2']);
DB.count();
DB.count(['level1', 'level2']);
DBTransaction.count();
DBTransaction.count(['level1']);
DB.clear();
DB.clear(['level1']);
DBTransaction.clear(['level1']); // this should be a transactional clear, to do this, we must iterator and then do `db.del`
DB.get('key');
DB.get(['level1', 'key']);
// these are not allowed, or they are equivalent to asking for undefined
DB.get([]);
DB.get();
DB.put('key', 'value');
DB.put(['level1', 'key'], 'value');
DB.del('key');
DB.del(['level1', 'key']);
DBTransaction.del('key');
DBTransaction.del(['level1', 'key']); |
… `ResourceRelease` types * Provided `iterator` methods to `DB` and `DBTransaction` to enable transactional iterators * Remove `DB.withLocks` and `DB.transact` as advisory locking is now the responsibility of the user * Root sublevels have been created `data` and `transactions` * Transactions have isolation level and read-phenomena tests * New methods on DB: `iterator`, `clear`, `count`, `dump` * New methods on DBTransaction: `iterator`, `clear`, `count`, `dump`
bc12c0a
to
0584757
Compare
Still need to add |
0584757
to
bd00f2a
Compare
withF
and withG
context for DB transactions and provide transactional iteratorswithF
and withG
context for DB transactions and provide transactional iterators
Ok this is ready to merge. |
Description
The
withF
andwithG
generalises resource acquisition and release. The DB transaction is one of those resources. Since we share a DB being used in PK, having these methods would be useful.Long term, the
withF
andwithG
types and utility functions would be extracted into its own package likejs-context
so it can be shared.Over time this should replace the
DB.transact
andDB.withLocks
methods, and instead just provide theDB.transaction
method.The transactional iterator implementation follows the iterator on LevelDB including the exception behaviour like in
leveldown
andabstract-leveldown
packages. This is a stop-gap solution until we migrate the whole DB implementation overabstract-level
#11.Downstream packages EFS and PK will need to be updated.
Issues Fixed
Tasks
1. Use resource control functions for transactions (
withF
andwithG
) by integratingResourceAcquire
andResourceRelease
types into aDB.transaction
method.2. Add an
iterator
method intoTransaction
andDBTransaction
interface so that we can perform transactional iteration. This will still use theAbstractIterator
type, which is not currently up to date in upstream which will necessitate the usage of@ts-ignore
comments. See: [@types/level] iterator type is lacking `[Symbol.asyncIterator]()` DefinitelyTyped/DefinitelyTyped#59265- This iterator must act like a "overlay", in that writes in the transaction take priority over data that is currently in the DB.
3. Remove the methods
DB.withLocks
andDB.transact
as this uses locking code, and locks are not necessary for our read-committed isolation level transactions, advisory-locks for transactions are now up to the user to manage.4. Create root sublevels such as
data
andtransactions
and eventuallyindex
to support temporary state, so that users ofDB
will only be storing data underdata
sublevel.- This means that
db.db
shouldn't be used anymore, as the root of data is now indb.dataDb
, thedb.db
is the still the underlying root LevelDB database, but this shouldn't be used unless you're doing something hacky on the LevelDB database.5. Move
withF
andwithG
andResourceAcquire
andResourceRelease
types into@matrixai/resources
package, which will be used by PK as well and subsequently EFS.6. Add
Transaction.test.ts
to formally test theTransaction
class, and formalise the 4 isolation-levels vs read-phenomena properties into the tests.5. Removed
DBTransaction
interface, and renamedTransaction
class toDBTransaction
, this just simplifies the types6. Removed
AbstractIterator
in favour of our ownDBIterator
since the upstream type is out of date, and this avoids having users having to do// @ts-ignore
all the time.Final checklist