Meilisearch 中的许多操作都是异步处理的。这些 API 请求不会立即处理——相反,Meilisearch 会将它们放入队列并按接收顺序依次处理。

哪些操作是异步的?

所有可能耗时较长的操作都会以异步方式处理。异步处理操作使得 Meilisearch 能够在不影响搜索性能的前提下执行资源密集型任务。

目前,Meilisearch 的异步操作包括:

  • 创建索引
  • 更新索引
  • 交换索引
  • 删除索引
  • 更新索引设置
  • 向索引添加文档
  • 更新索引中的文档
  • 从索引删除文档
  • 取消任务
  • 删除任务
  • 创建数据转储
  • 创建快照

理解任务机制

当 API 请求触发异步流程时,Meilisearch 会创建一个任务并将其放入任务队列中。

任务对象

任务对象包含允许您跟踪进度并在出现问题时进行故障排除的信息。

一个任务对象包含原始请求中没有的数据,例如请求入队时间、请求类型以及任务失败时的错误代码:

{
    "uid": 1,
    "indexUid": "movies",
    "status": "enqueued",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
        "receivedDocuments": 67493,
        "indexedDocuments": null
    },
    "error": null,
    "duration": null,
    "enqueuedAt": "2021-08-10T14:29:17.000000Z",
    "startedAt": null,
    "finishedAt": null
}

如需了解每个任务对象字段的完整说明,请查阅任务 API 参考文档

任务摘要对象

当你发起异步操作的 API 请求时,Meilisearch 会返回完整 task 对象的摘要版本

{
  "taskUid": 0,
  "indexUid": "movies",
  "status": "enqueued",
  "type": "indexCreation",
  "enqueuedAt": "2021-08-11T09:25:53.000000Z"
}

使用摘要任务的 taskUid 可以跟踪任务进度

任务状态(status)

任务对象始终包含一个表示当前 status 的字段。该字段可能为以下值之一:

  • enqueued:任务已接收,即将处理
  • processing:任务正在处理中
  • succeeded:任务已成功处理
  • failed:处理任务时发生错误。数据库未做任何更改
  • canceled:任务已被取消

succeededfailedcanceled 状态表示任务已完成。Meilisearch 会将这些任务保留在任务数据库中,但已完成处理。你可以配置 webhook 在任务完成时通知外部服务。

enqueuedprocessing 状态表示任务未完成。Meilisearch 正在处理这些任务或将在未来进行处理。

全局任务

某些任务类型不与特定索引关联,而是应用于整个实例。这类任务被称为全局任务。全局任务的 indexUid 字段始终显示为 null

Meilisearch 将以下任务类型视为全局任务:

在受保护的实例中,您的 API 密钥必须拥有对所有索引的访问权限("indexes": [*])才能查看全局任务。

任务队列

创建任务后,Meilisearch 会将其放入队列中。排队的任务按照请求顺序逐个处理。

当任务队列达到其限制(约 10GiB)时,会抛出 no_space_left_on_device 错误。用户需要通过删除任务端点删除任务才能继续写入操作。

任务队列优先级

Meilisearch 将某些任务视为高优先级任务,始终将其置于队列前端。

以下类型的任务会立即被处理:

  1. taskCancelation(任务取消)
  2. taskDeletion(任务删除)
  3. snapshotCreation(快照创建)
  4. dumpCreation(转储创建)

所有其他任务按照入队顺序处理。

任务工作流

当您发起异步操作请求时,Meilisearch 会按照以下统一流程处理所有任务:

  1. Meilisearch 创建任务,将其放入任务队列,并返回一个简化的task对象。此时任务status设为enqueued(已入队)
  2. 当任务到达队列前端时,Meilisearch 开始处理它。此时任务status设为processing(处理中)
  3. Meilisearch 完成任务处理。如果任务成功处理,状态设为succeeded(成功);如果出现错误,则设为failed(失败)

在异步操作过程中终止 Meilisearch 实例是完全安全的,这永远不会对数据库造成负面影响。

任务批次

Meilisearch 以批次为单位处理任务,通过任务分组实现最佳性能。在大多数情况下,批处理应该是透明的,不会对整个任务工作流产生影响。使用/batches路由可以获取有关批次及其处理方式的更多信息。

取消任务

您可以通过取消任务端点来取消处于enqueued(已入队)或processing(处理中)状态的任务。取消操作会将任务status更改为canceled(已取消)。

终止 Meilisearch 实例不会导致任务被取消。Meilisearch 会丢弃所有processing(处理中)任务的进度,并将其重置为enqueued(已入队)状态。实例重新启动后,任务处理会正常继续。

删除任务

已完成的任务会继续保留在任务列表中可见。如需手动删除,请使用删除任务接口

Meilisearch 在任务数据库中最多存储 100 万条任务。如果新增任务会导致超出此限制,Meilisearch 会自动尝试删除最旧的 10 万条已完成任务。如果数据库中没有已完成任务,Meilisearch 不会删除任何内容,而是照常将新任务加入队列。

示例

假设您使用添加文档端点向实例添加新文档,并收到一个 taskUid 作为响应。

当您使用该值查询获取任务端点时,会看到任务状态为 enqueued(已排队):

{
    "uid": 1,
    "indexUid": "movies",
    "status": "enqueued",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
        "receivedDocuments": 67493,
        "indexedDocuments": null
    },
    "error": null,
    "duration": null,
    "enqueuedAt": "2021-08-10T14:29:17.000000Z",
    "startedAt": null,
    "finishedAt": null
}

稍后,您再次检查任务进度。此时任务已成功处理,状态变为 succeeded(已完成):

{
    "uid": 1,
    "indexUid": "movies",
    "status": "succeeded",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
            "receivedDocuments": 67493,
            "indexedDocuments": 67493
    },
    "error": null,
    "duration": "PT1S",
    "enqueuedAt": "2021-08-10T14:29:17.000000Z",
    "startedAt": "2021-08-10T14:29:18.000000Z",
    "finishedAt": "2021-08-10T14:29:19.000000Z"
}

如果任务失败,响应中将包含详细的 error 对象:

{
    "uid": 1,
    "indexUid": "movies",
    "status": "failed",
    "type": "documentAdditionOrUpdate",
    "canceledBy": null,
    "details": {
            "receivedDocuments": 67493,
            "indexedDocuments": 0
    },
    "error": {
        "message": "Document does not have a `:primaryKey` attribute: `:documentRepresentation`.",
        "code": "internal",
        "type": "missing_document_id",
        "link": "https://docs.meilisearch.com/errors#missing-document-id"
    },
    "duration": "PT1S",
    "enqueuedAt": "2021-08-10T14:29:17.000000Z",
    "startedAt": "2021-08-10T14:29:18.000000Z",
    "finishedAt": "2021-08-10T14:29:19.000000Z"
}

如果任务在 enqueued(已排队)或 processing(处理中)状态时被取消,其状态将变为 canceled(已取消),且 canceledBy 字段会有非 null 值。

当任务被删除后,尝试访问该任务将返回 task_not_found 错误。