问题标签 [event-sourcing]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
96 浏览

c# - 通过测试命令和事件记录文档

我愿意通过我的测试生成一些文档。到目前为止,我的测试看起来像这样:

不幸的是,在使用 Nunit 时,我很难获得所需的信息以生成一些漂亮且易于阅读的文档。

你们中有人使用 Nunit 来做到这一点吗?你能给我指出一些有趣的资源吗,我会在网上忽略吗?您是否使用其他工具从测试中生成文档?

[编辑] 我的意图是从我的代码中生成如下内容:

这适用于第一种方法。我以后可能会改变,但主要目标是这个。我的目标是能够在不让他输入代码的情况下写出我的老板可能会理解的东西。

[/编辑]

0 投票
4 回答
160 浏览

architecture - 重新生成查询数据库

我拥有的网站有一个运行良好的简单 CQRS 架构。一个事件被不同的订阅者发布和接收,其中一个使报告数据库保持同步[在 RavenDb 中]。

例如,我的报告数据库已损坏/丢失。使用事件溯源,我可以重播事件并重建报告数据库,但是我 [当前] 不使用事件溯源;我有一个简单的 nHibernate 持久化到关系存储。解决方案是创建一个“重新生成”类型的脚本,该脚本基本上将基于关系存储发送所有事件(例如,PersonCreatedEvent 后跟 30xPersonLikedBlogPostEvent 等)?它本质上与事件源所做的事情相同,但事件是从关系模型中推断出来的。

可维护性和 DR 显然很重要。

0 投票
2 回答
827 浏览

c# - EventStore 和 RavenDB 持久性 JsonReaderException

试图将JOliver 的 EventStoreRavenDB 连接起来,但遇到了麻烦。我在 Raven 中创建了一个名为 RavenEventStore 的新数据库。

以下是我的接线图;

当调用 Wireup.Init() 时,此异常发生在 RavenDb 端;

网址:“/indexes/RavenCommitByDate”Newtonsoft.Json.JsonReaderException:解析值时遇到意外字符:。第 1 行,位置 1。在 Newtonsoft.Json.JsonTextReader.ParseValue(Char currentChar) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonTextReader.cs:Newtonsoft.Json.JsonTextReader.ReadInternal 的第 699 行() 在 d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonTextReader.cs:line 499 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, Type t, JsonConverter propertyConverter) in d:\ Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) 中的第 1072 行:

我也可以在 RavenDB 日志中看到异常;

我试图通过删除 UsingAsynchronousDispatchScheduler() 方法来消除所有可能性,并引发相同的错误。我使用的代码严格来自此处的示例: https ://github.com/joliver/EventStore/blob/master/doc/EventStore.Example/MainProgram.cs

有没有人经历过这个?在谷歌上也找不到任何东西。

0 投票
4 回答
4882 浏览

system.reactive - 反应式扩展是否适合公共汽车?

我一直在使用 Rx 在单个应用程序中创建事件总线(想想 CQRS/ES),它似乎工作得很好。然而,在调查了一堆不同的事件溯源框架之后,我还没有看到使用过一次 Rx。与基于反射/容器的调度程序相比,它似乎非常适合,但也许我缺少一些东西。我宁愿不花很多时间在 3 个月内大获成功的事情上。Rx 不适合有什么原因吗?

谢谢,埃里克

0 投票
2 回答
388 浏览

system.reactive - 使用 ReplaySubject 将事件添加到 Rx 可观察对象的开头 - 可能吗?

我正在使用 Rx(反应式框架)实现总线,到目前为止它看起来不错。我现在面临的问题是如何在流开始之前添加事件。

为了提供更多上下文,这是针对事件源(a la CQRS/ES)。当总线启动时,一些订阅者会得到IObservable。此时,总线会询问订阅者他们需要从什么事件编号/顺序开始。事件从最低编号开始从磁盘加载并添加到流中,每个订阅者使用 where 语句从正确的事件开始。随着应用程序的运行,新事件被添加并发送给订阅者。这部分效果很好。

一些迟到的订阅者,但仍需要所有事件。看起来ReplaySubject符合要求,只要事件的数量足够小。我在想我可能可以做一些磁盘/离线缓存来保留更多它们(欢迎任何指针!)。

更大的问题是,当一些订阅者获取 IObservable 时,他们需要获取在最初加载的事件之前发生的事件。像下面这样的情况。

当公共汽车启动时,它会向前加载事件#50(最早的人想要的)。现在,一个新的订阅者请求 IObservable,除非他们需要从 #20 开始。所以我想做的是加载 20-49,并在流开始之前添加它们。现有订阅者都不应看到任何事件(它将被 Where 过滤)。

看起来这应该是可能的,但我无法完全理解它。这在 Rx 中可能吗?如果是这样,怎么做?

谢谢!埃里克

0 投票
3 回答
2522 浏览

cqrs - 为什么事件存储应该在写端?

事件溯源被认为是许多事情的奖励,例如事件历史/审计跟踪、完整和一致的视图再生等。听起来很棒。我是粉丝。但这些都是读取端的实现细节,您可以通过将事件存储完全移动到读取端作为另一个订阅者来完成相同的操作。为什么不呢?

这里有一些想法:

  1. 视图/非规范化器本身并不关心事件存储。他们只是处理来自域的事件。
  2. 将事件存储移动到读取端仍然可以为您提供事件历史记录/审计
  3. 您仍然可以从事件存储中重新生成视图。除了现在它不必是写入模型泄漏。给他读模范公民!

这似乎是将其保留在写入端的一个技术论据。这是来自http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/的 Greg Young 的:

然而,使用存储当前状态快照的东西存在一些问题。最大的问题围绕着您向数据引入了两个模型这一事实。您有一个事件模型和一个表示当前状态的模型。

我觉得有趣的是术语“快照”,它最近也成为事件溯源中的一个显着术语。在写入端引入事件存储会增加加载聚合的一些开销。您可以争论多少开销,但这显然是一个感知或预期的问题,因为现在有从快照加载聚合和自快照以来的所有事件的概念。所以现在我们又有了……两个模型。不仅如此,我看到的快照建议旨在作为基础设施泄漏来实现,后台进程会遍历整个数据存储以保持性能。

在拍摄快照后,快照之前的事件从写入的角度来看 100% 无用,除了……重建读取端!这似乎是错误的。

另一个与性能相关的话题:文件存储。有时我们需要将大型二进制文件附加到实体。从概念上讲,有时这些与实体相关联,但有时它们是实体。将这些放在事件存储中意味着您必须在每次加载实体时物理加载该数据。这已经够糟糕的了,但想象一下其中有几个或数百个这样的大集合。我看到的每个答案基本上都是咬紧牙关并将uri传递给文件。这是一种逃避,会破坏分布式系统。

然后是维护。重建视图需要一个涉及事件存储的过程。因此,现在您编写的每个视图维护任务都进一步将您的写入模型绑定到使用事件存储......永远。

CQRS 的重点不是围绕读模型和写模型的用例根本不兼容吗?那么为什么我们要把读模型的东西放在写端,牺牲灵活性和性能,然后再把它们耦合起来。为什么要花时间?

所以总而言之,我很困惑。在我所坐的所有方面,事件存储作为读取模型细节更有意义。您仍然可以获得保留事件存储的许多好处,但您不会过度抽象写入端持久性,这可能会降低灵活性和性能。而且您不会通过泄漏的抽象和维护任务将您的读/写端耦合起来。

那么有人可以向我解释一个或多个令人信服的理由将其保留在写入方面吗?或者,为什么不应该将其作为维护/报告问题放在读取端?同样,我不是在质疑商店的实用性。就在它应该去的地方:)

0 投票
2 回答
526 浏览

domain-driven-design - 事件溯源和重建逻辑

我是事件溯源的新手,我对从事件流中重建对象有点困惑。

我相信我们需要按时间顺序运行加载所有发生的事件以重建对象状态。所以例如

如果我有一个名为客户的对象。

如果客户更改了两次名称,我们将在事件日志中存储两次事件,当我将事件重建为对象时,我将获得两次事件。是否需要采取上一个事件或归档事件,以便我们不再重新运行最后一个事件

0 投票
2 回答
1113 浏览

cqrs - Saga , 命令, 事件 & ReadModel

我目前正在编写我的第一个 saga,我对读取模型有点困惑。让我们用一个例子来解释它:

我有三个有界上下文:编程承包商控制。它们中的每一个都有其特定的读取模型。

工作流程:

  • 编程发送事件“ JobScheduled
  • Saga收到此事件并告诉承包商安排工作”。
  • 完成后,承包商发送事件“ JobDone ”。
  • Saga接收到这个事件并告诉控制开始控制周期”。

事实证明这里一切都很好。我们处于写入端,因此我们正在传递重要信息以使流程继续进行。

我的问题带有不必要的信息。假设事件“ JobScheduled ”有一个备注字段:“测试备注”,在此作业完成之前,该字段更改为“测试备注重要”。这种变化对所描述的工作流并不重要,但重要的是,承包商在查看承包商有界上下文的读取模型时可能会看到现场的变化。

我是给传奇事件NoteChanged并对其进行处理,还是应该创建一个在我的承包商有界上下文中直接监听此事件的投影?

将它交给saga在我看来像是不必要的工作,因为我只是在这里更新 readmodel,没有涉及更改的域。

另一方面,在两个有界上下文之间进行直接耦合会删除 sagas 的一个资产,即修改有界上下文在工作流中彼此之间的交互的可能性。

感谢您的阅读,

0 投票
2 回答
2849 浏览

cqrs - 可以在事件溯源中创建大型事件吗?

我们正在使用事件溯源并从事件流中构建聚合。我有 2 个聚合 - A1 和 A2。A1 用作模板以创建 A2。A1 的尺寸可能相当大。事件溯源的基本思想是确保对应用程序状态的每次更改都被捕获到事件对象中。所以要保存 A2,我们必须在第一个事件中存储大量信息。

这种情况是常见的还是从模板创建不是一个好主意?有没有更好的方法来解决它?

0 投票
1 回答
915 浏览

cqrs - 使用 CQRS 和 EventStore 创建并发

基线信息: 我正在使用外部 OAuth 提供程序进行登录。如果用户登录到外部 OAuth,他们可以进入我的系统。但是,此用户可能尚不存在于我的系统中。这不是真正的技术问题,但我使用 JOliver EventStore 是为了它的价值。

逻辑:

  1. 我没有为新用户提供指南。我只有一个电子邮件地址。
  2. 我在发送命令之前检查我的读取模型,如果用户电子邮件存在,我会发出带有 ID 的登录命令,如果不存在,我会发出带有生成 ID 的 CreateUser 命令。我的问题是新用户的情况。
  3. 使用新 ID 在事件存储中进行保存。

问题: 假设由于浏览器刷新或在实现与读取模型的一致性之前发生的一些其他异常,在读取模型更新之前以某种方式发出了两个创建命令。没关系,这不是我的问题。

发生了什么: 因为新 ID 是一个 Guid 梳,所以事件存储不可能知道这两个 CreateUser 命令代表同一个用户。当他们到达读取模型时,读取模型将知道(因为他们有相同的电子邮件)并且可以合并两条记录或采取其他一些补偿措施。但是现在我的读取模型与事件存储不同步,事件存储仍然认为这是两个独立的实体。

也许没关系,因为:

  1. 重放事件将对读取模型产生相同的影响,因此应该没问题。
  2. 因为这两个命令都是重复的“创建”命令,所以它们应该包含相同的信息,所以我不会在事件存储中丢失任何东西。

谁能说明他们如何处理类似问题?如果需要进行一些补偿操作,读取模型服务是否会在意识到它有重复条目时发出某种补偿命令?有没有我不考虑的更简单的方法?