From 5ffb7515043e26c7df3a48d5a27d8146d67332be Mon Sep 17 00:00:00 2001 From: pubkey <8926560+pubkey@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:51:34 +0100 Subject: [PATCH 1/3] The amount of collections in the open source version has been limited to `16` --- docs-src/docs/releases/16.0.0.md | 3 +- docs-src/docs/rx-collection.md | 11 +++++ docs-src/src/pages/premium-submitted.tsx | 11 +++-- src/plugins/dev-mode/dev-mode-tracking.ts | 10 +---- src/plugins/dev-mode/error-messages.ts | 3 ++ .../rx-storage-instance-dexie.ts | 9 ++-- src/plugins/utils/index.ts | 1 + src/plugins/utils/utils-global.ts | 3 -- src/plugins/utils/utils-premium.ts | 37 +++++++++++++++ src/rx-collection.ts | 45 ++++++++++++++++++- test/unit/attachments.test.ts | 8 +++- test/unit/hooks.test.ts | 14 +++--- test/unit/last.test.ts | 15 ++++++- test/unit/migration-schema.test.ts | 16 +++---- test/unit/orm.test.ts | 2 +- test/unit/population.test.ts | 3 ++ test/unit/rx-collection.test.ts | 35 ++++++++++++++- test/unit/rx-pipeline.test.ts | 14 +++--- 18 files changed, 192 insertions(+), 48 deletions(-) create mode 100644 src/plugins/utils/utils-premium.ts diff --git a/docs-src/docs/releases/16.0.0.md b/docs-src/docs/releases/16.0.0.md index d546241d1c1..2ac6d334ca1 100644 --- a/docs-src/docs/releases/16.0.0.md +++ b/docs-src/docs/releases/16.0.0.md @@ -71,9 +71,10 @@ I completely rewrote them and improved performance especially on initial load wh - If the handler of a [RxPipeline](../rx-pipeline.md) throws an error, block the whole pipeline and emit the error to the outside. - Throw error when dexie.js RxStorage is used with optional index fields [#6643](https://github.com/pubkey/rxdb/pull/6643#issuecomment-2505310082). -## Minor things +## Other - Added more [performance tests](https://rxdb.info/rx-storage-performance.html) +- The amount of collections in the open source version has been limited to `16`. - Moved RxQuery checks into dev-mode. - RxQuery.remove() now internally does a bulk operation for better performance. - Lazily process bulkWrite() results for less CPU usage. diff --git a/docs-src/docs/rx-collection.md b/docs-src/docs/rx-collection.md index 87a86afa67c..d461f901791 100644 --- a/docs-src/docs/rx-collection.md +++ b/docs-src/docs/rx-collection.md @@ -316,3 +316,14 @@ const is = isRxCollection(myObj); You have to call the `addCollections()` method each time you create your database. This will create the JavaScript object instance of the RxCollection so that you can use it in the RxDatabase. The persisted data will be automatically in your RxCollection each time you create it. +
+ How to remove the limit of 16 collections? +
+ In the open-source version of RxDB, the amount of RxCollections that can exist in parallel is limited to `16`. + To remove this limit, you can purchase the [Premium Plugins](/premium) and call the `setPremiumFlag()` function before creating a database: + ```ts + import { setPremiumFlag } from 'rxdb-premium/plugins/shared'; + setPremiumFlag(); + ``` +
+
diff --git a/docs-src/src/pages/premium-submitted.tsx b/docs-src/src/pages/premium-submitted.tsx index e8048fc15ab..bd7ada8dc0c 100644 --- a/docs-src/src/pages/premium-submitted.tsx +++ b/docs-src/src/pages/premium-submitted.tsx @@ -18,8 +18,13 @@ export default function PremiumSubmitted() { const database = await getDatabase(); const formValueDoc = await database.getLocal(FORM_VALUE_DOCUMENT_ID); console.dir(formValueDoc); + + window.trigger( + 'premium_lead', + Math.floor(formValueDoc._data.data.price / 3) // assume lead-to-sale-rate is 33%. + ); if (!formValueDoc) { - window.trigger('premium_lead_unknown', 300); + window.trigger('premium_lead_unknown', 0); await database.upsertLocal(FORM_VALUE_DOCUMENT_ID, { formSubmitted: true }); @@ -30,9 +35,9 @@ export default function PremiumSubmitted() { } window.trigger( 'premium_lead_' + formValueDoc._data.data.homeCountry.toLowerCase(), - Math.floor(formValueDoc._data.data.price / 3) // assume lead-to-sale-rate is 33%. + 0, // zero because we track the value already at the previous event trigger ); - await formValueDoc.incrementalPatch({formSubmitted: true}); + await formValueDoc.incrementalPatch({ formSubmitted: true }); } })(); }); diff --git a/src/plugins/dev-mode/dev-mode-tracking.ts b/src/plugins/dev-mode/dev-mode-tracking.ts index 426eed9db83..56e9d6b6914 100644 --- a/src/plugins/dev-mode/dev-mode-tracking.ts +++ b/src/plugins/dev-mode/dev-mode-tracking.ts @@ -1,9 +1,7 @@ import type { RxDatabase } from '../../types'; import { - PREMIUM_FLAG_HASH, - RXDB_UTILS_GLOBAL, RXDB_VERSION, - defaultHashSha256 + hasPremiumFlag } from '../utils/index.ts'; @@ -29,11 +27,7 @@ export async function addDevModeTrackingIframe(db: RxDatabase) { // do not show if premium flag is set. - if ( - RXDB_UTILS_GLOBAL.premium && - typeof RXDB_UTILS_GLOBAL.premium === 'string' && - (await defaultHashSha256(RXDB_UTILS_GLOBAL.premium) === PREMIUM_FLAG_HASH) - ) { + if (await hasPremiumFlag()) { return; } diff --git a/src/plugins/dev-mode/error-messages.ts b/src/plugins/dev-mode/error-messages.ts index b10cb38a5f8..59333775305 100644 --- a/src/plugins/dev-mode/error-messages.ts +++ b/src/plugins/dev-mode/error-messages.ts @@ -4,6 +4,8 @@ * This is mainly because error-string are hard to compress and we need a smaller build */ +import { NON_PREMIUM_COLLECTION_LIMIT } from '../utils/utils-premium.ts'; + export const ERROR_MESSAGES = { // util.js / config @@ -102,6 +104,7 @@ export const ERROR_MESSAGES = { COL21: 'The RxCollection is closed or removed already, either from this JavaScript realm or from another, like a browser tab', CONFLICT: 'Document update conflict. When changing a document you must work on the previous revision', COL22: '.bulkInsert() and .bulkUpsert() cannot be run with multiple documents that have the same primary key', + COL23: 'In the open-source version of RxDB, the amount of collections that can exist in parrallel is limited to '+NON_PREMIUM_COLLECTION_LIMIT+'. If you already purchased the premium access, you can remove this limit: https://rxdb.info/rx-collection.html#faq', // rx-document.js DOC1: 'RxDocument.get$ cannot get observable of in-array fields because order cannot be guessed', diff --git a/src/plugins/storage-dexie/rx-storage-instance-dexie.ts b/src/plugins/storage-dexie/rx-storage-instance-dexie.ts index 8eef365c01d..36d9a02d8e9 100644 --- a/src/plugins/storage-dexie/rx-storage-instance-dexie.ts +++ b/src/plugins/storage-dexie/rx-storage-instance-dexie.ts @@ -7,7 +7,8 @@ import { ensureNotFalsy, defaultHashSha256, RXDB_UTILS_GLOBAL, - PREMIUM_FLAG_HASH + PREMIUM_FLAG_HASH, + hasPremiumFlag } from '../utils/index.ts'; import type { RxStorageInstance, @@ -82,11 +83,7 @@ export class RxStorageInstanceDexie implements RxStorageInstance< if ( !shownNonPremiumLog && - ( - !RXDB_UTILS_GLOBAL.premium || - typeof RXDB_UTILS_GLOBAL.premium !== 'string' || - (await defaultHashSha256(RXDB_UTILS_GLOBAL.premium) !== PREMIUM_FLAG_HASH) - ) + !(await hasPremiumFlag()) ) { console.warn( [ diff --git a/src/plugins/utils/index.ts b/src/plugins/utils/index.ts index 4f3f41355fb..8601b46bae6 100644 --- a/src/plugins/utils/index.ts +++ b/src/plugins/utils/index.ts @@ -16,3 +16,4 @@ export * from './utils-time.ts'; export * from './utils-other.ts'; export * from './utils-rxdb-version.ts'; export * from './utils-global.ts'; +export * from './utils-premium.ts'; diff --git a/src/plugins/utils/utils-global.ts b/src/plugins/utils/utils-global.ts index 5eab44ee107..32b5f72b1f8 100644 --- a/src/plugins/utils/utils-global.ts +++ b/src/plugins/utils/utils-global.ts @@ -3,6 +3,3 @@ * can be imported and mutated at will. */ export const RXDB_UTILS_GLOBAL: any = {}; - - -export const PREMIUM_FLAG_HASH = '6da4936d1425ff3a5c44c02342c6daf791d266be3ae8479b8ec59e261df41b93'; diff --git a/src/plugins/utils/utils-premium.ts b/src/plugins/utils/utils-premium.ts new file mode 100644 index 00000000000..2a6b53a8235 --- /dev/null +++ b/src/plugins/utils/utils-premium.ts @@ -0,0 +1,37 @@ +import { RXDB_UTILS_GLOBAL } from './utils-global.ts'; +import { defaultHashSha256 } from './utils-hash.ts'; +import { PROMISE_RESOLVE_FALSE } from './utils-promise.ts'; + +export const PREMIUM_FLAG_HASH = '6da4936d1425ff3a5c44c02342c6daf791d266be3ae8479b8ec59e261df41b93'; +export const NON_PREMIUM_COLLECTION_LIMIT = 16; + +let hasPremiumPromise: Promise = PROMISE_RESOLVE_FALSE; +let premiumChecked = false; + +/** + * Here we check if the premium flag has been set. + * This code exists in the open source version of RxDB. + * Yes you are allowed to fork the repo and just overwrite this function. + * However you might better spend this time developing your real project + * and supporting the RxDB efforts by buying premium. + */ +export async function hasPremiumFlag() { + if (premiumChecked) { + return hasPremiumPromise; + } + premiumChecked = true; + + hasPremiumPromise = (async () => { + if ( + RXDB_UTILS_GLOBAL.premium && + typeof RXDB_UTILS_GLOBAL.premium === 'string' && + (await defaultHashSha256(RXDB_UTILS_GLOBAL.premium) === PREMIUM_FLAG_HASH) + ) { + return true; + } else { + return false; + } + })(); + + return hasPremiumPromise; +} diff --git a/src/rx-collection.ts b/src/rx-collection.ts index 46cae230268..edf82420187 100644 --- a/src/rx-collection.ts +++ b/src/rx-collection.ts @@ -12,7 +12,9 @@ import { ensureNotFalsy, getFromMapOrThrow, PROMISE_RESOLVE_FALSE, - PROMISE_RESOLVE_VOID + PROMISE_RESOLVE_VOID, + NON_PREMIUM_COLLECTION_LIMIT, + hasPremiumFlag } from './plugins/utils/index.ts'; import { fillObjectDataBeforeInsert, @@ -112,6 +114,8 @@ const HOOKS_KEYS = ['insert', 'save', 'remove', 'create'] as const; type HookKeyType = typeof HOOKS_KEYS[number]; let hooksApplied = false; +export const OPEN_COLLECTIONS = new Set>(); + export class RxCollectionBase< InstanceCreationOptions, RxDocumentType = { [prop: string]: any; }, @@ -157,6 +161,13 @@ export class RxCollectionBase< filter(changeEventBulk => changeEventBulk.collectionName === this.name) ); } else { } + + + /** + * Must be last because the hooks might throw on dev-mode + * checks and we do not want to have broken collections here. + */ + OPEN_COLLECTIONS.add(this); } get insert$(): Observable> { @@ -215,6 +226,35 @@ export class RxCollectionBase< public onRemove: (() => MaybePromise)[] = []; public async prepare(): Promise { + + if (!(await hasPremiumFlag())) { + + /** + * When used in a test suite, we often open and close many databases with collections + * while not awaiting the database.close() call to improve the test times. + * So when reopening collections and the OPEN_COLLECTIONS size is full, + * we retry after some times to account for this. + */ + let count = 0; + while (count < 10 && OPEN_COLLECTIONS.size > NON_PREMIUM_COLLECTION_LIMIT) { + count++; + await this.promiseWait(30); + } + if (OPEN_COLLECTIONS.size > NON_PREMIUM_COLLECTION_LIMIT) { + throw newRxError('COL23', { + database: this.database.name, + collection: this.name, + args: { + existing: Array.from(OPEN_COLLECTIONS.values()).map(c => ({ + db: c.database ? c.database.name : '', + c: c.name + })) + } + }); + } + } + + this.storageInstance = getWrappedStorageInstance( this.database, this.internalStorageInstance, @@ -880,6 +920,8 @@ export class RxCollectionBase< return PROMISE_RESOLVE_FALSE; } + OPEN_COLLECTIONS.delete(this); + await Promise.all(this.onClose.map(fn => fn())); @@ -1114,6 +1156,7 @@ export function createRxCollection( * we yet have to close the storage instances. */ .catch(err => { + OPEN_COLLECTIONS.delete(collection); return storageInstance.close() .then(() => Promise.reject(err as Error)); }); diff --git a/test/unit/attachments.test.ts b/test/unit/attachments.test.ts index 3d73f569d05..5481c6793cd 100644 --- a/test/unit/attachments.test.ts +++ b/test/unit/attachments.test.ts @@ -28,8 +28,14 @@ import { createBlobFromBase64, createBlob, blobToString, - RxDocumentWriteData + RxDocumentWriteData, + addRxPlugin } from '../../plugins/core/index.mjs'; +import { RxDBMigrationSchemaPlugin } from '../../plugins/migration-schema/index.mjs'; +addRxPlugin(RxDBMigrationSchemaPlugin); +import { RxDBUpdatePlugin } from '../../plugins/update/index.mjs'; +addRxPlugin(RxDBUpdatePlugin); + const STATIC_FILE_SERVER_URL = 'http://localhost:18001/'; diff --git a/test/unit/hooks.test.ts b/test/unit/hooks.test.ts index 93962f7bb2a..869fd77d182 100644 --- a/test/unit/hooks.test.ts +++ b/test/unit/hooks.test.ts @@ -19,8 +19,8 @@ import { } from '../../plugins/core/index.mjs'; -describeParallel('hooks.test.js', () => { - describe('get/set', () => { +describe('hooks.test.js', () => { + describeParallel('get/set', () => { it('should set a hook', async () => { const c = await humansCollection.create(0); c.preSave(function () { }, false); @@ -43,7 +43,7 @@ describeParallel('hooks.test.js', () => { c.database.close(); }); }); - describe('insert', () => { + describeParallel('insert', () => { describe('pre', () => { describe('positive', () => { it('series', async () => { @@ -182,7 +182,7 @@ describeParallel('hooks.test.js', () => { }); }); }); - describe('save', () => { + describeParallel('save', () => { describe('pre', () => { describe('positive', () => { it('series', async () => { @@ -308,7 +308,7 @@ describeParallel('hooks.test.js', () => { describe('negative', () => { }); }); }); - describe('remove', () => { + describeParallel('remove', () => { describe('pre', () => { describe('positive', () => { it('series', async () => { @@ -469,7 +469,7 @@ describeParallel('hooks.test.js', () => { describe('negative', () => { }); }); }); - describe('postCreate', () => { + describeParallel('postCreate', () => { describe('positive', () => { it('should define a getter', async () => { const db = await createRxDatabase({ @@ -523,7 +523,7 @@ describeParallel('hooks.test.js', () => { }); }); }); - describe('issues', () => { + describeParallel('issues', () => { it('ISSUE #158 : Throwing error in async preInsert does not prevent insert', async () => { const c = await humansCollection.create(0); c.preInsert(async function () { diff --git a/test/unit/last.test.ts b/test/unit/last.test.ts index be9b27da8d0..9bfd21fec33 100644 --- a/test/unit/last.test.ts +++ b/test/unit/last.test.ts @@ -3,7 +3,8 @@ import { waitUntil } from 'async-test-util'; import { dbCount, BROADCAST_CHANNEL_BY_TOKEN, - getFromMapOrThrow + getFromMapOrThrow, + OPEN_COLLECTIONS } from '../../plugins/core/index.mjs'; import config from './config.ts'; @@ -42,6 +43,18 @@ describe('last.test.ts (' + config.storage.name + ')', () => { it('ensure every db is cleaned up', () => { assert.strictEqual(dbCount(), 0); }); + it('ensure all collections are closed', async () => { + try { + await waitUntil(() => { + return OPEN_COLLECTIONS.size === 0; + }, 5 * 1000); + } catch (err) { + const openCollections = Array.from(OPEN_COLLECTIONS.values()).map(c => c.name); + console.log('open collection names:'); + console.log(openCollections.join(', ')); + throw new Error('not all collections have been closed (' + openCollections.length + ')'); + } + }); it('ensure all BroadcastChannels are closed', async () => { try { await waitUntil(() => { diff --git a/test/unit/migration-schema.test.ts b/test/unit/migration-schema.test.ts index b14dd2c0c2d..437e8a6bd03 100644 --- a/test/unit/migration-schema.test.ts +++ b/test/unit/migration-schema.test.ts @@ -35,7 +35,7 @@ import { ensureReplicationHasNoErrors } from '../../plugins/test-utils/index.mjs import { SimpleHumanAgeDocumentType } from '../../src/plugins/test-utils/schema-objects.ts'; -describeParallel('migration-schema.test.ts', function () { +describe('migration-schema.test.ts', function () { this.timeout(1000 * 10); if ( !config.storage.hasPersistence || @@ -49,7 +49,7 @@ describeParallel('migration-schema.test.ts', function () { addRxPlugin(RxDBAttachmentsPlugin); } - describe('.create() with migrationStrategies', () => { + describeParallel('.create() with migrationStrategies', () => { describe('positive', () => { it('ok to create with strategies', async () => { const db = await createRxDatabase({ @@ -201,7 +201,7 @@ describeParallel('migration-schema.test.ts', function () { }); }); }); - describe('getOldCollectionMeta()', () => { + describeParallel('getOldCollectionMeta()', () => { it('should NOT get an older version', async () => { const colName = 'human'; const db = await createRxDatabase({ @@ -266,7 +266,7 @@ describeParallel('migration-schema.test.ts', function () { db2.close(); }); }); - describe('migration basics', () => { + describeParallel('migration basics', () => { describe('.remove()', () => { it('should delete the old storage instance with all its content', async () => { if (!config.storage.hasMultiInstance) { @@ -406,7 +406,7 @@ describeParallel('migration-schema.test.ts', function () { }); }); }); - describe('integration into collection', () => { + describeParallel('integration into collection', () => { describe('run', () => { it('should auto-run on creation', async () => { const col = await humansCollection.createMigrationCollection( @@ -594,7 +594,7 @@ describeParallel('migration-schema.test.ts', function () { }); }); }); - describe('RxDatabase.migrationStates()', () => { + describeParallel('RxDatabase.migrationStates()', () => { it('should emit the ongoing migration state', async () => { const db = await createRxDatabase({ name: randomToken(10), @@ -643,7 +643,7 @@ describeParallel('migration-schema.test.ts', function () { db.close(); }); }); - describe('migration and replication', () => { + describeParallel('migration and replication', () => { it('should have migrated the replication state', async () => { const remoteDb = await createRxDatabase({ name: 'remote' + randomToken(10), @@ -767,7 +767,7 @@ describeParallel('migration-schema.test.ts', function () { await remoteDb.close(); }); }); - describe('issues', () => { + describeParallel('issues', () => { it('#212 migration runs into infinity-loop', async () => { const dbName = randomToken(10); const schema0 = { diff --git a/test/unit/orm.test.ts b/test/unit/orm.test.ts index 7bf64ca1d80..69d8dc555d1 100644 --- a/test/unit/orm.test.ts +++ b/test/unit/orm.test.ts @@ -83,7 +83,7 @@ describeParallel('orm.test.js', () => { } }), 'RxError', - reserved[t] + 'COL17' ); t++; } diff --git a/test/unit/population.test.ts b/test/unit/population.test.ts index c499c9c56d9..6e816f9100f 100644 --- a/test/unit/population.test.ts +++ b/test/unit/population.test.ts @@ -8,11 +8,14 @@ import { createRxSchema, RxJsonSchema, defaultHashSha256, + addRxPlugin, } from '../../plugins/core/index.mjs'; import { humansCollection, randomStringWithSpecialChars } from '../../plugins/test-utils/index.mjs'; +import { RxDBQueryBuilderPlugin } from '../../plugins/query-builder/index.mjs'; +addRxPlugin(RxDBQueryBuilderPlugin); describeParallel('population.test.js', () => { diff --git a/test/unit/rx-collection.test.ts b/test/unit/rx-collection.test.ts index 431fc0f28f0..1e0403e7f9f 100644 --- a/test/unit/rx-collection.test.ts +++ b/test/unit/rx-collection.test.ts @@ -39,7 +39,9 @@ import { getFromMapOrThrow, RxCollectionCreator, parseRevision, - getChangedDocumentsSince + getChangedDocumentsSince, + hasPremiumFlag, + NON_PREMIUM_COLLECTION_LIMIT } from '../../plugins/core/index.mjs'; import { RxDBUpdatePlugin } from '../../plugins/update/index.mjs'; @@ -107,6 +109,37 @@ describe('rx-collection.test.ts', () => { db.close(); }); }); + describe('negative', () => { + it('if not premium, it should limit the collections amount', async () => { + if ((await hasPremiumFlag())) { + return; + } + const db = await createRxDatabase({ + name: randomToken(10), + storage: config.storage.getStorage(), + }); + let t = NON_PREMIUM_COLLECTION_LIMIT + 1; + await assertThrows( + async () => { + while (t > 0) { + await db.addCollections({ + ['human_' + t]: { + schema: schemas.human, + options: { + foo: 'bar' + } + } + }); + t--; + } + }, + 'RxError', + 'COL23' + ); + + await db.close(); + }) + }); }); describeParallel('.checkCollectionName()', () => { describe('positive', () => { diff --git a/test/unit/rx-pipeline.test.ts b/test/unit/rx-pipeline.test.ts index fb0c0c3e18a..756dadc4fa4 100644 --- a/test/unit/rx-pipeline.test.ts +++ b/test/unit/rx-pipeline.test.ts @@ -22,14 +22,14 @@ import { RxDBLeaderElectionPlugin } from '../../plugins/leader-election/index.mj import { assertThrows } from 'async-test-util'; addRxPlugin(RxDBLeaderElectionPlugin); -describeParallel('rx-pipeline.test.js', () => { +describe('rx-pipeline.test.js', () => { if ( config.storage.name.includes('random-delay') ) { // TODO return; } - describe('basics', () => { + describeParallel('basics', () => { it('add and remove a pipeline', async () => { const c1 = await humansCollection.create(0); await c1.database.waitForLeadership(); @@ -150,7 +150,7 @@ describeParallel('rx-pipeline.test.js', () => { c2.database.close(); }); }); - describe('.awaitIdle()', () => { + describeParallel('.awaitIdle()', () => { it('should have updated its internal timestamps', async () => { const c1 = await humansCollection.create(0); await c1.database.waitForLeadership(); @@ -175,7 +175,7 @@ describeParallel('rx-pipeline.test.js', () => { c2.database.close(); }); }); - describe('error handling', () => { + describeParallel('error handling', () => { it('should not swallow the error if the handler throws', async () => { const c1 = await humansCollection.create(0); await c1.database.waitForLeadership(); @@ -223,7 +223,7 @@ describeParallel('rx-pipeline.test.js', () => { c2.database.close(); }); }); - describe('checkpoints', () => { + describeParallel('checkpoints', () => { it('should continue from the correct checkpoint', async () => { const dbName = randomToken(10); const identifier = randomToken(10); @@ -249,7 +249,7 @@ describeParallel('rx-pipeline.test.js', () => { await c1.database.close(); }); }); - describe('multiInstance', () => { + describeParallel('multiInstance', () => { if ( !config.storage.hasMultiInstance // config.storage.name === 'remote' // TODO @@ -323,7 +323,7 @@ describeParallel('rx-pipeline.test.js', () => { c2.database.close(); }); }); - describe('transactional behavior', () => { + describeParallel('transactional behavior', () => { it('should not block reads/writes that come from inside the pipeline handler', async () => { const c1 = await humansCollection.create(0); await c1.database.waitForLeadership(); From 5d0c2956dbff8982befa2d45da32122123eb82ac Mon Sep 17 00:00:00 2001 From: pubkey <8926560+pubkey@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:04:08 +0100 Subject: [PATCH 2/3] FIX tests --- src/plugins/dev-mode/error-messages.ts | 2 +- src/rx-collection.ts | 6 +++++- test/unit/last.test.ts | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/plugins/dev-mode/error-messages.ts b/src/plugins/dev-mode/error-messages.ts index 59333775305..3ef84905678 100644 --- a/src/plugins/dev-mode/error-messages.ts +++ b/src/plugins/dev-mode/error-messages.ts @@ -104,7 +104,7 @@ export const ERROR_MESSAGES = { COL21: 'The RxCollection is closed or removed already, either from this JavaScript realm or from another, like a browser tab', CONFLICT: 'Document update conflict. When changing a document you must work on the previous revision', COL22: '.bulkInsert() and .bulkUpsert() cannot be run with multiple documents that have the same primary key', - COL23: 'In the open-source version of RxDB, the amount of collections that can exist in parrallel is limited to '+NON_PREMIUM_COLLECTION_LIMIT+'. If you already purchased the premium access, you can remove this limit: https://rxdb.info/rx-collection.html#faq', + COL23: 'In the open-source version of RxDB, the amount of collections that can exist in parallel is limited to '+NON_PREMIUM_COLLECTION_LIMIT+'. If you already purchased the premium access, you can remove this limit: https://rxdb.info/rx-collection.html#faq', // rx-document.js DOC1: 'RxDocument.get$ cannot get observable of in-array fields because order cannot be guessed', diff --git a/src/rx-collection.ts b/src/rx-collection.ts index edf82420187..0aa0a531c5e 100644 --- a/src/rx-collection.ts +++ b/src/rx-collection.ts @@ -166,8 +166,12 @@ export class RxCollectionBase< /** * Must be last because the hooks might throw on dev-mode * checks and we do not want to have broken collections here. + * RxCollection instances created for testings do not have a database + * so we do not add these to the list. */ - OPEN_COLLECTIONS.add(this); + if (this.database) { + OPEN_COLLECTIONS.add(this); + } } get insert$(): Observable> { diff --git a/test/unit/last.test.ts b/test/unit/last.test.ts index 9bfd21fec33..696bb813272 100644 --- a/test/unit/last.test.ts +++ b/test/unit/last.test.ts @@ -49,9 +49,9 @@ describe('last.test.ts (' + config.storage.name + ')', () => { return OPEN_COLLECTIONS.size === 0; }, 5 * 1000); } catch (err) { - const openCollections = Array.from(OPEN_COLLECTIONS.values()).map(c => c.name); - console.log('open collection names:'); - console.log(openCollections.join(', ')); + const openCollections = Array.from(OPEN_COLLECTIONS.values()).map(c => ({ c: c.name, db: c.database ? c.database.name : '' })); + console.log('open collectios:'); + console.dir(openCollections); throw new Error('not all collections have been closed (' + openCollections.length + ')'); } }); From 1cc7fcc21de536072789077bebd375bc32cb6806 Mon Sep 17 00:00:00 2001 From: pubkey <8926560+pubkey@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:09:53 +0100 Subject: [PATCH 3/3] FIX lint --- src/rx-collection.ts | 2 +- test/unit/rx-collection.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rx-collection.ts b/src/rx-collection.ts index 0aa0a531c5e..36c1ddbf54b 100644 --- a/src/rx-collection.ts +++ b/src/rx-collection.ts @@ -164,7 +164,7 @@ export class RxCollectionBase< /** - * Must be last because the hooks might throw on dev-mode + * Must be last because the hooks might throw on dev-mode * checks and we do not want to have broken collections here. * RxCollection instances created for testings do not have a database * so we do not add these to the list. diff --git a/test/unit/rx-collection.test.ts b/test/unit/rx-collection.test.ts index 1e0403e7f9f..d3b701ac293 100644 --- a/test/unit/rx-collection.test.ts +++ b/test/unit/rx-collection.test.ts @@ -138,7 +138,7 @@ describe('rx-collection.test.ts', () => { ); await db.close(); - }) + }); }); }); describeParallel('.checkCollectionName()', () => {