[strapi]与 API 并行上传文件且“API Uploads”目录不存在时的并发错误

2024-05-13 829 views
3
错误报告 所需的系统信息
  • Node.js 版本:18.12.1
  • Strapi版本:v4.7.1
  • 数据库:PostgreSQL 14
  • 操作系统:Ubuntu 22.04
  • 您的项目是 Javascript 还是 Typescript:TS
描述错误

当“API Uploads”目录尚不存在时,如果同时触发多个文件上传(在我的例子中是通过迁移脚本),日志中会出现以下错误消息(并且某些文件未上传):

 error: insert into "public"."upload_folders" ("created_at", "name", "path", "path_id", "updated_at") values ($1, $2, $3, $4, $5) returning "id" - duplicate key value violates unique constraint "upload_folders_path_id_index"
error: insert into "public"."upload_folders" ("created_at", "name", "path", "path_id", "updated_at") values ($1, $2, $3, $4, $5) returning "id" - duplicate key value violates unique constraint "upload_folders_path_id_index"
    at Parser.parseErrorMessage (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:287:98)
    at Parser.handlePacket (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:126:29)
    at Parser.parse (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:39:38)
    at Socket.<anonymous> (/.../strapi-migration-test/node_modules/pg-protocol/dist/index.js:11:42)
    at Socket.emit (node:events:513:28)
    at Socket.emit (node:domain:489:12)
    at addChunk (node:internal/streams/readable:324:12)
    at readableAddChunk (node:internal/streams/readable:297:9)
    at Readable.push (node:internal/streams/readable:234:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)

这是因为多个“API Uploads”目录创建是并行触发的。当“API Uploads”目录已经存在时,不会出现该问题。

为了修复我的迁移脚本,我同步上传了第一个文件(以确保“API Uploads”目录创建仅完成一次),然后并行上传其他文件(每批 20 个)。有了这种行为,问题就不会发生。

预期行为

并发问题不应该发生。

回答

9

请注意,并行创建多个目录时也存在类似的问题:

 error: insert into "public"."upload_folders" ("created_at", "created_by_id", "name", "path", "path_id", "updated_at", "updated_by_id") values ($1, $2, $3, $4, $5, $6, $7) returning "id" - duplicate key value violates unique constraint "upload_folders_path_id_index"
error: insert into "public"."upload_folders" ("created_at", "created_by_id", "name", "path", "path_id", "updated_at", "updated_by_id") values ($1, $2, $3, $4, $5, $6, $7) returning "id" - duplicate key value violates unique constraint "upload_folders_path_id_index"
    at Parser.parseErrorMessage (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:287:98)
    at Parser.handlePacket (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:126:29)
    at Parser.parse (/.../strapi-migration-test/node_modules/pg-protocol/dist/parser.js:39:38)
    at Socket.<anonymous> (/.../strapi-migration-test/node_modules/pg-protocol/dist/index.js:11:42)
    at Socket.emit (node:events:513:28)
    at Socket.emit (node:domain:489:12)
    at addChunk (node:internal/streams/readable:324:12)
    at readableAddChunk (node:internal/streams/readable:297:9)
    at Readable.push (node:internal/streams/readable:234:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)

我通过串联而不是并行创建目录来“解决”这个问题。

3

抱歉,德里克不在。我正在阅读您的问题,但它不是很清楚,您能否添加一些我们可以遵循的简单重现步骤?

编辑:我还可以清楚地表明,发生此错误时您没有使用数据传输吗?

2

重现:

  1. 在 Postgre 上启动 Strapi(在 sqlite 上没有问题)
  2. 创建以下index.mjs文件:
import {StrapiClient} from '@smile/strapi-client';
const strapiClient = new StrapiClient('http://127.0.0.1:1337', 'token', 'admin_token');
await Promise.all([
    strapiClient.createMediaFolder('Directory 1'),
    strapiClient.createMediaFolder('Directory 2'),
])
  1. 代替:
    • 'token'使用有效的 Strapi 令牌
    • 'admin_token'使用有效的管理仪表板 JWT 令牌:在 Strapi 管理 UI 上时,您可以在浏览器控制台中使用以下脚本轻松获取它:JSON.parse(sessionStorage.jwtToken || localStorage.jwtToken)
  2. 下载所需的依赖项npm i @smile/strapi-client
  3. 运行脚本:node index.mjs

只应创建 1 个目录,并且 Strapi 日志中应显示错误。

您还可以通过用图像上传替换文件夹创建来轻松地重现使用相同脚本并行上传文档的问题。您可以使用StrapiClient.addMediaAsset(...)函数来实现此目的。

我没有使用数据传输。

9

感谢您的更新:)

2

您好,我创建了一个 PR 来防止创建文件夹时的竞争条件,这应该可以解决此问题。 https://github.com/strapi/strapi/pull/17146

我将在本周对此进行测试,并创建一个实验版本,以防您想尝试一下。

7

谢谢@Marc-Roig。您认为它还能解决一次上传多个文件时的问题吗(并且尚不存在“API Uploads”文件夹)?

6

它在我的机器上工作,我创建了一个实验版本:0.0.0-experimental.e30dccd40a6b6f762843005e6baefe4f2f82d919

如果有机会的话,你能尝试一下,看看它是否适合你? ?

6

我想整理一些失败的测试,但是现在一次上传多个文件时不应该出现任何错误:)

7

它在我的机器上工作,我创建了一个实验版本:0.0.0-experimental.e30dccd40a6b6f762843005e6baefe4f2f82d919

如果有机会的话,你能尝试一下,看看它是否适合你? ?

@Marc-Roig 我更新到0.0.0-experimental.e30dccd40a6b6f762843005e6baefe4f2f82d919package.json安装,重新启动并在“设置”>“概述”中看到相应的版本。但这并不能解决问题,无论是并行图像上传还是并行目录创建。

8

@marob 谢谢你测试这个!!我将尝试使用您的数据库进行复制,并提出适合您的解决方案。

4

@derrickmehaffy 我没有看到任何与解决并发错误相关的内容。再次强调,这张票与数据传输没有任何关系。请重新打开该问题。

0

@derrickmehaffy 我没有看到任何与解决并发错误相关的内容。再次强调,这张票与数据传输没有任何关系。请重新打开该问题。

啊抱歉,我会重新打开。

您能否提供您正在使用的迁移脚本的示例,以便我们可以重现?