Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export default class DownloadQueue {
this.isPausedByUser = !startActive;

// First revive tasks that were working in the background
existingTasks.forEach(task => this.reviveTask(task));
await Promise.all(existingTasks.map(task => this.reviveTask(task)));

// Now start downloads for specs that haven't finished
const specsToDownload = this.specs.filter(
Expand Down Expand Up @@ -731,9 +731,12 @@ export default class DownloadQueue {
}
}

private reviveTask(task: DownloadTask) {
private async reviveTask(task: DownloadTask) {
const spec = this.specs.find(spec => spec.id === task.id);
if (spec) {

// Don't revive finished tasks or ones that already have lazy deletes in
// progress.
if (spec && !spec.finished && spec.createTime > 0) {
let shouldAddTask = true;

switch (task.state) {
Expand Down Expand Up @@ -778,6 +781,18 @@ export default class DownloadQueue {
} else {
if (["DOWNLOADING", "PAUSED"].includes(task.state)) {
task.stop();

if (spec && !spec.finished) {
try {
// There might be a partially downloaded file on disk. We need to
// get rid of it in case a lazy-delete spec is revived, at which
// point an existing file on disk will be taken to be a
// successfully downloaded one.
await RNFS.unlink(spec.path);
} catch {
// Expected for missing files
}
}
}
}
}
Expand Down
23 changes: 21 additions & 2 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,25 @@ describe("DownloadQueue", () => {
expect(task.stop).toHaveBeenCalledTimes(2);
});

it("stops lazy-deleted tasks from previous launches", async () => {
const queue = new DownloadQueue();

(checkForExistingDownloads as jest.Mock).mockReturnValue([task]);
await kvfs.write("/mydomain/foo", {
id: task.id,
url: "http://foo.com/a.mp3",
path: `${RNFS.DocumentDirectoryPath}/DownloadQueue/mydomain/foo`,
createTime: -(Date.now() + 300000), // simulate lazy-delete
});

task.state = "DOWNLOADING";
await queue.init({ domain: "mydomain" });

expect(task.stop).toHaveBeenCalledTimes(1);
// Should also delete partially-downloaded file
expect(unlink).toHaveBeenCalledTimes(1);
});

it("starts downloads for specs without tasks or files", async () => {
const queue = new DownloadQueue();

Expand Down Expand Up @@ -1652,7 +1671,7 @@ describe("DownloadQueue", () => {
it("should handle a case where spec is finished but file is missing", async () => {
const queue = new DownloadQueue();

(download as jest.Mock).mockImplementation(_ =>
(download as jest.Mock).mockImplementation(() =>
Object.assign(task, {
done: jest.fn((handler: DoneHandler) => {
task._done = handler;
Expand All @@ -1676,7 +1695,7 @@ describe("DownloadQueue", () => {
Platform.OS = "android";
const queue = new DownloadQueue();

(download as jest.Mock).mockImplementation(_ =>
(download as jest.Mock).mockImplementation(() =>
Object.assign(task, {
done: jest.fn((handler: DoneHandler) => {
task._done = handler;
Expand Down