如何在事件源/事件中设计否决事件

时间:2019-03-12 05:07:58

标签: event-sourcing

让我们假设有一个简单的用例(java / microservice /事件源/事件):

  • 微服务A引入了一个用户实体
  • 微服务B引入了从我们的用户到某些外部用户存储的同步(也许是ldap等)

让我们假设B出于某种技术原因不能更改用户名,但是A本身允许更改用户名。

如何实施?在经典的整体作品中,我们可能会围绕 java.beans.VetoableChangeSupport。在微服务中,我遇到了麻烦。我的第一个想法是将其分为三个事件。

首先,我们发布一个事件,说明“用户名将被更改”。每当微服务B不喜欢时,第二个事件将是“取消用户名更改”。第三个事件是“用户名更改成功”。

到目前为止,它将起作用。但是我们如何实现呢?我不喜欢将所有微服务连接在一起的整体。我喜欢一些“插件”概念。只要我们不运行微服务B,就不会有人进行否决,我们将自动运行“用户名更改成功”。但是,一旦我们运行微服务B,我们就应该检查微服务B是否喜欢否决该事件。

我们如何将“微服务B未运行”从“微服务B当前处于脱机状态,但很快就会回来”呢?在第一种情况下,我们没有否决权。在第二种情况下,我们必须等待B再次回来检查未决的“用户名已更改”事件。

1 个答案:

答案 0 :(得分:0)

如果您不希望依赖于微服务B,那么我只允许最初更改名称并将对微服务B的拒绝视为最终的一致性异常。

因此,在微服务A中,您将尽最大努力确保更改不会引起与MS-B同步的问题。然后,记录“用户名已更改”事件。

如果MS-B不在运行,则说明您已完成操作,名称已更改。
如果MS-B 正在运行,并且在尝试同步更新的用户名时遇到问题,那么您将进入更正模式。确切的说,这取决于许多因素(问题发生的可能性,影响是什么,等等)。
您可能需要MS-B暂停并发送电子邮件,以便人工纠正情况。
否则,您可能让MS-B发出了撤消更改(另一个“用户名更改”或“名称更改恢复回X:-对您的域有意义的任何东西”)。

如果您发布补偿事件,则需要注意一些额外的例外情况,例如<?php # Connection info $hostname = 'server\instance,port'; $dbname = 'dbname'; $username = 'username'; $password = 'password'; # Connection try { $dbh = new PDO("sqlsrv:server=$hostname;Database=$dbname", $username, $password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch( PDOException $e ) { die( "Error connecting to SQL Server. ".$e->getMessage()); } # Statement try { $user_id = 123; $stat_id = 321; $val = '000'; $stmt = $dbh->prepare('insert into user_stats (user_id, stat_id, value) values (:user, :stat, :val)'); $stmt->bindParam(':user', $user_id); $stmt->bindParam(':stat', $stat_id); $stmt->bindParam(':val', $val); // OK, using bindParam() and a variaable //$stmt->bindValue(':val', '111'); // OK, using bindValue() //$stmt->bindParam(':val', '0'); // Error $stmt->execute(); } catch( PDOException $e ) { die( "Error connecting to SQL Server".$e->getMessage() ); } $stmt = null; # End $dbh = null; ?> 将其名称更改为User A,然后User X然后将其名称更改为User B。如果MS-B撤消了第一个名称更改,除非您也撤消了第二个名称更改,否则将使用重复的名称。 (或者,您可以在允许重新使用旧用户名之前将其“锁定”一定时间。)