Skip to content

Commit 4232468

Browse files
authored
TEST for no-push-after-reload (#7353)
* ADD test * REMOVE exit * FIX test * FIX lint * ADD changelog
1 parent 6ffd6af commit 4232468

4 files changed

Lines changed: 95 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# RxDB Changelog
33

44
<!-- CHANGELOG NEWEST -->
5+
- FIX "when a push handler is interrupted mid-way by a reload, after the reload retry doesn't happen" [via discord](https://discord.com/channels/969553741705539624/1059149217718861935/threads/1407063219062702111)
56
- FIX query hanging after local document inserted [#7349](https://github.com/pubkey/rxdb/pull/7349)
67
<!-- ADD new changes here! -->
78

src/replication-protocol/upstream.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ export async function startReplicationUpstream<RxDocType, CheckpointType>(
218218
* Merge/filter all open tasks
219219
*/
220220
const docs: RxDocumentData<RxDocType>[] = [];
221-
let checkpoint: CheckpointType = {} as any;
221+
let checkpoint: CheckpointType | undefined;
222222
while (openTasks.length > 0) {
223223
const taskWithTime = ensureNotFalsy(openTasks.shift());
224224
/**
@@ -255,7 +255,7 @@ export async function startReplicationUpstream<RxDocType, CheckpointType>(
255255

256256
await persistToMaster(
257257
docs,
258-
checkpoint
258+
checkpoint as any
259259
);
260260

261261
// might have got more tasks while running persistToMaster()

src/rx-storage-helper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ export function observeSingle<RxDocType>(
118118
* the document state from some, but not all shards.
119119
*/
120120
export function stackCheckpoints<CheckpointType>(
121-
checkpoints: CheckpointType[]
121+
checkpoints: (CheckpointType | undefined)[]
122122
): CheckpointType {
123123
return Object.assign(
124124
{},
125-
...checkpoints
125+
...checkpoints.filter(x => !!x)
126126
);
127127
}
128128

test/unit/replication.test.ts

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import type {
6262
RxStorage,
6363
RxStorageDefaultCheckpoint
6464
} from '../../plugins/core/index.mjs';
65-
import { firstValueFrom, Observable, Subject } from 'rxjs';
65+
import { firstValueFrom, map, Observable, Subject, timer } from 'rxjs';
6666
import type { HumanWithCompositePrimary, HumanWithTimestampDocumentType } from '../../src/plugins/test-utils/schema-objects.ts';
6767
import { RxDBAttachmentsPlugin } from '../../plugins/attachments/index.mjs';
6868
import { RxDBMigrationSchemaPlugin } from '../../plugins/migration-schema/index.mjs';
@@ -1152,6 +1152,95 @@ describe('replication.test.ts', () => {
11521152
});
11531153
});
11541154
describeParallel('issues', () => {
1155+
/**
1156+
* @link https://discord.com/channels/969553741705539624/1407063219062702111
1157+
*/
1158+
it('not re-running push when canceled during reload', async () => {
1159+
const identifier = randomToken(10);
1160+
const databaseName = randomToken(10);
1161+
const collection1 = await humansCollection.createHumanWithTimestamp(0, databaseName, false);
1162+
let pushedOne = false;
1163+
const replicationState1 = replicateRxCollection({
1164+
collection: collection1,
1165+
replicationIdentifier: identifier,
1166+
live: true,
1167+
retryTime: 2_000,
1168+
pull: {
1169+
handler: async (_lastPulledCheckpoint, _batchSize) => {
1170+
await wait(0);
1171+
1172+
return {
1173+
documents: [],
1174+
checkpoint: 'CHECKPOINT',
1175+
};
1176+
},
1177+
stream$: timer(0, 600_000).pipe(
1178+
map(() => {
1179+
return 'RESYNC';
1180+
})
1181+
),
1182+
},
1183+
push: {
1184+
batchSize: 1,
1185+
handler: async (_docsToSync: any) => {
1186+
pushedOne = true;
1187+
1188+
// reload sometime while waiting - the callback isn't retried again
1189+
await new Promise((resolve) => setTimeout(resolve, 9999999));
1190+
return [];
1191+
},
1192+
},
1193+
});
1194+
await replicationState1.awaitInSync();
1195+
await wait(10);
1196+
const checkpointAfter = await getLastCheckpointDoc(
1197+
ensureNotFalsy(replicationState1.internalReplicationState),
1198+
'up'
1199+
);
1200+
assert.ok(!checkpointAfter);
1201+
1202+
await collection1.insert(
1203+
schemaObjects.humanWithTimestampData()
1204+
);
1205+
await waitUntil(() => pushedOne === true);
1206+
1207+
await collection1.database.close();
1208+
1209+
const collection2 = await humansCollection.createHumanWithTimestamp(0, databaseName, false);
1210+
let pushedTwo = false;
1211+
replicateRxCollection({
1212+
collection: collection2,
1213+
replicationIdentifier: identifier,
1214+
live: true,
1215+
retryTime: 2_000,
1216+
pull: {
1217+
handler: async (_lastPulledCheckpoint, _batchSize) => {
1218+
await wait(0);
1219+
return {
1220+
documents: [],
1221+
checkpoint: 'CHECKPOINT',
1222+
};
1223+
},
1224+
stream$: timer(0, 600_000).pipe(
1225+
map(() => {
1226+
return 'RESYNC';
1227+
})
1228+
),
1229+
},
1230+
push: {
1231+
batchSize: 1,
1232+
handler: async (_docsToSync: any) => {
1233+
pushedTwo = true;
1234+
1235+
// reload sometime while waiting - the callback isn't retried again
1236+
await new Promise((resolve) => setTimeout(resolve, 9999999));
1237+
return [];
1238+
},
1239+
},
1240+
});
1241+
await waitUntil(() => pushedTwo === true);
1242+
await collection2.database.close();
1243+
});
11551244
it('#7261 should update document via replication stream AFTER migration', async () => {
11561245
const dbName = randomToken(10);
11571246
const storage = wrappedValidateZSchemaStorage({ storage: config.storage.getStorage() });

0 commit comments

Comments
 (0)