|
@@ -643,6 +643,12 @@ function register(app, ctx) {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
await store.withTransaction(async (tx) => {
|
|
await store.withTransaction(async (tx) => {
|
|
|
|
|
+ // 事务内二次校验:并发同名文件只允许一个写入
|
|
|
|
|
+ if (!body.force && await tx.findUploadBySha(sha256)) {
|
|
|
|
|
+ const err = new Error('duplicate');
|
|
|
|
|
+ err.code = 'OPS_DUPLICATE';
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
if (body.force) await tx.deletePlatformRowsBySha(sha256);
|
|
if (body.force) await tx.deletePlatformRowsBySha(sha256);
|
|
|
await tx.insertUpload({
|
|
await tx.insertUpload({
|
|
|
id: uploadId,
|
|
id: uploadId,
|
|
@@ -661,6 +667,9 @@ function register(app, ctx) {
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
|
|
+ if (e.code === 'OPS_DUPLICATE') {
|
|
|
|
|
+ return sendJson(res, 409, { error: '该文件已导入过', uploadId: await store.findUploadBySha(sha256), duplicate: true });
|
|
|
|
|
+ }
|
|
|
return sendJson(res, 500, { error: '写入失败', detail: e.message || String(e) });
|
|
return sendJson(res, 500, { error: '写入失败', detail: e.message || String(e) });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -705,6 +714,11 @@ function register(app, ctx) {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
await store.withTransaction(async (tx) => {
|
|
await store.withTransaction(async (tx) => {
|
|
|
|
|
+ if (!body.force && await tx.findUploadBySha(sha256)) {
|
|
|
|
|
+ const err = new Error('duplicate');
|
|
|
|
|
+ err.code = 'OPS_DUPLICATE';
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
if (body.force) await tx.deleteRowsBySha(sha256);
|
|
if (body.force) await tx.deleteRowsBySha(sha256);
|
|
|
await tx.insertUpload({
|
|
await tx.insertUpload({
|
|
|
id: uploadId,
|
|
id: uploadId,
|
|
@@ -723,6 +737,9 @@ function register(app, ctx) {
|
|
|
await tx.pruneOrphanShops();
|
|
await tx.pruneOrphanShops();
|
|
|
});
|
|
});
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
|
|
+ if (e.code === 'OPS_DUPLICATE') {
|
|
|
|
|
+ return sendJson(res, 409, { error: '该文件已导入过', uploadId: await store.findUploadBySha(sha256), duplicate: true });
|
|
|
|
|
+ }
|
|
|
return sendJson(res, 500, { error: '写入失败', detail: e.message || String(e) });
|
|
return sendJson(res, 500, { error: '写入失败', detail: e.message || String(e) });
|
|
|
}
|
|
}
|
|
|
|
|
|