跳至主要内容

数据库事件

结构

数据库更改事件的结构取决于模型和执行的操作类型。您可以在API 参考中了解更多信息。

以下示例基于此User模型

model User {
id Int @id @default(autoincrement())
name String?
email String @unique
}

所有事件都具有以下共同字段

  • id:唯一标识符
  • action:执行的事件类型,可以是以下之一:createupdatedelete

根据事件类型,通过 Prisma Pulse 收到的事件对象中可能存在其他字段。请参阅以下部分以了解一些示例事件。

创建事件

以下是在创建新记录时您可能收到的事件对象示例

{
action: 'create',
created: { id: 3, email: '[email protected]', name: 'Jane Doe' },
id: '0/2A5A590'
}

更新事件

以下是在更新记录时您可能收到的事件对象示例

{
action: 'update',
after: { id: 2, email: '[email protected]', name: 'Jane Doe' },
before: null,
id: '0/2A5A248'
}

如果您希望before字段承载记录在更新之前的值,则需要将REPLICA IDENTITY设置为FULL,如此处所述。在这种情况下,事件对象可能如下所示

{
action: 'update',
after: { id: 2, email: '[email protected]', name: 'Jane Doe' },
before: { id: 2, email: '[email protected]', name: 'Jane' },
id: '0/2A5A248'
}

删除事件

以下是在删除记录时您可能收到的事件对象示例

 {
action: 'delete',
deleted: { id: 1 },
id: '0/2A5A398'
}

如果您希望deleted字段承载已删除记录的值,则需要将REPLICA IDENTITY设置为FULL,如此处所述。否则它将只承载记录的id值。在这种情况下,事件对象可能如下所示

 {
action: 'delete',
deleted: { id: 21, email: '[email protected]', name: 'Jane Doe' },
id: '0/2A5A398'
}

传递语义

本节概述了 Prisma Pulse 的事件传递语义。

什么是事件传递语义?

事件传递语义描述了事件生产者在事件驱动架构中关于事件传递所能提供的保证

通常有三种传递保证

  • 最多一次:事件要么传递一次,要么根本不传递。
  • 至少一次:事件传递一次或多次,确保它绝不会未传递。
  • 恰好一次:事件恰好传递一次,避免重复。

Prisma Pulse 中的事件传递语义

以下是 Prisma Pulse 中事件传递语义的摘要

stream()subscribe()
需要事件持久化
传递保证至少一次最多一次
事件顺序与事件生成时的顺序相同可能与事件生成时的顺序不同
可以“重放”错过的事件
警告

请注意,如果事件超过了您订阅计划大小限制,则该事件将被拒绝,并且不会传递到您的应用程序。

stream()

使用stream()时,Prisma Pulse 提供以下传递保证

至少一次传递

使用stream()流式传输数据库更改事件时,数据库更改事件保证以至少一次语义传递,这意味着 Prisma Pulse 可以保证数据库中发生的任何事件都将传递一次或多次。

按正确顺序传递事件

Prisma Pulse 进一步保证按事件生成的顺序传递数据库更改事件。

恰好一次传递

虽然 Pulse 默认提供至少一次语义,但它也为您提供了自行实现恰好一次传递保证的原语

Prisma Pulse 生成的每个事件都包含一个标识符/幂等键,您可以将其用于在事件的下游处理过程中去重。这最好通过将标识符传递到支持幂等的外部服务或在使用数据库时使用 upsert 等概念来实现。

此事件有效负载中针对User模型的id字段表示标识符/幂等键

{
action: 'update',
after: { id: 1, name: 'Jane', email: "[email protected]" },
before: null,
id: '01HYBEER1JPSBVPG2NQADNQTA6'
}

subscribe()

最多一次传递

使用.subscribe()流式传输数据库更改事件时,数据库更改事件保证以最多一次语义传递,这意味着某些数据库事件可能会丢失。

不保证事件的顺序

subscribe()不提供任何关于事件到达顺序的保证。

事件持久化

您可以在控制台项目中配置 Pulse 的事件持久化。只有在启用事件持久化的情况下,您才能通过stream() API 利用 Prisma Pulse 提供的至少一次正确顺序传递保证。

哪些事件会被持久化?

一旦您在控制台项目中为 Pulse 启用事件持久化,Pulse 将存储来自所有表所有数据库事件。

事件以什么形式被持久化?

事件以与传递时相同的结构被持久化。

事件持久化如何影响定价?

启用事件持久化后,定价将受到以下影响

  • 数据库事件:Pulse 捕获的数据库事件数量
  • 事件读取:Pulse 通过.stream()读取传递的数据库事件数量
  • 事件存储:存储的事件消耗的磁盘空间量(以 GiB 为单位)

有关更多详细信息,请参阅订阅计划。无论您使用subscribe()还是stream(),都适用定价。

恢复事件流

stream() API 提供了提供name参数的选项,这使得流可恢复

const stream = await prisma.user.stream({
name: "all-user-events"
})

如果提供了name,则 Pulse 使用游标跟踪事件的传递。只有在接收方确认事件后,与该name关联的游标才会移动。

如果由于某种原因(例如,您的服务器已关闭)流不可用,则接收方无法确认任何事件。一旦流再次可用,该流将从上次游标位置继续,并在同时传递任何尚未确认的事件

Resuming event streams with a name argument

如果省略了name选项,则不会将任何游标与流关联,并且流关闭期间发生的事件将不会传递。

Resuming event streams without a name argument

请注意,如果提供了name,则在任何给定时间,只有一个客户端可以连接到具有该特定name的流。