Домен Управляемый Дизайн и пакетная обработка

Имеет следующую структуру:

  1. Уровень презентации:

    Веб-интерфейс, REST API и командная строка — все они вызывают только OrderService.

  2. Уровень приложений:

    class OrderService
    {
    private $em;
    private $repository;
    private $calculator;
    
    public function __construct(
    \Doctrine\ORM\EntityManagerInterface $em;
    ClientRepositoryInterface $repository,
    cumulativeDiscountCalculator $calculator
    } {
    $this->em = $em;
    $this->repository = $repository;
    $this->calculator = $calculator;
    }
    
    public function calculateCumulativeDiscount($id)
    {
    $this->em->beginTransaction();
    try {
    $client = $this->repository->findClient();
    $this->calculator->calculate($client);
    
    $this->em->flush();
    $this->em->commit();
    } catch (\Exception $e) {
    $this->em->rollback();
    
    throw $e;
    }
    }
    }
    
  3. Модельный слой:

    interface ClientInterface
    {
    public function setDiscount($discount);
    }
    interface ClientRepositoryInterface
    {
    public function findClient($id);
    public function findClientsByDataRange($from, $to);
    }
    class cumulativeDiscountCalculator
    {
    public function calculate(ClientInterface $client)
    {
    $client->setDiscount(mt_rand(1, 50));
    }
    }
    
  4. Уровень инфраструктуры:

    PHP Doctrine 2 — реализовать ClientRepositoryInterface.

Моя задача — выполнить расчет скидок для коллекции клиентов.
(метод ClientRepositoryInterface :: findClientsByDataRange возвращает коллекцию для обработки)

Проблема в том, что мне нужно обработать до 100 000 записей. Я знаю, как это сделать технически, но как это сделать с точки зрения DDD? Возникают следующие вопросы:

  • Какой слой использовать для пакетной обработки?
  • Как собрать результаты действий: ошибки, подсчитать успешных клиентов и т. Д.?
  • Где установить границы транзакции (каждый N клиентов — совершить и начать новую транзакцию)?
  • У меня около 10-20 пакетных операций, может иметь смысл какую-то структуру разрабатывать?

2

Решение

По моему мнению, вы должны рассматривать пакетную операцию как часть вашего домена, а не просто как «тривиальную» операцию в стороне. Запишите требования, и вы увидите, что для этого также требуется некоторое моделирование предметной области. Например. вам нужно хранить базовые данные о каждом пакетном запуске (тип, когда, сколько записей обработано, результаты, связанные ошибки и т. д.), а затем вам нужно иметь возможность просматривать и планировать их (когда, какой пакетный запуск, повторный запуск и т. д.) ). Возможно, вы захотите иметь какой-нибудь инструмент для мониторинга их с точки зрения времени или ресурсов (сколько времени занимает каждый запуск, сколько памяти занимает и т. Д.).

Из того, что вы упомянули выше, я могу представить себе такие классы, как:

  • BatchRunner
  • BatchInterface
  • ClientDiscountBatch {$ scheduleDay, $ scheduleTime}
  • BatchResultEntity {$ itemProcessed, $ itemErrors, $ maxMemory,
    $ duration}
  • BatchResultRepository

Тогда каждая из ваших пакетных операций будет реализовывать BatchInterface и будет управляться BatchRunner, а результаты будут сохраняться BatchResultRepository и т. Д.

Все операции будут использовать другие классы домена, как вы упомянули выше, например. CumulativeDiscountCalculator.

В терминах границ транзакций вы продолжаете использовать существующие границы — например. Совокупный корень. После каждой итерации вы увеличиваете количество результатов или регистрируете ошибку.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]