Skip to content

Commit

Permalink
feat: add dao layer
Browse files Browse the repository at this point in the history
  • Loading branch information
TheoPascoli committed Dec 19, 2024
1 parent d8df7e9 commit 04727b3
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 104 deletions.
106 changes: 9 additions & 97 deletions antarest/study/business/link_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,123 +11,35 @@
# This file is part of the Antares project.

import typing as t
from typing import Any

from antares.study.version import StudyVersion

from antarest.core.exceptions import LinkNotFound
from antarest.core.model import JSON
from antarest.study.business.model.link_model import LinkBaseDTO, LinkDTO, LinkInternal
from antarest.study.business.utils import execute_or_add_commands
from antarest.study.business.model.link_model import LinkBaseDTO, LinkDTO
from antarest.study.dao.dao_factory import DAOFactory
from antarest.study.model import RawStudy, Study
from antarest.study.storage.rawstudy.model.filesystem.factory import FileStudy
from antarest.study.storage.storage_service import StudyStorageService
from antarest.study.storage.variantstudy.model.command.create_link import CreateLink
from antarest.study.storage.variantstudy.model.command.remove_link import RemoveLink
from antarest.study.storage.variantstudy.model.command.update_link import UpdateLink


class LinkManager:
def __init__(self, storage_service: StudyStorageService) -> None:
self.storage_service = storage_service
def __init__(self, dao_factory: DAOFactory) -> None:
self.composite_dao = dao_factory.create_link_dao()

def get_all_links(self, study: Study) -> t.List[LinkDTO]:
file_study = self.storage_service.get_storage(study).get_raw(study)
result: t.List[LinkDTO] = []

for area_id, area in file_study.config.areas.items():
links_config = file_study.tree.get(["input", "links", area_id, "properties"])

for link in area.links:
link_tree_config: t.Dict[str, t.Any] = links_config[link]
link_tree_config.update({"area1": area_id, "area2": link})

link_internal = LinkInternal.model_validate(link_tree_config)

result.append(link_internal.to_dto())

return result

def get_link(self, study: RawStudy, link: LinkInternal) -> LinkInternal:
file_study = self.storage_service.get_storage(study).get_raw(study)

link_properties = self._get_link_if_exists(file_study, link)

link_properties.update({"area1": link.area1, "area2": link.area2})

updated_link = LinkInternal.model_validate(link_properties)

return updated_link
return self.composite_dao.get_links(study)

def create_link(self, study: Study, link_creation_dto: LinkDTO) -> LinkDTO:
link = link_creation_dto.to_internal(StudyVersion.parse(study.version))

storage_service = self.storage_service.get_storage(study)
file_study = storage_service.get_raw(study)

command = CreateLink(
area1=link.area1,
area2=link.area2,
parameters=link.model_dump(exclude_none=True),
command_context=self.storage_service.variant_study_service.command_factory.command_context,
study_version=file_study.config.version,
)

execute_or_add_commands(study, file_study, [command], self.storage_service)

return link_creation_dto
return self.composite_dao.create_link(study, link_creation_dto)

def update_link(self, study: RawStudy, area_from: str, area_to: str, link_update_dto: LinkBaseDTO) -> LinkDTO:
link_dto = LinkDTO(area1=area_from, area2=area_to, **link_update_dto.model_dump(exclude_unset=True))

link = link_dto.to_internal(StudyVersion.parse(study.version))
file_study = self.storage_service.get_storage(study).get_raw(study)

self._get_link_if_exists(file_study, link)

command = UpdateLink(
area1=link.area1,
area2=link.area2,
parameters=link.model_dump(
include=link_update_dto.model_fields_set, exclude={"area1", "area2"}, exclude_none=True
),
command_context=self.storage_service.variant_study_service.command_factory.command_context,
study_version=file_study.config.version,
)

execute_or_add_commands(study, file_study, [command], self.storage_service)

updated_link = self.get_link(study, link)

return updated_link.to_dto()
return self.composite_dao.update_link(study, area_from, area_to, link_update_dto)

def update_links(
self,
study: RawStudy,
update_links_by_ids: t.Mapping[t.Tuple[str, str], LinkBaseDTO],
) -> t.Mapping[t.Tuple[str, str], LinkBaseDTO]:
new_links_by_ids = {}
for (area1, area2), update_link_dto in update_links_by_ids.items():
updated_link = self.update_link(study, area1, area2, update_link_dto)
new_links_by_ids[(area1, area2)] = updated_link

return new_links_by_ids
return self.composite_dao.update_links(study, update_links_by_ids)

def delete_link(self, study: RawStudy, area1_id: str, area2_id: str) -> None:
file_study = self.storage_service.get_storage(study).get_raw(study)
command = RemoveLink(
area1=area1_id,
area2=area2_id,
command_context=self.storage_service.variant_study_service.command_factory.command_context,
study_version=file_study.config.version,
)
execute_or_add_commands(study, file_study, [command], self.storage_service)

def _get_link_if_exists(self, file_study: FileStudy, link: LinkInternal) -> dict[str, Any]:
try:
return file_study.tree.get(["input", "links", link.area1, "properties", link.area2])
except KeyError:
raise LinkNotFound(f"The link {link.area1} -> {link.area2} is not present in the study")
self.composite_dao.delete_link(study, area1_id, area2_id)

@staticmethod
def get_table_schema() -> JSON:
Expand Down
Empty file added antarest/study/dao/__init__.py
Empty file.
24 changes: 24 additions & 0 deletions antarest/study/dao/dao_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2024, RTE (https://www.rte-france.com)
#
# See AUTHORS.txt
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

from antarest.core.interfaces.cache import ICache
from antarest.study.dao.link.composite_link_dao import CompositeLinkDAO
from antarest.study.storage.storage_service import StudyStorageService


class DAOFactory:
def __init__(self, storage_service: StudyStorageService, cache_service: ICache):
self.storage_service = storage_service
self.cache_service = cache_service

def create_link_dao(self) -> CompositeLinkDAO:
return CompositeLinkDAO(self.storage_service, self.cache_service)
Empty file.
58 changes: 58 additions & 0 deletions antarest/study/dao/link/cache_link_dao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright (c) 2024, RTE (https://www.rte-france.com)
#
# See AUTHORS.txt
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

import typing as t

from antarest.core.interfaces.cache import ICache
from antarest.study.business.model.link_model import LinkDTO


class CacheLinkDao:
def __init__(self, cache: ICache):
self.cache = cache

def get_links(self, study_id: str) -> t.Optional[t.List[LinkDTO]]:
cache_key = self._get_cache_key(study_id)
cached_data = self.cache.get(cache_key)
if cached_data is None:
return None
return [LinkDTO.model_validate(link) for link in cached_data["links"]]

def put(self, study_id: str, link: LinkDTO, timeout: int = 600000) -> None:
try:
cache_key = self._get_cache_key(study_id)
cached_links = self.cache.get(cache_key)

if cached_links is None:
cached_links = {"links": []}

existing_links = cached_links.get("links", [])

if isinstance(existing_links, dict):
existing_links = list(existing_links.values())
elif not isinstance(existing_links, list):
existing_links = []

link_data = link.model_dump()
existing_links.append(link_data)

cached_links["links"] = existing_links
self.cache.put(cache_key, cached_links, timeout)
except:
raise

def invalidate(self, study_id: str) -> None:
cache_key = self._get_cache_key(study_id)
self.cache.invalidate(cache_key)

def _get_cache_key(self, study_id: str) -> str:
return f"links:{study_id}"
57 changes: 57 additions & 0 deletions antarest/study/dao/link/composite_link_dao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright (c) 2024, RTE (https://www.rte-france.com)
#
# See AUTHORS.txt
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0
#
# This file is part of the Antares project.

import typing as t

from antarest.core.interfaces.cache import ICache
from antarest.study.business.model.link_model import LinkBaseDTO, LinkDTO
from antarest.study.dao.link.cache_link_dao import CacheLinkDao
from antarest.study.dao.link.storage_link_dao import StorageLinkDao
from antarest.study.model import Study
from antarest.study.storage.storage_service import StudyStorageService


class CompositeLinkDAO:
def __init__(self, storage_service: StudyStorageService, cache_service: ICache):
self.storage_dao = StorageLinkDao(storage_service)
self.cache_dao = CacheLinkDao(cache_service)

def create_link(self, study: Study, link: LinkDTO) -> LinkDTO:
self.cache_dao.invalidate(study.id)
return self.storage_dao.create_link(study, link)

def get_links(self, study: Study) -> t.List[LinkDTO]:
links = self.cache_dao.get_links(study.id)
if links is not None:
return links

links = self.storage_dao.get_links(study)

for link in links:
self.cache_dao.put(study.id, link)
return links

def update_link(self, study: Study, area_from: str, area_to: str, link_update_dto: LinkBaseDTO) -> LinkDTO:
self.cache_dao.invalidate(study.id)
return self.storage_dao.update_link(study, area_from, area_to, link_update_dto)

def update_links(
self,
study: Study,
update_links_by_ids: t.Mapping[t.Tuple[str, str], LinkBaseDTO],
) -> t.Mapping[t.Tuple[str, str], LinkBaseDTO]:
self.cache_dao.invalidate(study.id)
return self.storage_dao.update_links(study, update_links_by_ids)

def delete_link(self, study: Study, area_from: str, area_to: str) -> None:
self.cache_dao.invalidate(study.id)
self.storage_dao.delete_link(study, area_from, area_to)
Loading

0 comments on commit 04727b3

Please sign in to comment.