@soga/uploader 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,423 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseUploader = void 0;
4
- const typeorm_1 = require("typeorm");
5
- const entities_1 = require("@soga/entities");
6
- const types_1 = require("@soga/types");
7
- const prepare_1 = require("../hooks/prepare");
8
- const utils_1 = require("@soga/utils");
9
- const complete_1 = require("../hooks/complete");
10
- const trasform_1 = require("../hooks/trasform");
11
- let isDequeueing = false;
12
- const runningMap = new Map();
13
- const successMap = new Map();
14
- class BaseUploader {
15
- hostType;
16
- onProgress = async () => { };
17
- onSuccess = async () => { };
18
- onError = async () => { };
19
- successRepository;
20
- fileRepository;
21
- partRepository;
22
- thread_count = 1;
23
- maxThreads = 10;
24
- threads = [];
25
- baseParams;
26
- getValidThreads(threads) {
27
- return Math.min(Math.max(threads ?? 0, 0), this.maxThreads);
28
- }
29
- async onPartProgress(params) {
30
- const { id: file_id, data, type } = params;
31
- if (type != 'percent')
32
- return;
33
- const { part_id, percent } = data;
34
- const part = await this.partRepository.findOneBy({
35
- id: part_id,
36
- });
37
- if (!part)
38
- return;
39
- if (part.upload_percent >= percent)
40
- return;
41
- if (part.upload_status == types_1.UploadStatus.ERROR)
42
- return;
43
- if (part.upload_status == types_1.UploadStatus.SUCCESS)
44
- return;
45
- await this.partRepository.update(part_id, {
46
- upload_percent: percent,
47
- });
48
- const parts = await this.partRepository.findBy({
49
- file_id,
50
- host_type: this.hostType,
51
- });
52
- let total = 0;
53
- let uploaded = 0;
54
- for (const part of parts) {
55
- total += part.info.size;
56
- uploaded += part.info.size * part.upload_percent;
57
- }
58
- const global_percent = uploaded / total;
59
- const file = await this.fileRepository.findOneBy({ id: file_id });
60
- const step = types_1.UploadProcessStep[`upload_${this.hostType}`];
61
- file.progress[step].percent = global_percent;
62
- file.percent = (0, utils_1.getProgressPercent)(file.progress);
63
- await this.fileRepository.update(file_id, {
64
- progress: file.progress,
65
- percent: file.percent,
66
- });
67
- await this.onProgress(file);
68
- }
69
- async onPartSuccess({ file_id, host_type, }) {
70
- while (successMap.get(file_id)) {
71
- await new Promise((resolve) => {
72
- setTimeout(resolve, 100);
73
- });
74
- }
75
- try {
76
- successMap.set(file_id, true);
77
- const file = await this.fileRepository.findOneBy({
78
- id: file_id,
79
- });
80
- if (!file)
81
- return;
82
- const status = `${host_type}_upload_status`;
83
- if (file[status] == types_1.UploadStatus.ERROR) {
84
- return;
85
- }
86
- if (file.upload_status == types_1.UploadStatus.ERROR)
87
- return;
88
- const exist = await this.partRepository.findOneBy({
89
- file_id: file.id,
90
- host_type,
91
- upload_status: (0, typeorm_1.Not)(types_1.UploadStatus.SUCCESS),
92
- });
93
- if (exist)
94
- return;
95
- const parts = await this.partRepository.findBy({
96
- file_id: file.id,
97
- host_type,
98
- });
99
- const result = {};
100
- if (host_type == types_1.HostType.BAIDU) {
101
- for (const part of parts) {
102
- result[part.info.file] = {
103
- ...part.upload_result.baidu,
104
- md4: part.info.md4,
105
- };
106
- }
107
- }
108
- else if (host_type == types_1.HostType.ALI) {
109
- for (const part of parts) {
110
- result[part.info.file] = {
111
- ...part.upload_result.ali,
112
- sha1: part.info.sha1,
113
- };
114
- }
115
- }
116
- const result_field = `${host_type}_upload_result`;
117
- const current_file = await this.fileRepository.findOneBy({
118
- id: file.id,
119
- });
120
- const step = types_1.UploadProcessStep[`upload_${this.hostType}`];
121
- current_file.progress[step].percent = 1;
122
- current_file.percent = (0, utils_1.getProgressPercent)(current_file.progress);
123
- await this.fileRepository.update(file.id, {
124
- [status]: types_1.UploadStatus.SUCCESS,
125
- [result_field]: result,
126
- progress: current_file.progress,
127
- percent: current_file.percent,
128
- });
129
- const latest_file = await this.fileRepository.findOneBy({ id: file.id });
130
- const allHostUploaded = await this.checkAllHostsUploaded(latest_file);
131
- if (!allHostUploaded)
132
- return;
133
- await this.onFileSuccess(latest_file);
134
- }
135
- finally {
136
- successMap.delete(file_id);
137
- }
138
- }
139
- async onFileSuccess(file) {
140
- await (0, complete_1.complete)({
141
- file_id: file.id,
142
- fileRepository: this.fileRepository,
143
- sdk_domain: this.baseParams.sdk_domain,
144
- });
145
- const latest_file = await this.fileRepository.findOneBy({
146
- id: file.id,
147
- });
148
- await this.onSuccess(latest_file);
149
- await (0, trasform_1.transform)({
150
- file_id: file.id,
151
- fileRepository: this.fileRepository,
152
- partRepository: this.partRepository,
153
- successRepository: this.successRepository,
154
- });
155
- }
156
- async onPartError({ error, part_id, file_id, }) {
157
- await this.partRepository.update(part_id, {
158
- upload_status: types_1.UploadStatus.ERROR,
159
- });
160
- const status = `${this.hostType}_upload_status`;
161
- const file = await this.fileRepository.findOneBy({ id: file_id });
162
- if (file[status] == types_1.UploadStatus.ERROR)
163
- return;
164
- await this.fileRepository.update(file.id, {
165
- [status]: types_1.UploadStatus.ERROR,
166
- upload_status: types_1.UploadStatus.ERROR,
167
- });
168
- await this.onError(error, file);
169
- }
170
- constructor(baseParams, host_type) {
171
- this.hostType = host_type;
172
- this.baseParams = baseParams;
173
- const { dataSource } = baseParams;
174
- this.fileRepository = dataSource.getRepository(entities_1.UploadFile);
175
- this.successRepository = dataSource.getRepository(entities_1.UploadSuccess);
176
- this.partRepository = dataSource.getRepository(entities_1.UploadPart);
177
- this.thread_count = this.getValidThreads(baseParams.threads ?? this.thread_count);
178
- if (baseParams.onProgress) {
179
- this.onProgress = baseParams.onProgress.bind(this);
180
- }
181
- if (baseParams.onSuccess) {
182
- this.onSuccess = baseParams.onSuccess.bind(this);
183
- }
184
- if (baseParams.onError) {
185
- this.onError = baseParams.onError.bind(this);
186
- }
187
- }
188
- async setThreads(threads) {
189
- const validThreads = this.getValidThreads(threads);
190
- this.thread_count = validThreads;
191
- await this.run();
192
- }
193
- async start() {
194
- await this.run();
195
- }
196
- async stopFiles(ids) {
197
- const threads = this.threads.filter((thread) => ids.includes(thread.file_id));
198
- await Promise.all(threads.map((thread) => thread.stop()));
199
- await this.start();
200
- }
201
- async deleteFiles(ids) {
202
- const threads = this.threads.filter((thread) => ids.includes(thread.file_id));
203
- await Promise.all(threads.map((thread) => thread.stop()));
204
- }
205
- async stopAll() {
206
- await Promise.all(this.threads.map((thread) => thread.stop()));
207
- }
208
- async dequeueOneFile() {
209
- while (isDequeueing) {
210
- await new Promise((resolve) => {
211
- setTimeout(resolve, 50);
212
- });
213
- }
214
- try {
215
- isDequeueing = true;
216
- const status_field = `${this.hostType}_upload_status`;
217
- const host_id_field = `${this.hostType}_host_id`;
218
- const file = await this.fileRepository.findOne({
219
- where: {
220
- uid: this.baseParams.uid,
221
- is_paused: false,
222
- encode_status: types_1.EncodeStatus.SUCCESS,
223
- [status_field]: (0, typeorm_1.IsNull)(),
224
- upload_status: (0, typeorm_1.In)([types_1.UploadStatus.NULL, types_1.UploadStatus.PROCESS]),
225
- },
226
- order: {
227
- created_at: 'ASC',
228
- },
229
- });
230
- if (!file)
231
- return;
232
- await this.fileRepository.update(file.id, {
233
- [status_field]: types_1.UploadStatus.PROCESS,
234
- upload_status: types_1.UploadStatus.PROCESS,
235
- });
236
- await (0, prepare_1.prepare)({
237
- file_id: file.id,
238
- sdk_domain: this.baseParams.sdk_domain,
239
- fileRepository: this.fileRepository,
240
- });
241
- const { encoded } = file;
242
- const { affix: affix_data, source: source_data, txt: txt_data, img: img_data, media: media_data, } = encoded;
243
- const parts = [
244
- ...(source_data?.parts ?? []),
245
- ...(txt_data?.parts ?? []),
246
- ...(img_data?.parts ?? []),
247
- ...(media_data?.parts ?? []),
248
- ];
249
- affix_data?.forEach((item) => {
250
- item.parts?.forEach((part) => {
251
- parts.push(part);
252
- });
253
- });
254
- const host_id = file[host_id_field];
255
- const lists = [];
256
- const { length } = parts;
257
- for (let i = 0; i < length; i++) {
258
- const item = parts[i];
259
- const exist = await this.partRepository.findOneBy({
260
- file_id: file.id,
261
- part_name: item.file,
262
- host_id,
263
- });
264
- if (!exist) {
265
- lists.push({
266
- uid: this.baseParams.uid,
267
- file_id: file.id,
268
- part_name: item.file,
269
- info: item,
270
- output_root: file.output_root,
271
- host_id,
272
- host_type: this.hostType,
273
- });
274
- }
275
- }
276
- await this.partRepository.save(lists);
277
- return;
278
- }
279
- finally {
280
- isDequeueing = false;
281
- }
282
- }
283
- async checkProcessingFile(file) {
284
- if (!file)
285
- return;
286
- if (file.baidu_host_id &&
287
- file.baidu_upload_status == types_1.UploadStatus.PROCESS) {
288
- const exist = await this.partRepository.findOneBy({
289
- file_id: file.id,
290
- host_type: types_1.HostType.BAIDU,
291
- upload_status: (0, typeorm_1.Not)(types_1.UploadStatus.SUCCESS),
292
- });
293
- if (!exist) {
294
- await this.onPartSuccess({
295
- file_id: file.id,
296
- host_type: types_1.HostType.BAIDU,
297
- });
298
- }
299
- }
300
- if (file.ali_host_id && file.ali_upload_status == types_1.UploadStatus.PROCESS) {
301
- const exist = await this.partRepository.findOneBy({
302
- file_id: file.id,
303
- host_type: types_1.HostType.ALI,
304
- upload_status: (0, typeorm_1.Not)(types_1.UploadStatus.SUCCESS),
305
- });
306
- if (!exist) {
307
- await this.onPartSuccess({
308
- file_id: file.id,
309
- host_type: types_1.HostType.ALI,
310
- });
311
- }
312
- }
313
- }
314
- async run() {
315
- const uid = this.baseParams.uid;
316
- while (runningMap.get(uid)) {
317
- await new Promise((resolve) => {
318
- setTimeout(resolve, 100);
319
- });
320
- }
321
- runningMap.set(uid, true);
322
- const time1 = Date.now();
323
- const files = await this.fileRepository.findBy({
324
- uid: this.baseParams.uid,
325
- is_paused: false,
326
- upload_status: types_1.UploadStatus.PROCESS,
327
- });
328
- if (files.length) {
329
- const thread_file_ids = this.threads.map((thread) => thread.file_id);
330
- const exception_files = files.filter((file) => {
331
- return !thread_file_ids.includes(file.id);
332
- });
333
- for (const file of exception_files) {
334
- await this.checkProcessingFile(file);
335
- }
336
- }
337
- const time2 = Date.now();
338
- const parts = await this.partRepository.findBy({
339
- uid: this.baseParams.uid,
340
- is_paused: false,
341
- upload_status: types_1.UploadStatus.PROCESS,
342
- host_id: this.baseParams.host_id,
343
- });
344
- if (parts.length) {
345
- const thread_part_ids = this.threads.map((thread) => thread.part_id);
346
- const exception_parts = parts.filter((part) => {
347
- return !thread_part_ids.includes(part.id);
348
- });
349
- if (exception_parts.length) {
350
- const ids = exception_parts.map((part) => part.id);
351
- await this.partRepository.update({
352
- id: (0, typeorm_1.In)(ids),
353
- upload_status: types_1.UploadStatus.PROCESS,
354
- }, {
355
- upload_status: types_1.UploadStatus.NULL,
356
- });
357
- }
358
- }
359
- const real_count = this.threads.length;
360
- const def_count = this.thread_count;
361
- if (real_count < def_count) {
362
- const less = def_count - real_count;
363
- const getOnePart = async () => {
364
- const part = await this.partRepository.findOne({
365
- where: {
366
- uid: this.baseParams.uid,
367
- is_paused: false,
368
- upload_status: types_1.UploadStatus.NULL,
369
- host_id: this.baseParams.host_id,
370
- },
371
- order: {
372
- created_at: 'ASC',
373
- },
374
- });
375
- return part;
376
- };
377
- for (let i = 0; i < less; i++) {
378
- const part = await getOnePart();
379
- if (!part)
380
- break;
381
- const thread = this.getThread(part);
382
- this.threads.push(thread);
383
- await this.partRepository.update(part.id, {
384
- upload_status: types_1.UploadStatus.PROCESS,
385
- });
386
- thread.start();
387
- }
388
- if (this.threads.length < def_count) {
389
- await this.dequeueOneFile();
390
- const exist_part = await getOnePart();
391
- if (exist_part) {
392
- runningMap.delete(uid);
393
- await this.run();
394
- }
395
- else {
396
- runningMap.delete(uid);
397
- }
398
- }
399
- else {
400
- runningMap.delete(uid);
401
- }
402
- }
403
- else {
404
- const more = real_count - def_count;
405
- const threads = this.threads.slice(0, more);
406
- for (const thread of threads) {
407
- await thread.stop();
408
- }
409
- runningMap.delete(uid);
410
- }
411
- }
412
- async checkAllHostsUploaded(file) {
413
- if (file.baidu_host_id &&
414
- file.baidu_upload_status != types_1.UploadStatus.SUCCESS) {
415
- return false;
416
- }
417
- if (file.ali_host_id && file.ali_upload_status != types_1.UploadStatus.SUCCESS) {
418
- return false;
419
- }
420
- return true;
421
- }
422
- }
423
- exports.BaseUploader = BaseUploader;
@@ -1,25 +0,0 @@
1
- import { UploadFile } from '@soga/entities';
2
- import { DataSource } from 'typeorm';
3
- interface CommonParams {
4
- uid: number;
5
- sdk_domain: string;
6
- dataSource: DataSource;
7
- onProgress?: (file: UploadFile) => Promise<void>;
8
- onSuccess?: (file: UploadFile) => Promise<void>;
9
- onError?: (error: Error, file: UploadFile) => Promise<void>;
10
- }
11
- export interface UploaderParams extends CommonParams {
12
- host_id: number;
13
- threads?: number;
14
- debug?: boolean;
15
- }
16
- export interface GetUploaderParams extends CommonParams {
17
- }
18
- export type ThreadType = {
19
- file_id: number;
20
- part_id: number;
21
- uid: number;
22
- start: () => Promise<void>;
23
- stop: () => Promise<void>;
24
- };
25
- export {};
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,21 +0,0 @@
1
- import { DataSource, Repository } from 'typeorm';
2
- import { UploadFile, UploadPart } from '@soga/entities';
3
- import { GetUploaderParams } from './types/main';
4
- import { BaseUploader } from './host-uploader/base';
5
- export declare class Uploader {
6
- protected params: GetUploaderParams;
7
- protected uid: number;
8
- protected dataSource: DataSource;
9
- protected fileRepository: Repository<UploadFile>;
10
- protected partRepository: Repository<UploadPart>;
11
- constructor(params: GetUploaderParams);
12
- protected processorMap: Map<number, BaseUploader>;
13
- init(): Promise<void>;
14
- start(): Promise<void>;
15
- stopAll(): Promise<void>;
16
- stopFiles(ids: number[]): Promise<void>;
17
- deleteFiles(ids: number[]): Promise<void>;
18
- private startHost;
19
- private startAli;
20
- private startBaidu;
21
- }
package/dist/uploader.js DELETED
@@ -1,102 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Uploader = void 0;
4
- const types_1 = require("@soga/types");
5
- const entities_1 = require("@soga/entities");
6
- const baidu_1 = require("./host-uploader/baidu");
7
- const ali_1 = require("./host-uploader/ali");
8
- class Uploader {
9
- params;
10
- uid;
11
- dataSource;
12
- fileRepository;
13
- partRepository;
14
- constructor(params) {
15
- this.params = params;
16
- this.uid = params.uid;
17
- this.dataSource = params.dataSource;
18
- this.fileRepository = this.dataSource.getRepository(entities_1.UploadFile);
19
- this.partRepository = this.dataSource.getRepository(entities_1.UploadPart);
20
- }
21
- processorMap = new Map();
22
- async init() {
23
- }
24
- async start() {
25
- await Promise.all([this.startAli(), this.startBaidu()]);
26
- }
27
- async stopAll() {
28
- const processor_iterator = this.processorMap.values();
29
- for (const processor of processor_iterator) {
30
- await processor.stopAll();
31
- }
32
- }
33
- async stopFiles(ids) {
34
- const processor_iterator = this.processorMap.values();
35
- for (const processor of processor_iterator) {
36
- await processor.stopFiles(ids);
37
- }
38
- }
39
- async deleteFiles(ids) {
40
- const processor_iterator = this.processorMap.values();
41
- for (const processor of processor_iterator) {
42
- await processor.deleteFiles(ids);
43
- }
44
- }
45
- async startHost(host_id, host_type) {
46
- if (this.processorMap.has(host_id)) {
47
- const processor = this.processorMap.get(host_id);
48
- await processor.start();
49
- return;
50
- }
51
- const params = {
52
- uid: this.uid,
53
- sdk_domain: this.params.sdk_domain,
54
- dataSource: this.dataSource,
55
- host_id,
56
- onProgress: this.params.onProgress,
57
- onSuccess: this.params.onSuccess,
58
- onError: this.params.onError,
59
- };
60
- if (host_type == types_1.HostType.BAIDU) {
61
- const baiduUploader = await (0, baidu_1.getBaiduUploader)(params);
62
- this.processorMap.set(host_id, baiduUploader);
63
- await baiduUploader.start();
64
- }
65
- else if (host_type == types_1.HostType.ALI) {
66
- const aliUploader = await (0, ali_1.getAliUploader)(params);
67
- this.processorMap.set(host_id, aliUploader);
68
- await aliUploader.start();
69
- }
70
- }
71
- async startAli() {
72
- const ali_hosts = await this.fileRepository
73
- .createQueryBuilder('file')
74
- .select('DISTINCT file.ali_host_id')
75
- .where('file.uid = :uid', { uid: this.uid })
76
- .getRawMany();
77
- const ali_host_ids = ali_hosts
78
- .map((file) => file.ali_host_id)
79
- .filter((id) => !!id);
80
- if (ali_host_ids.length) {
81
- for (const ali_host_id of ali_host_ids) {
82
- await this.startHost(ali_host_id, types_1.HostType.ALI);
83
- }
84
- }
85
- }
86
- async startBaidu() {
87
- const baidu_hosts = await this.fileRepository
88
- .createQueryBuilder('file')
89
- .select('DISTINCT file.baidu_host_id')
90
- .where('file.uid = :uid', { uid: this.uid })
91
- .getRawMany();
92
- const baidu_host_ids = baidu_hosts
93
- .map((file) => file.baidu_host_id)
94
- .filter((id) => !!id);
95
- if (baidu_host_ids.length) {
96
- for (const baidu_host_id of baidu_host_ids) {
97
- await this.startHost(baidu_host_id, types_1.HostType.BAIDU);
98
- }
99
- }
100
- }
101
- }
102
- exports.Uploader = Uploader;