跳到主要内容

数据库事件

结构

数据库更改事件的结构取决于模型和执行的操作类型。您可以在 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() 不提供任何关于事件到达顺序的保证。

事件持久性

您可以在您的 Console 项目中为 Pulse 配置 Event persistence。 只有启用 Event persistence,您才能通过 stream() API 利用 Prisma Pulse 的至少一次正确顺序交付保证。

哪些事件会被持久化?

一旦您在 Console 项目中为 Pulse 启用 Event persistence,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 的流。