Skip to content

Commit

Permalink
FIX #3319 graphql checkpoint not removed after database.remove()
Browse files Browse the repository at this point in the history
  • Loading branch information
pubkey committed Sep 20, 2021
1 parent 90646a5 commit 544f466
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 18 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ examples/react-native
examples/vanilla
examples/vue
examples/svelte
examples/react/build
node_modules
docs
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Other:
- Added svelte example [#3287](https://github.com/pubkey/rxdb/pull/3287) Thanks [@bkeating](https://github.com/bkeating)
- Improved error messages

Bugfixes:
- [#3319](https://github.com/pubkey/rxdb/issues/3319) Graphql replication checkpoint was not deleted after running `RxDatabase.remove()`

### 10.0.3 (9 August 2021)

Bugfixes:
Expand Down
17 changes: 16 additions & 1 deletion src/plugins/pouchdb/rx-storage-pouchdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,16 @@ export class RxStorageInstancePouch<RxDocType> implements RxStorageInstance<
const doc: RxDocumentData<RxDocType> = change.operation === 'DELETE' ? change.previous as any : change.doc as any;
const primaryPath = getPrimaryFieldOfPrimaryKey(this.schema.primaryKey);
const primary: string = (doc as any)[primaryPath];

// TODO remove this check because this should never happen
if (!primary) {
console.log('----');
console.dir(this.schema);
console.dir(change);
console.dir(doc);
throw new Error('primary missing (' + primaryPath + ')');
}

const eventId = getEventKey(false, primary, doc._rev);

if (this.emittedEventIds.has(eventId)) {
Expand Down Expand Up @@ -1211,12 +1221,17 @@ export function pouchStripLocalFlagFromPrimary(str: string): string {
return str.substring(POUCHDB_LOCAL_PREFIX.length);
}

export function getEventKey(isLocal: boolean, primary: string, revision: string): string {
export function getEventKey(
isLocal: boolean,
primary: string,
revision: string
): string {

// TODO remove this check this should never happen
if (!primary) {
throw new Error('primary missing !!');
}

const prefix = isLocal ? 'local' : 'non-local';
const eventKey = prefix + '|' + primary + '|' + revision;
return eventKey;
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/replication-graphql/crawling-checkpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ export async function getChangesSinceLastPushSequence<RxDocType>(

const pullLastDocumentId = (endpointHash: string) => GRAPHQL_REPLICATION_PLUGIN_IDENT + '-pull-checkpoint-' + endpointHash;

export async function getLastPullDocument(
collection: RxCollection,
export async function getLastPullDocument<RxDocType>(
collection: RxCollection<RxDocType>,
endpointHash: string
) {
): Promise<RxDocType | null> {
const localDoc = await findLocalDocument<any>(
collection.localDocumentsStore,
pullLastDocumentId(endpointHash)
Expand Down
7 changes: 6 additions & 1 deletion src/rx-collection-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ export function fillObjectDataBeforeInsert(
return useJson;
}


export function getCollectionLocalInstanceName(collectionName: string): string {
return collectionName + '-local';
}

/**
* Creates the storage instances that are used internally in the collection
*/
Expand Down Expand Up @@ -161,7 +166,7 @@ export async function createRxCollectionStorageInstances<RxDocumentType, Interna
* so that the local docs can be kept while deleting the normal instance
* after migration.
*/
collectionName + '-local',
getCollectionLocalInstanceName(collectionName),
instanceCreationOptions
)
]);
Expand Down
36 changes: 23 additions & 13 deletions src/rx-database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
newRxError
} from './rx-error';
import {
createRxSchema
createRxSchema, getPrimaryFieldOfPrimaryKey
} from './rx-schema';
import {
isRxChangeEventIntern,
Expand Down Expand Up @@ -60,7 +60,7 @@ import {
} from './rx-storage-helper';
import type { RxBackupState } from './plugins/backup';
import { getPseudoSchemaForVersion } from './rx-schema-helper';
import { createRxCollectionStorageInstances } from './rx-collection-helper';
import { createRxCollectionStorageInstances, getCollectionLocalInstanceName } from './rx-collection-helper';

/**
* stores the used database names
Expand Down Expand Up @@ -708,20 +708,30 @@ export async function removeRxDatabase(
const docs = await getAllDocuments(storageInstance.internalStore);
await Promise.all(
docs
.map(colDoc => colDoc.collectionName)
.map(async (id: string) => {
.map(async (colDoc) => {
const id = colDoc.collectionName;
const schema = colDoc.schema
const split = id.split('-');
const name = split[0];
const collectionName = split[0];
const version = parseInt(split[1], 10);
const instance = await storage.createStorageInstance<InternalStoreDocumentData>(
{
const primaryPath = getPrimaryFieldOfPrimaryKey(schema.primaryKey);
const [instance, localInstance] = await Promise.all([
storage.createStorageInstance<InternalStoreDocumentData>(
{
databaseName,
collectionName,
schema: getPseudoSchemaForVersion(version, primaryPath as any),
options: {}
}
),
storage.createKeyObjectStorageInstance(
databaseName,
collectionName: name,
schema: getPseudoSchemaForVersion(version, 'collectionName'),
options: {}
}
);
return instance.remove();
getCollectionLocalInstanceName(collectionName),
{}
)
]);

await Promise.all([instance.remove(), localInstance.remove()]);
})
);

Expand Down
20 changes: 20 additions & 0 deletions test/unit/replication-graphql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,26 @@ describe('replication-graphql.test.js', () => {

c.database.destroy();
});
it('#3319 database.remove() should delete the last-pull document', async () => {
const dbName = randomCouchString(12);
const c = await humansCollection.createHumanWithTimestamp(1, dbName);
const doc = await c.findOne().exec(true);
let docData = doc.toJSON(true);
docData = clone(docData); // clone to make it mutateable
(docData as any).name = 'foobar';

await setLastPullDocument(c, endpointHash, docData);
await c.database.remove();


// recreate the same collection again
const c2 = await humansCollection.createHumanWithTimestamp(1, dbName);
// there should be no pull document now
const ret = await getLastPullDocument(c2, endpointHash);
assert.strictEqual(ret, null);

c2.database.destroy();
});
});
});
describe('browser', () => {
Expand Down

0 comments on commit 544f466

Please sign in to comment.