fix(fe/worker): improve uploader robustness and upload files one by one
This commit is contained in:
parent
4e9a53574f
commit
46ccddc5f8
2 changed files with 37 additions and 20 deletions
|
@ -1,5 +1,10 @@
|
||||||
import { FilesClient } from "../client/files";
|
import { FilesClient } from "../client/files";
|
||||||
import { IFilesClient, Response, isFatalErr } from "../client";
|
import {
|
||||||
|
IFilesClient,
|
||||||
|
Response,
|
||||||
|
isFatalErr,
|
||||||
|
UploadStatusResp,
|
||||||
|
} from "../client";
|
||||||
import { UploadStatus, UploadState } from "./interface";
|
import { UploadStatus, UploadState } from "./interface";
|
||||||
|
|
||||||
// TODO: get settings from server
|
// TODO: get settings from server
|
||||||
|
@ -8,8 +13,9 @@ const defaultChunkLen = 1024 * 1024 * 1;
|
||||||
const speedDownRatio = 0.5;
|
const speedDownRatio = 0.5;
|
||||||
const speedUpRatio = 1.1;
|
const speedUpRatio = 1.1;
|
||||||
const chunkLimit = 1024 * 1024 * 50; // 50MB
|
const chunkLimit = 1024 * 1024 * 50; // 50MB
|
||||||
const createRetryLimit = 512;
|
const createRetryLimit = 1024;
|
||||||
const uploadRetryLimit = 1024;
|
const uploadRetryLimit = 1024;
|
||||||
|
const readRetryLimit = 8;
|
||||||
const backoffMax = 2000;
|
const backoffMax = 2000;
|
||||||
|
|
||||||
export interface ReaderResult {
|
export interface ReaderResult {
|
||||||
|
@ -96,7 +102,7 @@ export class ChunkUploader {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < readRetryLimit; i++) {
|
||||||
try {
|
try {
|
||||||
const chunkRightPos =
|
const chunkRightPos =
|
||||||
uploaded + this.chunkLen > file.size
|
uploaded + this.chunkLen > file.size
|
||||||
|
@ -124,12 +130,22 @@ export class ChunkUploader {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const uploadResp = await this.client.uploadChunk(
|
let uploadResp: Response<UploadStatusResp> = undefined;
|
||||||
|
for (let i = 0; i < uploadRetryLimit; i++) {
|
||||||
|
uploadResp = await this.client.uploadChunk(
|
||||||
filePath,
|
filePath,
|
||||||
result.chunk,
|
result.chunk,
|
||||||
uploaded
|
uploaded
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (uploadResp.status === 200) {
|
||||||
|
break;
|
||||||
|
} else if (uploadResp.status !== 429) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await this.backOff();
|
||||||
|
}
|
||||||
|
|
||||||
if (uploadResp.status === 200 && uploadResp.data != null) {
|
if (uploadResp.status === 200 && uploadResp.data != null) {
|
||||||
this.chunkLen = Math.ceil(this.chunkLen * speedUpRatio);
|
this.chunkLen = Math.ceil(this.chunkLen * speedUpRatio);
|
||||||
return {
|
return {
|
||||||
|
@ -152,7 +168,18 @@ export class ChunkUploader {
|
||||||
this.chunkLen = Math.ceil(this.chunkLen * speedDownRatio);
|
this.chunkLen = Math.ceil(this.chunkLen * speedDownRatio);
|
||||||
await this.backOff();
|
await this.backOff();
|
||||||
|
|
||||||
const uploadStatusResp = await this.client.uploadStatus(filePath);
|
let uploadStatusResp: Response<UploadStatusResp> = undefined;
|
||||||
|
for (let i = 0; i < uploadRetryLimit; i++) {
|
||||||
|
uploadStatusResp = await this.client.uploadStatus(filePath);
|
||||||
|
|
||||||
|
if (uploadStatusResp.status === 200) {
|
||||||
|
break;
|
||||||
|
} else if (uploadStatusResp.status !== 429) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await this.backOff();
|
||||||
|
}
|
||||||
|
|
||||||
return uploadStatusResp.status === 200
|
return uploadStatusResp.status === 200
|
||||||
? {
|
? {
|
||||||
filePath,
|
filePath,
|
||||||
|
|
|
@ -15,15 +15,12 @@ import {
|
||||||
import { errUploadMgr } from "../common/errors";
|
import { errUploadMgr } from "../common/errors";
|
||||||
import { ErrorLogger } from "../common/log_error";
|
import { ErrorLogger } from "../common/log_error";
|
||||||
|
|
||||||
const win: Window = self as any;
|
|
||||||
|
|
||||||
export interface IWorker {
|
export interface IWorker {
|
||||||
onmessage: (event: MessageEvent) => void;
|
onmessage: (event: MessageEvent) => void;
|
||||||
postMessage: (event: FileWorkerReq) => void;
|
postMessage: (event: FileWorkerReq) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UploadMgr {
|
export class UploadMgr {
|
||||||
private idx = 0;
|
|
||||||
private cycle: number = 500;
|
private cycle: number = 500;
|
||||||
private intervalID: number;
|
private intervalID: number;
|
||||||
private worker: IWorker;
|
private worker: IWorker;
|
||||||
|
@ -42,15 +39,10 @@ export class UploadMgr {
|
||||||
if (this.infos.size === 0) {
|
if (this.infos.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.idx > 10000) {
|
|
||||||
this.idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = this.idx % this.infos.size;
|
|
||||||
const infos = this.infos.valueSeq().toArray();
|
const infos = this.infos.valueSeq().toArray();
|
||||||
for (let i = 0; i < this.infos.size; i++) {
|
for (let i = 0; i < this.infos.size; i++) {
|
||||||
const pos = (start + i) % this.infos.size;
|
const info = infos[i];
|
||||||
const info = infos[pos];
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
info.state === UploadState.Ready ||
|
info.state === UploadState.Ready ||
|
||||||
|
@ -72,8 +64,6 @@ export class UploadMgr {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.idx++;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_setInfos = (infos: OrderedMap<string, UploadEntry>) => {
|
_setInfos = (infos: OrderedMap<string, UploadEntry>) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue