Мне нужен сканер, который находит документы из одной системы и сохраняет их для последующей синхронизации.
Искатель создается ServiceContainer, который разрешает все зависимости в конструкторе искателя.
Может быть, мое понимание или подход к моей архитектуре совершенно неверно, но я постараюсь описать свою структуру. Мои так называемые «сервисы» - это на самом деле просто классы, зарегистрированные как синглтоны в ServiceContainer. Это решение было принято для обеспечения того, чтобы «разделение интересов» не нарушалось.
Итак, сканер зависит от:
- SOAP-сервис для подключения к исходной системе
- a "NodeService", чтобы сообщить сканеру, возвращены ли данные (узел) из SOAP
это либо документ, либо каталог (возможно больше типов, поэтому здесь необходимо явное сравнение)
- a DocumentService, который выполняет работу с любым возвращенным документом.
DocumentService может сообщить сканеру, является ли документ новым или изменились ли какие-либо данные с момента последнего просмотра.
Для этого «DocumentService» снова зависит от двух сервисов
"MetaDataService" и "DocumentVersionService".
Метод обхода сканера выполняется рекурсивно, и на каждой итерации возвращаемый «узел» передается в «NodeService» и «DocumentService», которые были внедрены в конструктор сканеров.
// CRAWLER
function __construct(
SOAPService $css,
NodeService $ncs,
DocumentService $ds
) {
$this->css = $css;
$this->node = $ncs;
$this->document = $ds;
}
public function init($entryPoint)
{
$this->setEntryPoint($entryPoint);
$this->setDocType();
if ($this->isNotRunning())
{
$this->currentProcess = Crawl::create(['doc_type' => $this->docType]);
$this->processingTime = microtime(true);
Document::where('document_type', $this->docType)->update(['seen' => 0]);
}
else
{
throw new CrawlerAlreadyRunningException();
}
}
public function crawlDirectory($path = array())
{
if (empty($path)) {
$path[] = $this->docType;
}
$children = $this->css->getChildNodes($this->entryPoint);
foreach ($children as $child)
{
$this->node->set($child);
if($this->node->isDirectory())
{
$newPath = array_merge($path, array($child->Name));
$this->entryPoint = $child->ID;
$this->crawlDirectory($newPath);
}
else if ($this->node->isDocument())
{
$this->document->set($child);
$this->document->toIndex($this->docType, $path);
if ($this->document->isNew())
{
$this->document->toQueue('new');
}
if ($this->document->hasChangedMeta())
{
$this->document->toQueue('meta');
}
if ($this->document->hasNewVersion())
{
$this->document->toQueue('version');
}
}
}
}
DocumentService знает, где в «узле» хранится информация о версии и метаданных, и отправляет их в следующие внедренные службы, называемые «MetaDataService» и «DocumentVersionService».
См. «SoC» выше, «DocumentService» не должен знать, как на самом деле структурируются данные для версий или метаданных или как их извлекать (и если есть какие-либо другие правила, которые должны применяться). Он только выбрасывает кучу данных в другой сервис и получает результат. В соответствии с этим, может быть, даже сбор соответствующих данных является нарушением SOC вместо того, чтобы толкать весь «узел» в чересстрочные сервисы.
class DocumentService
{
private $documentVersion;
private $currentDocument;
private $documentMeta;
private $attributeMap;
private $versionAttributes;
private $possibleArrays;
private $sync;
function __construct(
DocumentVersionService $dvs,
MetaDataService $mds
)
{
$this->documentVersion = $dvs;
$this->documentMeta = $mds;
$this->attributeMap = config('soap.attributeMaps.documents.attributes');
$this->versionAttributes = config('soap.attributeMaps.documents.version');
$this->sync = false;
}
public function set($node)
{
$this->node = $node;
$this->documentVersion->set($node->VersionInfo->Versions);
$this->documentMeta->set($node->Metadata->AttributeGroups);
$this->initDocument();
}
Поскольку эти службы внедряются через конструктор, я не могу передать никакие дополнительные аргументы этим службам.
Для этого я добавил метод «set», чтобы привести соответствующий сервис в правильное состояние для операций текущей итерации.
Моя проблема в том, что если в этой цепочке рекурсивных итераций методы набора служб не будут вызваны (по любой причине), данные служб не будут обновлены, и они никогда не смогут вернуть какой-либо надежный результат.
Таким образом, каждый раз, когда служба используется (может позже кем-то, где-то еще), методы служб должны вызываться в точном правильном порядке.
Я думал о том, чтобы сделать все методы в этих службах закрытыми и вызывать их косвенно с помощью волшебного __call () - mehtod. Только метод set () будет общедоступным.
Затем в методе __call () я могу убедиться, что служба готова выполнить запрошенное действие.
Facepalm
Сейчас, когда я пишу это, я понимаю, что даже этот подход не может удовлетворить мои требования, чтобы гарантировать правильные текущие данные в каждой итерации. Я мог только проверить, присутствуют ли какие-либо данные в экземпляре службы. Другими словами, если это было инициализировано когда-либо прежде.
Заключение
Я думаю, что мне не хватает некоторых очень фундаментальных аспектов в этой архитектуре. Я был бы очень рад, если бы кто-нибудь мог дать мне совет, как это будет сделано "правильным образом".