def test_try_register_documents_call_article_factory_once(self): article_factory_mock = MagicMock() self.mk_hooks.KERNEL_HOOK_BASE.run.side_effect = [ MagicMock(url="http://kernel_url/") ] try_register_documents( documents=self.documents, get_relation_data=lambda _: ( "issue-1", { "id": "67TH7T7CyPPmgtVrGXhWXVs", "order": "01" }, ), fetch_document_front=lambda _: self.document_front, article_factory=article_factory_mock, ) article_factory_mock.assert_called_once_with( "67TH7T7CyPPmgtVrGXhWXVs", self.document_front, "issue-1", "01", "http://kernel_url/documents/67TH7T7CyPPmgtVrGXhWXVs", )
def test_try_register_documents_call_fetch_document_front_once(self): fetch_document_front_mock = MagicMock() article_factory_mock = MagicMock() try_register_documents( documents=self.documents, get_relation_data=lambda _: ("", {}), fetch_document_front=fetch_document_front_mock, article_factory=article_factory_mock, ) fetch_document_front_mock.assert_called_once_with( "67TH7T7CyPPmgtVrGXhWXVs")
def test_try_register_documents_call_save_methods_from_article_instance( self): article_factory_mock = MagicMock() article_instance_mock = MagicMock() article_factory_mock.return_value = article_instance_mock try_register_documents( documents=self.documents, get_relation_data=lambda document_id: ( "issue-1", { "id": "67TH7T7CyPPmgtVrGXhWXVs", "order": "01" }, ), fetch_document_front=lambda document_id: self.document_front, article_factory=article_factory_mock, ) article_instance_mock.save.assert_called_once()
def register_documents(**kwargs): """Registra documentos na base de dados do OPAC a partir de informações vindas da API do `Kernel`. Armazena como órfãos nas variáveis do Airflow os documentos que não puderam ser salvos.""" mongo_connect() tasks = kwargs["ti"].xcom_pull(key="tasks", task_ids="read_changes_task") def _get_relation_data(document_id: str) -> Tuple[str, Dict]: """Recupera informações sobre o relacionamento entre o DocumentsBundle e o Document. Retorna uma tupla contendo o identificador da issue onde o documento está relacionado e o item do relacionamento. >> _get_relation_data("67TH7T7CyPPmgtVrGXhWXVs") ('0034-8910-2019-v53', {'id': '67TH7T7CyPPmgtVrGXhWXVs', 'order': '01'}) :param document_id: Identificador único de um documento """ for issue_id, items in known_documents.items(): for item in items: if document_id == item["id"]: return (issue_id, item) return (None, {}) def _get_known_documents(**kwargs) -> Dict[str, List[str]]: """Recupera a lista de todos os documentos que estão relacionados com um `DocumentsBundle`. Levando em consideração que a DAG que detecta mudanças na API do Kernel roda de forma assíncrona em relação a DAG de espelhamento/sincronização. É possível que algumas situações especiais ocorram onde em uma rodada **anterior** o **evento de registro** de um `Document` foi capturado mas a atualização de seu `DocumentsBundle` não ocorreu (elas ocorrem em transações distintas e possuem timestamps também distintos). O documento será registrado como **órfão** e sua `task` não será processada na próxima execução. Na próxima execução a task `register_issue_task` entenderá que o `bundle` é órfão e não conhecerá os seus documentos (known_documents) e consequentemente o documento continuará órfão. Uma solução para este problema é atualizar a lista de documentos conhecidos a partir da lista de eventos de `get` de `bundles`. """ known_documents = kwargs["ti"].xcom_pull( key="i_documents", task_ids="register_issues_task") issues_recently_updated = [ get_id(task["id"]) for task in filter_changes(tasks, "bundles", "get") if known_documents.get(get_id(task["id"])) is None ] for issue_id in issues_recently_updated: known_documents.setdefault(issue_id, []) known_documents[issue_id] = list( itertools.chain(known_documents[issue_id], fetch_bundles(issue_id).get("items", []))) return known_documents known_documents = _get_known_documents(**kwargs) # TODO: Em caso de um update no document é preciso atualizar o registro # Precisamos de uma nova task? documents_to_get = itertools.chain( Variable.get("orphan_documents", default_var=[], deserialize_json=True), (get_id(task["id"]) for task in filter_changes(tasks, "documents", "get")), ) orphans = try_register_documents(documents_to_get, _get_relation_data, fetch_documents_front, ArticleFactory) Variable.set("orphan_documents", orphans, serialize_json=True)