When I created RxDB, two years ago, there where some things that I did not consider and other things that I just decided wrong.
With the breaking version 8.0.0
I rewrote some parts of RxDB and changed the API a bit. The focus laid on better defaults and better performance.
Because the keyCompression was confusing and most users do not use it, it is now disabled by default. Also the naming was bad, so disableKeyCompression
is now renamed to keyCompression
which defaults to false
.
In the past, it was allowed to set an RxSchema
or an RxJsonSchema
as schema
-field when creating a collection. This was confusing and so it is now only allowed to use RxJsonSchema
.
In the past it was allowed to set a field as required by setting the boolean value required: true
.
This is against the json-schema-standard and will make problems when switching between different schema-validation-plugins. Therefore required fields must now be set via required: ['fieldOne', 'fieldTwo']
.
To be similar to mongoosejs, there was the possibility to set a documents value via myDoc.foo = 'bar'
and later call myDoc.save()
to persist these changes.
But there was the problem that we have no weak pointers in javascript and therefore we have to store all document-instances in a cache to run change-events on them and make them 'reactive'. To save memory-space, we reuse the same documents when they are used multiple times. This made it hard to determine what happens when multiple parts of an application used the setters at the same time. Also there was an undefined behavior what should happen when a field is changed via setter and also via replication before save()
was called.
myDoc.age = 50;
,myDoc.set('age', 50);
andmyDoc.save()
is no more allowed on non-temporary-documents- Instead, to change document-data, use
RxDocument.atomicUpdate()
orRxDocument.atomicSet()
orRxDocument.update()
. - The following document-methods no longer exist:
synced$
,resync()
When the middleware-hooks where created, the goal was to work equal then mongoose. But this is not possible because mongoose is more 'static' and its documents never change their attributes. RxDB is a reactive database and when the state on disc changes, the attributes of the document also change. This caused some undefined behavior especially with async middleware-hooks. To solve this, hooks now can only modify the plain data, not the RxDocument
itself.
myCollection.preSave(function(data, rxDocument) {
// to set age to 50 before saving, change the first parameter
data.age = 50;
}, false);
Because the BroadcastChannel-API is not usable in all browsers and also not in NodeJs, multiInstance-communication was hard. The hacky workaround was to use a pseudo-socket and regularly check if an other instance has emitted a RxChangeEvent
.
This was expensive because even when the database did nothing, we wasted disk-IO and CPU by handling this.
To solve this waste, I spend one month creating a module that polyfills the broadcast-channel-api so it works on old browsers, new browsers and even NodeJs. This does not only waste less resources but also has a lower latency. Also the module is used by more projects than RxDB which allows use the fix bugs and improve performance together.
In the past, the QueryChangeDetection had to be enabled by importing the QueryChangeDetection and calling a function on it. This was strange and also did not allow to toggle the QueryChangeDetection on specific databases.
Now we set the QueryChangeDetection by adding the boolean field queryChangeDetection: true
when creating the database.
const db = await RxDB.create({
name: 'heroesdb',
adapter: 'idb',
queryChangeDetection: false // <- queryChangeDetection (optional, default: false)
});
console.dir(db);
Because the fields of an RxDocument
are defined dynamically by the schema and we could not use the Proxy
-Object because it is not supported in IE11, there was one workaround used: Each time a document is created, all getters and setters where applied on it. This was expensive and now we use a different approach.
Once per collection, a custom RxDocument-prototype and constructor is created and each RxDocument of this collection is created with the constructor. This change is a rewrite internally and should not change anything for RxDB-users. If you use RxDB with vuejs, you might get some problems that can be fixed by upgrading vuejs to the latest version.
The inMemory-plugin was written with some wrong estimations. I rewrote it and added much more tests. Also awaitPersistence()
can now be used to check if all writes have already been replicated into the parent collection. Also RxCollection.watchForChanges()
got split out from the replication
-plugin into its own watch-for-changes
-plugin because it is used in the inMemory and the replication functionality.
(Tested with node 10.6.0 and the memory-adapter, lower is better)
Reproduce with npm run build:size
and npm run test:performance
7.7.1 | 8.0.0 | |
---|---|---|
Bundle-Size (Webpack+minify+gzip) | 110 kb | 101.962 kb |
Spawn 1000 databases with 5 collections each | 8744 ms | 9906 ms |
insert 2000 documents | 8006 ms | 5781 ms |
find 10.000 documents | 3202 ms | 1312 ms |