Skip to content

Commit b54fc2c

Browse files
authored
feat: removes duplicate spec records with same URL (#44)
1 parent ae7e055 commit b54fc2c

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

src/index.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,25 @@ export default class DownloadQueue {
233233
this.getDirFilenames(),
234234
]);
235235
const now = Date.now();
236-
const loadedSpecs = specData.map(spec => spec.value as Spec);
236+
const seenUrls = new Set<string>();
237+
const dupeSpecIds = new Set<string>();
238+
const loadedSpecs = specData.map(data => {
239+
const spec = data.value as Spec;
240+
241+
// This deduplicates specs that might have been written multiple times,
242+
// which has happened in the past based on client use mistakes.
243+
if (seenUrls.has(spec.url)) {
244+
dupeSpecIds.add(spec.id);
245+
} else {
246+
seenUrls.add(spec.url);
247+
}
248+
return spec;
249+
});
237250
const deletes = loadedSpecs.filter(
238251
spec =>
239252
spec.createTime === 0 ||
240-
(spec.createTime < 0 && -spec.createTime <= now)
253+
(spec.createTime < 0 && -spec.createTime <= now) ||
254+
dupeSpecIds.has(spec.id)
241255
);
242256
const deleteIds = new Set(deletes.map(spec => spec.id));
243257

@@ -482,7 +496,9 @@ export default class DownloadQueue {
482496
const liveUrls = new Set(
483497
this.specs.filter(spec => spec.createTime > 0).map(spec => spec.url)
484498
);
485-
const urlsToAdd = urls.filter(url => !liveUrls.has(url));
499+
// Using urlSet instead of urls in the filter automatically deduplicates
500+
// any URLs the caller might have duplicated.
501+
const urlsToAdd = [...urlSet].filter(url => !liveUrls.has(url));
486502
const specsToRemove = this.specs.filter(
487503
spec => !urlSet.has(spec.url) && spec.createTime > 0
488504
);

test/index.spec.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import {
66
DownloadTask,
77
ensureDownloadsAreRunning,
88
ErrorHandler,
9-
ProgressHandler
9+
ProgressHandler,
1010
} from "@kesha-antonov/react-native-background-downloader";
1111
import AsyncStorage from "@react-native-async-storage/async-storage";
1212
import {
1313
addEventListener,
1414
fetch,
1515
NetInfoState,
16-
NetInfoStateType
16+
NetInfoStateType,
1717
} from "@react-native-community/netinfo";
1818
import { mock } from "jest-mock-extended";
1919
import KVFS from "key-value-file-system";
@@ -309,6 +309,44 @@ describe("DownloadQueue", () => {
309309
expect(unlink).toHaveBeenCalledTimes(1);
310310
});
311311

312+
it("removes duplicate specs with the same URLs", async () => {
313+
const queue = new DownloadQueue();
314+
315+
(readdir as jest.Mock).mockImplementation(() => [
316+
"foo.mp3",
317+
"bar.mp3",
318+
"foo.mp3",
319+
]);
320+
321+
await kvfs.write("/mydomain/foo", {
322+
id: "foo",
323+
url: "http://foo.com/a.mp3",
324+
path: `${RNFS.DocumentDirectoryPath}/DownloadQueue/mydomain/foo.mp3`,
325+
createTime: Date.now() - 1000,
326+
});
327+
await kvfs.write("/mydomain/boo", {
328+
id: "boo",
329+
url: "http://foo.com/b.mp3",
330+
path: `${RNFS.DocumentDirectoryPath}/DownloadQueue/mydomain/boo.mp3`,
331+
createTime: Date.now() - 1000,
332+
});
333+
await kvfs.write("/mydomain/foo2", {
334+
id: "foo2",
335+
url: "http://foo.com/a.mp3",
336+
path: `${RNFS.DocumentDirectoryPath}/DownloadQueue/mydomain/foo.mp3`,
337+
createTime: Date.now() - 800,
338+
});
339+
expect((await kvfs.readMulti("/mydomain/*")).length).toEqual(3);
340+
341+
await queue.init({ domain: "mydomain" });
342+
const specs = await kvfs.readMulti("/mydomain/*");
343+
344+
expect(specs.length).toEqual(2);
345+
expect(
346+
specs.some(spec => "id" in spec && spec.id === "foo2")
347+
).toBeFalsy();
348+
});
349+
312350
it("revives still-downloading specs from previous launches", async () => {
313351
const queue = new DownloadQueue();
314352
const handlers: DownloadQueueHandlers = {
@@ -853,7 +891,7 @@ describe("DownloadQueue", () => {
853891
progress: (handler: ProgressHandler) => {
854892
progresser = handler;
855893
return task;
856-
}
894+
},
857895
}),
858896
]);
859897

0 commit comments

Comments
 (0)