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

209 lines
10 KiB
JavaScript
Raw Permalink 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 tslib_1 = require("tslib");
const index_backend_1 = require("../utils/cos/index.backend");
const Exception_1 = require("oak-domain/lib/types/Exception");
const Projection_1 = require("../types/Projection");
const assert_1 = tslib_1.__importDefault(require("assert"));
const triggers = [
{
name: '生成extraFile需要的上传meta',
when: 'before',
entity: 'extraFile',
action: 'create',
priority: 20,
fn: async ({ operation }, context) => {
const { data } = operation;
let cachedOrigin = undefined;
const getCosOrigin = async () => {
if (cachedOrigin) {
return cachedOrigin;
}
const [application] = await context.select("application", {
data: {
config: 1,
system: {
config: 1,
platform: {
config: 1
}
}
},
filter: {
id: context.getApplicationId(),
},
}, {
dontCollect: true
});
(0, assert_1.default)(application, `找不到 当前应用程序`);
if (application.config?.cos?.defaultOrigin) {
console.log('使用应用程序配置的默认Cos源', application.config.cos.defaultOrigin);
cachedOrigin = application.config?.cos?.defaultOrigin;
}
else if (application.system?.config?.Cos?.defaultOrigin) {
console.log('使用系统配置的默认Cos源', application.system?.config?.Cos?.defaultOrigin);
cachedOrigin = application.system?.config?.Cos?.defaultOrigin;
}
else if (application.system?.platform?.config?.Cos?.defaultOrigin) {
console.log('使用平台配置的默认Cos源', application.system?.platform?.config?.Cos?.defaultOrigin);
cachedOrigin = application.system?.platform?.config?.Cos?.defaultOrigin;
}
(0, assert_1.default)(cachedOrigin, `应用程序${application.id}、系统${application?.system?.id}及平台均未配置默认的Cos源`);
(0, assert_1.default)(cachedOrigin !== 'unknown', `应用程序${application.id}、系统${application?.system?.id}及平台配置的默认Cos源不能为'unknown'`);
return cachedOrigin;
};
const formMeta = async (data) => {
// 如果提供了就用提供的origin否则尝试从应用程序、系统配置、平台配置中获取默认的Cos源
const configOrigin = data.origin || await getCosOrigin();
data.origin = configOrigin;
(0, assert_1.default)(configOrigin, `extraFile的origin未指定且应用程序、系统配置、平台配置中也没有默认的Cos源请检查`);
if (!data.applicationId) {
data.applicationId = context.getApplicationId();
}
if (configOrigin === 'unknown') {
Object.assign(data, {
uploadState: 'success',
});
return;
}
if (!configOrigin) {
throw new Exception_1.OakException(`origin为${configOrigin}的extraFile没有定义Cos类请调用registerCos注入`);
}
const cos = (0, index_backend_1.getCosBackend)(configOrigin);
await cos.formUploadMeta(context.getApplication(), data, context);
Object.assign(data, {
uploadState: 'uploading',
});
};
if (data instanceof Array) {
await Promise.all(data.map(ele => {
return formMeta(ele);
}));
return data.length;
}
await formMeta(data);
return 1;
}
},
{
name: '对分片上传的extraFile生成上传所需的分片信息',
when: 'before',
entity: 'extraFile',
action: 'create',
priority: 24,
fn: async ({ operation }, context) => {
const { data } = operation;
const formChunkInfo = async (data) => {
if (!data.enableChunkedUpload) {
return;
}
(0, assert_1.default)(data.origin, `启用分片上传的extraFile必须指定origin`);
(0, assert_1.default)(data.chunkInfo?.chunkSize, `启用分片上传的extraFile必须指定chunkInfo.chunkSize`);
(0, assert_1.default)(data.size, `启用分片上传的extraFile必须指定size`);
(0, assert_1.default)(data.chunkInfo?.chunkSize >= 100 * 1024, `chunkInfo.chunkSize必须大于100KB`);
(0, assert_1.default)(data.chunkInfo?.chunkSize <= 1 * 1024 * 1024 * 1024, `chunkInfo.chunkSize必须小于1GB`);
(0, assert_1.default)(data.chunkInfo?.partCount && data.chunkInfo.partCount > 0, `chunkInfo.partCount必须大于0`);
(0, assert_1.default)(!data.chunkInfo?.merged, `chunkInfo.merged必须为false`);
(0, assert_1.default)(data.chunkInfo?.partCount <= 1000, `分片数量不能超过1000`);
// 计算partCount 是否正确
const expectedPartCount = Math.ceil(data.size / data.chunkInfo.chunkSize);
(0, assert_1.default)(data.chunkInfo.partCount === expectedPartCount, `chunkInfo.partCount计算错误预期值为${expectedPartCount},但实际值为${data.chunkInfo.partCount}`);
if (!data.origin) {
throw new Exception_1.OakException(`origin为${data.origin}的extraFile没有定义Cos类请调用registerCos注入`);
}
const cos = (0, index_backend_1.getCosBackend)(data.origin);
const infos = await cos.prepareChunkedUpload(context.getApplication(), data, context);
Object.assign(data, {
chunkInfo: {
uploadId: infos.uploadId,
chunkSize: data.chunkInfo?.chunkSize,
partCount: data.chunkInfo?.partCount,
parts: new Array(data.chunkInfo.partCount).fill(null).map(() => ''),
merged: false,
},
});
};
if (data instanceof Array) {
await Promise.all(data.map(ele => {
return formChunkInfo(ele);
}));
return data.length;
}
await formChunkInfo(data);
return 1;
}
},
{
name: '删除extraFile时远端也进行删除',
when: 'commit',
strict: 'makeSure',
entity: 'extraFile',
action: 'remove',
fn: async ({ ids }, context) => {
const fn = context.openRootMode();
const rows = await context.select('extraFile', {
data: {
id: 1,
origin: 1,
objectId: 1,
bucket: 1,
extension: 1,
entity: 1,
entityId: 1,
extra2: 1,
applicationId: 1,
application: Projection_1.applicationProjection,
enableChunkedUpload: 1,
chunkInfo: 1,
},
filter: {
id: { $in: ids },
},
}, { includedDeleted: true });
for (const extraFile of rows) {
const { origin, objectId, application } = extraFile;
// 用objectId来去重只有当没有还有效的objectId方可删除
const count = await context.count('extraFile', {
filter: {
objectId: objectId,
},
}, {});
if (count === 0) {
const uploader = (0, index_backend_1.getCosBackend)(origin);
const application2 = context.getApplication(true) || application;
if (extraFile.enableChunkedUpload) {
// 是否所有的分片都已经有etag上传成功
const chunkInfo = extraFile.chunkInfo;
const allPartsDone = chunkInfo?.parts?.every(part => !!part);
if (allPartsDone) {
if (!chunkInfo?.merged) {
try {
// 先完成分片合并
await uploader.mergeChunkedUpload(extraFile.application, extraFile, extraFile.chunkInfo.parts.map((etag, index) => ({
partNumber: index + 1,
etag: etag,
})), context);
}
catch (err) {
console.error(`合并extraFile ${extraFile.id} 的分片上传时出错,但仍继续删除操作`, err);
}
}
// 然后删除文件
await uploader.removeFile(application2, extraFile, context);
}
else {
// 删除未完成的分片上传
await uploader.abortMultipartUpload(extraFile.application, extraFile, context);
}
}
else {
await uploader.removeFile(application2, extraFile, context);
}
}
}
fn();
}
},
];
exports.default = triggers;