Skip to content

Commit

Permalink
service history
Browse files Browse the repository at this point in the history
  • Loading branch information
pcrespov committed Jul 17, 2024
1 parent f7d44a4 commit cf753ab
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
from models_library.services import ServiceKey, ServiceVersion
from models_library.users import GroupID, UserID
from psycopg2.errors import ForeignKeyViolation
from pydantic import PositiveInt, ValidationError
from pydantic import PositiveInt, ValidationError, parse_obj_as
from simcore_postgres_database.utils_services import create_select_latest_services_query
from sqlalchemy import literal_column
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.sql import and_, or_
from sqlalchemy.sql.expression import tuple_

from ...models.services_db import (
ReleaseFromDB,
ServiceAccessRightsAtDB,
ServiceMetaDataAtDB,
ServiceWithHistoryFromDB,
Expand Down Expand Up @@ -386,6 +387,27 @@ async def list_latest_services(

return (total_count, items_page)

async def get_service_history(
self,
# access-rights
product_name: ProductName,
user_id: UserID,
# get args
key: ServiceKey,
) -> list[ReleaseFromDB] | None:

stmt_history = get_service_history_stmt(
product_name=product_name,
user_id=user_id,
access_rights=AccessRightsClauses.can_read,
service_key=key,
)
async with self.db_engine.begin() as conn:
result = await conn.execute(stmt_history)
row = result.one_or_none()

return parse_obj_as(list[ReleaseFromDB], row.history) if row else None

# Service Access Rights ----

async def get_service_access_rights(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from models_library.services_access import ServiceGroupAccessRights
from models_library.services_base import ServiceKeyVersion
from models_library.services_history import ServiceRelease
from models_library.services_metadata_editable import ServiceMetaDataEditable
from models_library.services_types import ServiceKey, ServiceVersion
from pydantic import BaseModel, Field
Expand Down Expand Up @@ -61,13 +60,6 @@ class ReleaseFromDB(BaseModel):
created: datetime
compatibility_policy: CompatiblePolicyDict | None

def to_api_model(self) -> ServiceRelease:
return ServiceRelease.construct(
version=self.version,
released=self.created,
retired=self.deprecated,
)


class ServiceWithHistoryFromDB(BaseModel):
key: ServiceKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,29 @@ async def _eval_custom_compatibility(
repo: ServicesRepository,
product_name: ProductName,
user_id: UserID,
compatibility_policy: CompatiblePolicyDict,
target_version: ServiceVersion,
service_versions: list[Version],
released_versions: list[Version],
compatibility_policy: CompatiblePolicyDict,
) -> Compatibility | None:
# TODO: guarantees on these data structures!
versions_specifier = SpecifierSet(compatibility_policy["versions_specifier"])

other_service_key = compatibility_policy.get("other_service_key")
other_service_versions = None

if other_service_key and (
other_service := await repo.get_service_with_history(
other_service_history := await repo.get_service_history(
product_name=product_name,
user_id=user_id,
key=ServiceKey(other_service_key),
version=None, # TODO: get_service_history(service_key)
)
):
other_service_versions = _to_versions(other_service.history)
other_service_versions = _to_versions(other_service_history)

versions_specifier = SpecifierSet(compatibility_policy["versions_specifier"])

if version := _get_latest_compatible_version(
target_version,
other_service_versions or service_versions,
other_service_versions or released_versions,
versions_specifier, # custom policy
):
if other_service_key:
Expand All @@ -98,17 +98,17 @@ async def _eval_custom_compatibility(
return None


async def eval_service_compatibility(
async def eval_service_compatibility_map(
repo: ServicesRepository,
product_name: ProductName,
user_id: UserID,
service_history: list[ReleaseFromDB],
service_release_history: list[ReleaseFromDB],
) -> dict[ServiceVersion, Compatibility]:

latest_first_versions = _to_versions(service_history)
released_versions = _to_versions(service_release_history)

result = {}
for release in service_history:
for release in service_release_history:
compatibility = None

# custom compatibility policy
Expand All @@ -118,13 +118,13 @@ async def eval_service_compatibility(
user_id=user_id,
repo=repo,
target_version=release.version,
released_versions=released_versions,
compatibility_policy=release.compatibility_policy,
service_versions=latest_first_versions,
)

elif version := _get_latest_compatible_version(
release.version,
latest_first_versions,
released_versions,
None, # default policy
):
compatibility = Compatibility(can_update_to=ServiceKey(f"{version}"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from models_library.products import ProductName
from models_library.rest_pagination import PageLimitInt
from models_library.services_enums import ServiceType
from models_library.services_history import Compatibility, ServiceRelease
from models_library.services_metadata_published import ServiceMetaDataPublished
from models_library.services_types import ServiceKey, ServiceVersion
from models_library.users import UserID
Expand All @@ -25,6 +26,7 @@
from simcore_service_catalog.services.director import DirectorApi

from ..db.repositories.services import ServicesRepository
from .compatibility import eval_service_compatibility_map
from .function_services import is_function_service

_logger = logging.getLogger(__name__)
Expand All @@ -42,10 +44,13 @@ def _db_to_api_model(
service_db: ServiceWithHistoryFromDB,
access_rights_db: list[ServiceAccessRightsAtDB],
service_manifest: ServiceMetaDataPublished,
compatibility_map: dict[ServiceKey, Compatibility] | None = None,
) -> ServiceGetV2:
assert (
compatibility_map = compatibility_map or {}
assert ( # nosec
_deduce_service_type_from(service_db.key) == service_manifest.service_type
) # nosec
)

return ServiceGetV2(
key=service_db.key,
version=service_db.version,
Expand All @@ -70,7 +75,15 @@ def _db_to_api_model(
},
classifiers=service_db.classifiers,
quality=service_db.quality,
history=[h.to_api_model() for h in service_db.history],
history=[
ServiceRelease.construct(
version=h.version,
released=h.created,
retired=h.deprecated,
compatibility=compatibility_map.get(h.version),
)
for h in service_db.history
],
)


Expand Down Expand Up @@ -161,15 +174,20 @@ async def get_service(
product_name=product_name,
)

service.history
compatibility_map = await eval_service_compatibility_map(
repo,
product_name=product_name,
user_id=user_id,
service_release_history=service.history,
)

service_manifest = await manifest.get_service(
key=service_key,
version=service_version,
director_client=director_api,
)

return _db_to_api_model(service, access_rights, service_manifest)
return _db_to_api_model(service, access_rights, service_manifest, compatibility_map)


async def update_service(
Expand Down

0 comments on commit cf753ab

Please sign in to comment.