oak-general-business/lib/watchers/extraFile.js

202 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = require("oak-domain/lib/utils/assert");
const index_backend_1 = require("../utils/cos/index.backend");
const uuid_1 = require("oak-domain/lib/utils/uuid");
const lodash_1 = require("oak-domain/lib/utils/lodash");
const Projection_1 = require("../types/Projection");
async function checkWhetherSuccess(context, applicationId, rows) {
const successIds = [];
const failedIds = [];
await context.setApplication(applicationId);
for (const d of rows) {
const { origin } = d;
const cos = (0, index_backend_1.getCosBackend)(origin);
(0, assert_1.assert)(cos);
const success = await cos.checkWhetherSuccess(context.getApplication(), d, context);
if (success) {
successIds.push(d.id);
}
else {
failedIds.push(d.id);
}
}
if (successIds.length > 0) {
await context.operate('extraFile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
uploadState: 'success',
},
filter: {
id: {
$in: successIds,
}
}
}, {});
}
if (failedIds.length > 0) {
await context.operate('extraFile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
uploadState: 'failed',
},
filter: {
id: {
$in: successIds,
}
}
}, {});
}
}
const watchers = [
{
name: '确定uploading的文件状态',
entity: 'extraFile',
filter: async () => {
const now = Date.now();
const deadline = process.env.NODE_ENV === 'production' ? now - 3600 * 1000 : now - 60 * 1000;
return {
$$updateAt$$: {
$lt: deadline,
},
uploadState: 'uploading',
enableChunkedUpload: {
$exists: false,
}
};
},
projection: {
id: 1,
applicationId: 1,
origin: 1,
bucket: 1,
uploadState: 1,
objectId: 1,
extension: 1,
},
fn: async (context, data) => {
const eg = (0, lodash_1.groupBy)(data, 'applicationId');
for (const appId in eg) {
await checkWhetherSuccess(context, appId, eg[appId]);
}
return {
extraFile: {
update: data.length,
}
};
}
},
{
name: '处理长时间未完成分片上传的文件',
entity: 'extraFile',
filter: async () => {
const now = Date.now();
const deadline = process.env.NODE_ENV === 'production' ? now - 3 * 24 * 60 * 60 * 1000 : now - 60 * 1000;
return {
$$updateAt$$: {
$lt: deadline,
},
uploadState: 'uploading',
enableChunkedUpload: true
};
},
projection: {
...Projection_1.extraFileProjection,
application: {
...Projection_1.applicationProjection,
},
enableChunkedUpload: 1,
chunkInfo: 1,
},
fn: async (context, data) => {
const eg = (0, lodash_1.groupBy)(data, 'applicationId');
for (const appId in eg) {
// 这里检查需要分片上传的文件信息,但是考虑到可能还在上传之类的,所以先不管,后面再处理
// 1. 要去查询分片信息看看是不是都有etag了如果都有etag了就说明上传完成了否则就标记为失败
const rows = eg[appId];
const successIds = [];
const failedIds = [];
await context.setApplication(appId);
for (const d of rows) {
const { origin } = d;
const cos = (0, index_backend_1.getCosBackend)(origin);
(0, assert_1.assert)(cos);
const success = await cos.checkWhetherSuccess(context.getApplication(), d, context);
if (success) {
successIds.push(d.id);
}
else {
// 这个文件不存在,此时去尝试合并,如果合并失败,则标记为失败
try {
if (d.chunkInfo?.merged) {
// 已经合并过了,说明是合并后删除的
failedIds.push(d.id);
continue;
}
// 去合并分片
await cos.mergeChunkedUpload(context.getApplication(), d, d.chunkInfo.parts.map((etag, index) => ({
partNumber: index + 1,
etag: etag,
})), context);
await context.operate('extraFile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
chunkInfo: {
...d.chunkInfo,
merged: true,
},
},
filter: {
id: d.id,
},
}, {});
successIds.push(d.id);
}
catch (err) {
console.log(`分片合并失败,文件: ${d.id} 标记为上传失败: `, err);
failedIds.push(d.id);
}
}
}
if (successIds.length > 0) {
await context.operate('extraFile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
uploadState: 'success',
},
filter: {
id: {
$in: successIds,
}
}
}, {});
}
if (failedIds.length > 0) {
await context.operate('extraFile', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'update',
data: {
uploadState: 'failed',
},
filter: {
id: {
$in: successIds,
}
}
}, {});
}
}
return {
extraFile: {
update: data.length,
}
};
}
},
];
exports.default = watchers;