fix(fe/worker): improve uploader robustness and upload files one by one

This commit is contained in:
hexxa 2022-01-09 18:34:00 +08:00 committed by Hexxa
parent 4e9a53574f
commit 46ccddc5f8
2 changed files with 37 additions and 20 deletions

View file

@ -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,11 +130,21 @@ export class ChunkUploader {
} }
try { try {
const uploadResp = await this.client.uploadChunk( let uploadResp: Response<UploadStatusResp> = undefined;
filePath, for (let i = 0; i < uploadRetryLimit; i++) {
result.chunk, uploadResp = await this.client.uploadChunk(
uploaded filePath,
); result.chunk,
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);
@ -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,

View file

@ -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>) => {