事件存储无法写入软删除流

Event Store cannot write to soft deleted streams

澄清一下:这个问题是关于 Greg Young 的活动商店的。

我试图软删除包含 2 个事件的流:

var slice = con.ReadStreamEventsBackwardAsync(streamName, 0, 1, resolveLinkTos: true).Result;
es.DeleteStreamAsync(streamName, slice.LastEventNumber, hardDelete: false).Wait();

此次调用成功,对商店的调查揭示了一个新的元数据事件。此事件的类型为 $metadata 并包含:

{
  "$tb": 9223372036854775807
}

$tb代表"truncate before",在Deleting streams and events中有描述。文档说:

When you delete a stream, its TruncateBefore or $tb is set to the streams current last event number.

(正如您在上面的 json 中所见)并非如此。之前截断设置为 long.MaxVaue。虽然这似乎是不良行为,但这并不是真正的问题。 问题是我无法再写入流。调用以下片段成功完成,但不会将任何事件附加到流:

await es.AppendToStreamAsync(persistenceId, expectedVersion < 0 ? ExpectedVersion.NoStream : expectedVersion, events);

在上面的片段中,expectedVersion 设置为 -1。软删除流的元数据显示:

Stream is deleted: False
Meta Stream version: 0
Truncate before: 9223372036854775807
Max count:
Max age:

从流的最后一个事件中读取切片显示:

Last Event number: 1
Next Event number: -1
Status: StreamNotFound

有没有人遇到同样的问题并且可能找到了允许继续将事件附加到已删除的流的解决方案?

我通过 Pull Request 收到了一些有价值的信息。 首先,Event Store 的行为是正确的,即使它在当前时间点的行为与文档中描述的不一样。

我们无法写入流的原因是 EventStore 将我们的事件识别为重复事件并忽略了它。重复项是与之前收到的事件具有相同 ID 的事件 。事件 ID 是客户端生成的,既不是流名称也不是事件索引。

这意味着您在生成事件 ID 时必须小心。 确保您的活动 ID 是唯一的!

我们的问题是我们的事件 ID 是 Guid 确定性地根据流名称和事件计数生成的。事件计数是流中的事件数。软删除流包含 0 个事件,导致软删除后第一个事件的 id 与删除流前的第一个事件具有相同的 id(删除后的第二个事件生成的与删除前的第二个事件相同,等等)。

我们的解决方案是根据 StreamEventSlice.LastEventNumber(由 ClientApi 公开)而不是根据流中的事件数计算事件 ID。