Запрос модели записи для дублированного совокупного корневого свойства

Я реализую шаблон CQRS с источником событий, я использую NServiceBus, NEventStore и NES (соединяется между NSB и NEventStore).

Мое приложение будет регулярно проверять веб-службу на предмет загрузки и обработки любого файла. когда файл найден, на шину отправляется команда (DownloadFile), которую получает FileCommandHandler, который создает новый совокупный корень (File) и обрабатывает сообщение.

Теперь внутри (корень совокупного файла) я должен проверить, что содержимое файла не совпадает с каким-либо другим содержимым файла (поскольку веб-служба гарантирует, что только имя файла является уникальным, а содержимое может дублироваться с другим именем) , путем хеширования и сравнения со списком хешированного содержимого.

Вопрос в том, где мне сохранить список хеш-кодов? разрешено ли запрашивать модель чтения?

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));
        }
}

person Nour    schedule 22.04.2014    source источник
comment
Я верю в тот факт, что принцип заключается в разделении команд и запросов (например, могут быть разные источники данных). Это не означает, что команда не может использовать запросы. Я предпочитаю использовать запросы при выполнении команд.   -  person Mike    schedule 22.04.2014
comment
Что должно произойти с дублирующимися файлами содержимого (т.е. с командой DownloadFile, которая не может быть обработана)?   -  person Chris Bednarski    schedule 23.04.2014


Ответы (3)


Похоже, вы ищете дедупликацию.

Ваша командная сторона - это то место, где вы хотите, чтобы все было согласовано. Запросы всегда оставляют вас открытыми для условий гонки. Итак, вместо выполнения запроса я бы изменил логику и фактически записал хеш в таблицу базы данных (любой db с гарантиями ACID). Если эта запись прошла успешно, обработайте файл. Если запись хэша не удалась, пропустите обработку.

Нет смысла помещать эту логику в обработчик, потому что повторная попытка сообщения в случае сбоя (т.е. сохранение хеша несколько раз) не приведет к успеху. Вы также получите сообщения о повторяющихся файлах в ошибке q.

Хорошее место для логики дедупликации, вероятно, будет внутри вашего клиента веб-службы. Некоторая псевдологика

  1. Получить файл
  2. Открытая транзакция
  3. Вставить хеш в базу данных и перехватить ошибку (не сбой, только сбой при вставке)
  4. Bus: отправить сообщение в файл обработки, если количество записей, вставленных на шаге 3, не равно нулю.
  5. совершить транзакцию

Пример кода дедупликации в шлюзе NServiceBus здесь < / а>

Изменить:
Глядя на их код, я действительно думаю, что session.Get<DeduplicationMessage> не нужен. session.Save(gatewayMessage); должно быть достаточно, и это граница согласованности.

Выполнение запроса имеет смысл только в том случае, если вероятность сбоев высока, а это означает, что у вас много файлов дублированного содержимого. Если 99% + вставок успешны, дубликаты действительно могут рассматриваться как исключения.

person Chris Bednarski    schedule 23.04.2014
comment
Для меня имеет смысл передать логику дедупликации клиенту. Спасибо за предложение @chrisbednarski - person jokab; 15.03.2020

Это зависит от многих вещей ... одна из них - пропускная способность. Но поскольку вы все равно подходите к этой проблеме «методом вытягивания» (вы запрашиваете веб-сервис для опроса о работе (загрузка и анализ файла)), вы можете сделать весь этот процесс последовательным, не беспокоясь о коллизиях. Это может не дать желаемой скорости, с которой вы хотите выполнять «работу», но, что более важно ... вы измерили? Давайте на минутку обойдем это стороной и предположим, что серийный номер не сработает. О скольких файлах идет речь? Несколько 100, 1000, ... миллионов? В зависимости от этого хэши могут уместиться в памяти и могут быть перестроены, если / когда процесс остановится. Также может быть возможность разделить вашу проблему по оси времени или контекста. Каждый файл с начала рассвета или только сегодня, или, может быть, файлы за этот месяц? На самом деле, я думаю, вам следует глубже покопаться в своем проблемном пространстве. Кроме того, это выглядит как неудобная проблема для решения с использованием источников событий, но YMMV.

person Yves Reynhout    schedule 22.04.2014
comment
Извините за мой поздний ответ, веб-служба является внешней веб-службой, и я не могу ее контролировать. Проблема в том, что дублирования не должно быть, но из-за человеческих ошибок с другой стороны веб-службы (и веб-служба не выполняет проверку) может быть дублирование, но когда?, Как долго? И сколько ?, никто не может ответить на эти вопросы. Поэтому я должен сохранять все хэш-коды всех файлов с тех пор, и когда любой файл загружается, его следует проверять на дублирование. Кроме того, мы говорим о 5000 файлов в месяц, что, я думаю, немного. - person Nour; 26.04.2014
comment
И как именно я должен сохранять хеши и восстанавливать их, если процесс упадет? Могу ли я использовать любой метод сохранения (БД, системный файл и т. д.). Меня также интересует сама идея, а не только этот конкретный случай, другими словами, практично ли иметь такие бизнес-правила внутри модели предметной области? Спасибо. - person Nour; 26.04.2014

Когда у вас есть истинное ограничение уникальности в вашем домене, вы можете сделать тестер уникальности доменной службой, реализация которой является частью инфраструктуры - аналогично репозиторию, чей интерфейс является частью домена и чья реализация является частью инфраструктура. Затем для реализации вы можете использовать хэш в памяти или базу данных, которая обновляется / запрашивается по мере необходимости.

person Alexander Langer    schedule 23.04.2014
comment
Итак, в этом случае мне нужно создать класс, содержащий хэш-код для каждого файла, и попросить службу домена сохранять его каждый раз при загрузке файла? Плюс, AFAIK, служба домена выполняет операцию, не связанную с каким-либо агрегированным корнем! который в моем случае принадлежит агрегату файлов, правильно? - person Nour; 28.04.2014
comment
В аналогичной настройке я использую проекцию из потока событий, чтобы сохранить список хэшей файлов, как и с другими моделями чтения. Я не уверен, что вы имеете в виду под агрегатом root / File, я бы сохранил ограничение уникальности вне агрегата File, но я не знаю вашу модель. - person Alexander Langer; 29.04.2014