Задача:
1. Есть сущность "Организация", которая включает в себя "Документы"
2. "Документ" - это файл + мета данные
3. В рамках "Организация" должен быть метод "Добавление документа". Метод добавлять только уникальные для данной организации файлы.
4. Файлы могут быть общего характера. Т.е. в целом документ может легко встречаться в рамках нескольких организаций.
5. Количество файлов на организацию не ограничено. Для конкретных цифр есть 2млн. Часть данных парсится автоматически, документы постоянно добавляются, число растет.
6. В рамках метода добавления документа есть еще действия связанные с самим документом (в примерах они через троеточие)
Реализация с нарушением слоев и всего что можно (просто для показа задачи, если непонятно выше):
Код: Выделить всё
class Company {
...
public function addDocument($document) {
...
if(!$this->documentStorage
->hash($document->md5File())
->companyId($this->getId())
->exists()) {
...
$this->documentStorage->add($document);
...
$this->persist();
}
...
}
}
Код: Выделить всё
class Company {
...
public function addDocument($document) {
...
if(!$this->documentsCollection->exists($document)) {
...
$this->documentSCollection->add($document);
...
}
...
}
}
...
$company->addDocument($document);
$em->persist($company);
...
Естественно всю коллекцию документов грузить в память нельзя. Там просто падает или memory limit или 30s timeout
Опробованные схемы:
1. Не делать метод добавления документы в рамках "Организация" а сделать его сразу в сервисе или в сервисе + репозиторий, например.
2. Сделать в репозитории отдельно методы add, findByHash, а также трейт,
где метод add будет реализован не выходя за рамки вызова методов, описанных в интерфейсе.
3. При выборке "Организация" из репозитория заменять "Коллекцию документов" на прокси и там обернуть исходный метод addDocument.
4. Отдельно делать часть помеченную тут троеточием в методе addDocument, отдельно делать сохранением в хранилище через репозиторий.
Проблемы схем:
1. Часть правил в сервисах, часть в моделях.
2. При использовании нужно помнить и про интерфейс и про трейт + 1 проблема из 1.
3. Получаем по факту почти тоже самое, что и без соблюдения слоев + требуем реализацию прокси
4. Тоже что и в 1. Можно не вызвать один из методов и либо не сохранить в хранилище, либо не выполнить нужные действия.
Хранилище:
Если вдруг понадобится, то хранилище - это mysql + файловые сервера
Т.е. exists - это упрощенно SELECT * FROM files WHERE content_md5='{$file_md5}' AND company_id={$company_id}
А add - это отправка в API удаленного сервера файла, ожидание успешного ответа, занесение в базу.
Упустил варианты или лучше вообще не так сделал?