CQRS запускает обработчики в определенном порядке
У меня есть рабочий заказ на 2 обработчика Удаление и изменение порядка изображений, и я хотел бы получить несколько советов для лучшего решения.
В пользовательском интерфейсе некоторые изображения удаляются, пользователь нажимает на удаленную кнопку. Весь поток, команда delete до обработчика событий, который фактически удаляет физические файлы, запускается.
Затем пользователь сразу сортирует оставшиеся картинки. Новый поток от команды переупорядочения до обработчика переупорядочения событий для файловой системы запускается снова.
Уже существует проблема параллелизма. Переупорядочение не может быть правильно применено без удаления. На данный момент эта проблема решается с помощью своего рода блокировки. Временной файл создается и затем удаляется в конце процесса удаления. Пока этот файл существует, другой поток (переупорядочение или удаление в зависимости от действий пользователя) ожидает.
Это не идеальное решение, и хотелось бы изменить его. Потенциальное решение также должно быть довольно быстрым (конечно, текущее не быстрое), поскольку пользовательский интерфейс обновляется через вызов JSON в конце заказа.
В более поздней реализации мы думаем использовать очередь событий, но на данный момент мы застряли.
Любая идея будет оценена! Спасибо, Мосу!
Изменить: Другие возможные проблемы согласованности, которые мы решили, используя менеджер данных Javascript на стороне клиента. В основном быть оптимистом и обманом пользователя!:) Я начинаю верить, что это путь сюда. Но тогда как я узнаю, когда данные изменяются в файловой системе?
2 ответа
Вот одна мысль по этому поводу. Что именно вы меняете? Фотографий? На основании, скажем, даты. Почему есть команда для этого? Результат этой команды увидят все или только этот конкретный пользователь?
Я могу только догадываться, но похоже, что у вас есть вопрос презентации здесь. На стороне записи не нужно хранить картинки в каком-то порядке, это просто список имен и ссылок на хранилище файлов. Что вам нужно сделать, так это сохранить небольшое поле где-то в пользовательских настройках или настройках коллекции: Дата по возрастанию или Имя по убыванию. Таким образом, команда Reorder должна изменить только это маленькое поле. Затем, когда вы загружаете галерею, это поле должно быть прочитано первым, и на основании этого вы должны загрузить тот или иной вид. Так как в наше время магазин дешев, вы можете хранить различные отсортированные коллекции на стороне чтения для всех необходимых вам параметров.
Подводя итог, команда Delete изменяет коллекцию на стороне записи, но команда Reoder является просто настройкой пользователя или коллекции. Следовательно, здесь нет параллелизма.
Обновить
На основании ваших комментариев и разъяснений.
- Конечно, вы можете и, вероятно, должны ограничивать действия пользователя только одним за раз. Если время удаления и переупорядочения достаточно короткое. Это всегда вопрос типа пользовательского опыта, которого вы просили достичь. Возьмите обычный пример системы заказа. После размещения заказа пользователь может почти сразу увидеть его в пользовательском интерфейсе, и статус будет примерно таким же, как InProcess. Скорее всего, вы не позволите пользователю изменять порядок каким-либо образом, что означает, что вы не собираетесь показывать какие-либо пользовательские элементы управления, такие как кнопка "Отмена" (конечно, это только пример). Следовательно, вы можете использовать этот подход здесь.
- Если 2 пользователя могут изменять одну и ту же физическую коллекцию, у вас здесь нет выбора - вы работаете с общими данными и должна быть какая-то синхронизация. Например, если вы используете саги, может быть несколько саг: сага переупорядочивания коллекции и сага удаления - они могут сотрудничать. Сначала был запущен процесс удаления - агрегат сбора был помечен как выполняемое удаление, а затем сразу после запуска этой саги переупорядочения он попытается запустить процесс переупорядочения, но поскольку саги удаления не выполняется, он должен дождаться DeletedEvent и продолжить процесс после этого. То же самое, если операция переупорядочения началась первой - сага об удалении должна дождаться какого-то события и продолжить после того, как это событие наступило.
Обновить
Хорошо, если мы договорились не о самой файловой системе, а о совокупности, представляющей коллекцию изображений. Наиболее важные проблемы параллелизма могут быть решены с помощью оптимистического подхода параллелизма - в хранилище данных обычно используется уникальное ограничение, основанное на агрегированном идентификаторе и агрегатной версии.
Вот типичные шаги в обработчике команд:
Это общая последовательность шагов, которой следует обработчик команд:
- Проверяйте команду по существу.
- Загрузите агрегат.
- Проверьте команду на текущее состояние агрегата.
- Создайте новое событие, примените событие к агрегату в памяти.
- Попытка сохранить совокупность. Если во время этого шага возникнет конфликт параллелизма, либо откажитесь, либо повторите попытку с шага 2.
Вот ссылка, которая мне очень помогла некоторое время назад: http://www.cqrs.nu/
Макс предложения очень приветствуются и обычно они применяются.
Иногда сложно объяснить все детали реализации, но следует упомянуть одну деталь: способ хранения изображений означает, что при переупорядочении все пути к изображениям (и, следовательно, все ссылки) меняются.
У коллеги очень хорошая идея просто удалить эту часть. Это означает, что даже если порядок изменится, путь к изображению останется прежним. На стороне пользовательского интерфейса будет отображаться соответствие между индексом изображения в порядке отображения и его путем, и это означает, что больше нет необходимости изменять файловую систему, кроме случаев удаления.
Поскольку мы хотим быть максимально терпимыми к нашим пользователям, это лучшее решение для нас. Я думаю, что в целом это также хороший подход, когда возникает проблема параллелизма. Можно ли удалить параллелизм?