查询重复聚合根属性的写模型

时间:2014-04-22 09:47:14

标签: c# nservicebus cqrs event-sourcing neventstore

我通过事件采购实施CQRS模式,我使用NServiceBus,NEventStore和NES(NSB和NEventStore之间的连接)。

我的应用程序将定期检查Web服务是否有任何要下载和处理的文件。找到a文件后,会向总线发送一个命令(DownloadFile),并由FileCommandHandler接收,该命令会创建一个新的聚合根(File)并处理该消息。

现在在(文件聚合根目录)内部,我必须检查文件的内容是否与任何其他文件内容不匹配(因为Web服务保证只有文件名是唯一的,并且内容可能是用不同的名称复制,通过散列并与散列内容列表进行比较。

问题是我必须保存哈希码列表?是否允许查询读取模型?

public class File : AggregateBase
{
    public File(DownloadFile cmd, IFileService fileDownloadService, IClaimSerializerService serializerService, IBus bus)
            : this()
        {
        // code to download the file content, deserialize it, and publish an event.
        }
}

public class FileCommandHandler : IHandleMessages<DownloadFile>, IHandleMessages<ExtractFile>
{
        public void Handle(DownloadFile command)
        {
             //for example, is it possible to do this (honestly, I feel it is not, since read model should always considered stale !)
            var file = readModelContext.GetFileByHashCode (Hash(command.FileContent));
            if (file != null)
                throw new Exception ("File content matched with another already downloaded file");

            // Since there is no way to query the event source for file content like:
            // eventSourceRepository.Find<File>(c=>c.HashCode == Hash(command.FileContent));
        }
}

3 个答案:

答案 0 :(得分:0)

这取决于很多事情......吞吐量就是其中之一。但是,既然你正在以“基于拉取”的方式解决这个问题(你正在查询网络服务以进行工作(下载和分析文件)),你可以使整个过程连续进行而不必担心冲突。现在,这可能无法提供您想要处理“工作”的理想速度,但更重要的是......您有没有测量过?让我们回避这一点,并假设序列不起作用。我们在谈论多少个文件?几百,1000,......百万?取决于散列可能适合内存并且可以在进程应该降低时重建。可能还有机会按时间轴或上下文划分问题。自黎明开始或刚刚今天的每个文件,还是本月的文件价值?真的,我认为你应该深入挖掘你的问题空间。除此之外,这感觉就像使用事件采购解决一个尴尬的问题,但YMMV。

答案 1 :(得分:0)

如果您的域中具有真正的唯一性约束,则可以使唯一性测试器成为域服务,其实现是基础结构的一部分 - 类似于存储库,其接口是域的一部分及其实现是基础设施的一部分。对于实现,您可以使用内存中的哈希或根据需要更新/查询的数据库。

答案 2 :(得分:0)

好像您正在寻找重复数据删除。

您的命令端是您希望事物保持一致的地方。查询将始终让您对竞争条件开放。因此,我不是运行查询,而是反转逻辑并实际将哈希写入数据库表(任何具有ACID保证的数据库)。如果此写入成功,则处理该文件。如果写入散列失败,则跳过处理。

没有必要将此逻辑放入处理程序中,因为如果失败(即多次存储哈希值)重试消息将无法使其成功。您还会在错误q中找到重复文件的消息。

重复数据删除逻辑的一个好地方可能在您的Web服务客户端中。一些伪逻辑

  1. 获取档案
  2. 打开交易
  3. 将哈希值插入数据库&amp;捕获失败(没有任何失败,只有插入失败)
  4. 如果在步骤3中插入的记录数不为零,则将消息发送到处理文件
  5. 提交交易
  6. NServiceBus网关here

    中的一些重复数据删除代码示例

    编辑:
    看看他们的代码,我实际上认为session.Get<DeduplicationMessage>是不必要的。 session.Save(gatewayMessage);应该足够并且是一致性边界。

    只有在失败率很高的情况下执行查询才有意义,这意味着您有大量重复的内容文件。如果99%以上的插入成功,则重复项确实可以视为异常。