docs/rx-storage-memory-mapped.html
On this page
The memory mapped RxStorage is a wrapper around any other RxStorage. The wrapper creates an in-memory storage that is used for query and write operations. This memory instance is kept persistent with a given underlying storage.
awaitWritePersistence flag.10k documents.This plugin is part of RxDB Premium. It is not part of the default RxDB module.
import {
getRxStorageIndexedDB
} from 'rxdb-premium/plugins/storage-indexeddb';
import {
getMemoryMappedRxStorage
} from 'rxdb-premium/plugins/storage-memory-mapped';
/**
* Here we use the IndexedDB RxStorage as persistence storage.
* Any other RxStorage can also be used.
*/
const parentStorage = getRxStorageIndexedDB();
// wrap the persistent storage with the memory-mapped storage.
const storage = getMemoryMappedRxStorage({
storage: parentStorage
});
// create the RxDatabase like you would do with any other RxStorage
const db = await createRxDatabase({
name: 'myDatabase',
storage,
});
/ **...** /
By how the memory-mapped storage works, it is not possible to have the same storage open in multiple JavaScript processes. So when you use this in a browser application, you can not open multiple databases when the app is used in multiple browser tabs. To solve this, use the SharedWorker Plugin so that the memory-mapped storage runs inside of a SharedWorker exactly once and is then reused for all browser tabs.
If you have a single JavaScript process, like in a React Native app, you do not have to care about this and can just use the memory-mapped storage in the main process.
Normally RxDB is not capable of running queries on encrypted fields. But when you use the memory-mapped RxStorage, you can store the document data encrypted on disc, while being able to run queries on the not encrypted in-memory state. Make sure you use the encryption storage wrapper around the persistent storage, NOT around the memory-mapped storage as a whole.
import {
getRxStorageIndexedDB
} from 'rxdb-premium/plugins/storage-indexeddb';
import {
getMemoryMappedRxStorage
} from 'rxdb-premium/plugins/storage-memory-mapped';
import {
wrappedKeyEncryptionWebCryptoStorage
} from 'rxdb-premium/plugins/encryption-web-crypto';
const storage = getMemoryMappedRxStorage({
storage: wrappedKeyEncryptionWebCryptoStorage({
storage: getRxStorageIndexedDB()
})
});
const db = await createRxDatabase({
name: 'myDatabase',
storage,
});
/ **...** /
Running operations on the memory-mapped storage by default returns directly when the operation has run on the in-memory state and then persist changes in the background. Sometimes you might want to ensure write operations is persisted, you can do this by setting awaitWritePersistence: true.
const storage = getMemoryMappedRxStorage({
awaitWritePersistence: true,
storage: getRxStorageIndexedDB()
});
During cleanup, the memory-mapped storage will merge many small write-blocks into single big blocks for better initial load performance. The blockSizeLimit defines the maximum of how many documents get stored in a single block. The default is 10000.
const storage = getMemoryMappedRxStorage({
blockSizeLimit: 1000,
storage: getRxStorageIndexedDB()
});
When you switch from a "normal" persistent storage (like IndexedDB or SQLite) to the memory-mapped storage, you must migrate the data using the Storage Migrator. You cannot simply switch the storage adapter on an existing database because the memory-mapped storage uses a different internal data structure.
To provide the fast initial page load and low write latency, the memory-mapped storage saves data in a "blockchain-like" structure. Writes are appended in blocks rather than modifying the state in place. These blocks are lazily cleaned up and processed later when the CPU is idle (see Idle Functions).