问题标签 [occasionallyconnected]

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 投票
0 回答
333 浏览

winforms - 偶尔连接的 Winforms 应用程序的现代同步策略

我的任务是为一家拥有大约 10 个地点的小公司编写一个 Winforms 服务点应用程序。它有一个相当简单的数据库结构,包含客户、发票、交易、商店、车辆等表。我正在考虑使用 Azure SQL 数据库作为“主”数据库,但该应用程序对每个位置都至关重要,需要有一个“偶尔连接”的架构,以确保它可以在互联网连接不可用时运行,然后在连接恢复时同步。

我研究了 Microsoft Sync Framework,这似乎是最好的选择,但所有文档似乎都有几年的历史并且已经过时了。

Azure 数据同步看起来很有希望,但这似乎更像是一种 Azure 管理类型的工具,而我希望将同步功能内置到客户端应用程序中。

一些移动解决方案听起来很有趣,但在我看来,我需要在客户端和云服务器上基本相同的 SQL Server 数据库,而且大多数(如果不是所有)表都需要保持同步。我认为最简单的方法是为每个实体和同步框架使用 GUID ID,或者滚动我自己的代码进行同步。

所以,我想我的问题是:

  • 创建偶尔连接的 Winforms 应用程序的一般推荐的最新方法是什么?
  • MS 同步框架是否仍然相关?
  • 我在客户端和服务器上拥有相同的数据库、对实体使用 GUID ID、使用 MS Sync Framework 或滚动我自己的同步代码的想法是合理的还是疯狂的?

谢谢。

0 投票
1 回答
260 浏览

event-sourcing - 偶尔连接系统中的事件溯源:如果有两台服务器怎么办?

我最近正在努力解决这个问题。

单服务器场景

您有一个偶尔连接到单个服务器的客户端。

我最近再次在 Skillsmatter.com 上观看了关于偶尔连接系统的 greg youngs 视频

他在那里指出,处理它的最佳方法是:

  • 您有一个使用事件流的客户端。
  • 客户端将其已执行的所有命令保存在队列中
  • 当服务器再次可用时,客户端推送所有命令并再次下载结果事件(在本地,客户端删除本地发出的事件,因为服务器是唯一的事实来源

现在这一切都很好,但我有一个更复杂的场景 - 一个有两台服务器:测试和生产

多服务器服务

  • 所以客户端用于创建某种模板
  • 然后它连接到测试服务器并推送它的命令 => 我们在测试服务器上有一个新的模板版本
  • 客户端有时会重新连接到测试服务器并更改模板
  • 然而,在某一时刻,该模板将被发布到生产服务器。

您也可以将其视为 git 合并场景,您希望将所有更改从分叉的远程存储库 A 推送到原始远程存储库 B。

问题是:

  1. 一旦客户端将其更改推送到测试环境,命令就消失了 - 那么它如何将任何更改推送到生产环境......
  2. 另外:可能会使用另一个用户将新模板实际发布到生产环境。(例如,因为发布是由 IT 人员而不是开发人员完成的)

所以我猜这个问题基本上有两种解决方案: a)保持命令流并将其下载到客户端 - 但这与在事件溯源系统中仅存储事件的事实相冲突b)有一种机制从已经提交的事件中重新创建命令。这样,客户端可以查看 Production 上的模板版本,以查看尚未在那里发出哪些事件。然后它相应地创建命令并执行它们。

我的问题:

  1. 我想这里只有 b 是一个可行的选择?
  2. 选项 b 是否违反事件溯源和/或 cqrs 的任何规则/原则?
  3. 有没有其他甚至更好的方法来做到这一点?

谢谢你们的想法!



更新

感谢您分享您的想法。但似乎我必须澄清一些事情 - 测试和生产的事情。

让我们假设我们正在构建一些应用程序框架,如 salesforce:您可以 - 通过使用点击 - 定义您的应用程序及其实体和工作流等。当然,您可以在单独的沙盒环境中执行此操作。当您完成第一个应用程序版本时,您将希望将其移至生产服务器,以便您的用户可以实际使用您“构建”的应用程序。

现在考虑以下几点:在生产中,您意识到存在一个小错误,并且您立即修复它。然后,您希望将这些更改传输回测试环境。

所以现在的问题是:真相的来源到底是什么?

正如大多数开发人员所知,我喜欢将其与 git 进行比较。基本上我可以看到我有两个选择:

  1. git rebase

其中一种环境是记录簿。所以在这种情况下,我必须收集所有命令,一旦我更新生产,我就会推送命令。这就像一个git rebase

  1. git 合并

让我们假设这两个系统都是“记录簿”。在这种情况下,我需要同步测试环境中发生的事件和生产环境中发生的事件(所以我在测试和生产中得到了完全相同的应用程序定义)所以来自测试的事件不只是附加到事件流中生产,但按实际发生的顺序在生产事件流中排序。这就像一个git 合并

我个人更喜欢git merge选项,因为它导致两个系统中的事件顺序完全相同。当然,这将允许偶尔连接的客户端使用相同的方法进行分布式协作:假设我们在测试中定义并使用此事件源方法发布到生产环境的应用程序随后被多个偶尔连接的客户端用于实际收集数据. 现在,多个客户端可以在相同的聚合根同步上一起工作,彼此和服务器(就像在 peer2peer 系统中一样),同时仍然保持相同的事件流顺序。

但是,问题可能是客户端将事件 e1 同步到服务器,但该事件对应的聚合根已经处理了稍后发生的事件 e2。所以事件处理会出现问题。

所以我的问题是:这个“git merge”有什么明显的缺点吗?

0 投票
1 回答
62 浏览

cqrs - 如何在使用 CQRS 和事件源的偶尔连接的系统上选择将哪些事件发送给用户?

我正在构建一个用户可以编辑和共享笔记的网络应用程序。用户应该通过角色(所有者、读取、读写)连接到笔记。这是一个偶尔连接的系统,所以我选择使用 CQRS 和事件源进行同步。在Greg Young 的演讲 [36:20 - 38:40]之后,流程如下:

  1. 客户端在离线时进行更改。
  2. 客户端连接到 Internet。
  3. “存储和转发”发送客户端离线时发生的事件。
  4. 客户端将本地事件与接收到的事件进行比较并进行合并,决定保留哪些命令。然后更新本地视图模型。
  5. 客户端将存储的命令(离线创建)发送到服务器。
  6. 服务器执行命令并生成存储在事件存储中的事件。
  7. “存储和转发”保存每个用户感兴趣的事件,直到用户重新上线。

问题是:“存储和前言”如何决定应该向每个用户发送哪些事件?

显然,发送所有事件会危及其他用户的安全。