Skip to content

Commit

Permalink
feat(restapi): update entrypoint and plugin services for changes to db
Browse files Browse the repository at this point in the history
This commit makes the necessary changes to the service layer to handle the change from the three-way
entry_point_plugin_files linking table to the two two-way linking tables (entry_point_plugins and
plugin_plugin_files).

As part of this change, a new snapshot for Plugin resources is created when an associated PluginFile
is added, deleted, or modified.

Co-authored-by: Keith Manville <[email protected]>
  • Loading branch information
henrychoy and keithmanville committed Feb 14, 2025
1 parent 4e25ed8 commit 755cff1
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 191 deletions.
6 changes: 3 additions & 3 deletions src/dioptra/restapi/db/models/entry_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

if TYPE_CHECKING:
from .jobs import EntryPointJob
from .plugins import Plugin, PluginFile
from .plugins import Plugin
from .resources import Resource


Expand Down Expand Up @@ -55,7 +55,7 @@ class EntryPoint(ResourceSnapshot):
entry_point_jobs: Mapped[list["EntryPointJob"]] = relationship(
init=False, viewonly=True
)
entry_point_plugin_files: Mapped[list["EntryPointPluginFile"]] = relationship(
entry_point_plugins: Mapped[list["EntryPointPlugin"]] = relationship(
init=False, back_populates="entry_point"
)

Expand Down Expand Up @@ -159,6 +159,6 @@ class EntryPointPlugin(db.Model): # type: ignore[name-defined]

# Relationships
entry_point: Mapped["EntryPoint"] = relationship(
back_populates="entry_point_plugin_files", lazy="joined"
back_populates="entry_point_plugins", lazy="joined"
)
plugin: Mapped["Plugin"] = relationship(lazy="joined")
14 changes: 14 additions & 0 deletions src/dioptra/restapi/db/models/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ class Plugin(ResourceSnapshot):
resource_id: Mapped[bigint] = mapped_column(init=False, nullable=False, index=True)
name: Mapped[text_] = mapped_column(nullable=False, index=True)

# Relationships
plugin_plugin_files: Mapped[list["PluginPluginFile"]] = relationship(
init=False, back_populates="plugin_file"
)
plugin_files: Mapped[list["PluginFile"]] = relationship(
"PluginFile",
secondary="plugin_plugin_files",
primaryjoin="Plugin.resource_snapshot_id == "
"PluginPluginFile.plugin_resource_snapshot_id",
secondaryjoin="PluginPluginFile.plugin_file_resource_snapshot_id == "
"PluginFile.resource_snapshot_id",
init=False,
)

# Additional settings
__table_args__ = ( # type: ignore[assignment]
Index(None, "resource_snapshot_id", "resource_id", unique=True),
Expand Down
11 changes: 11 additions & 0 deletions src/dioptra/restapi/v1/entrypoints/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"""The schemas for serializing/deserializing Entrypoint resources."""
from marshmallow import Schema, fields, validate

from dioptra.restapi.v1.plugins.schema import PluginTaskSchema
from dioptra.restapi.v1.queues.schema import QueueRefSchema
from dioptra.restapi.v1.schemas import (
BasePageSchema,
Expand Down Expand Up @@ -49,6 +50,12 @@ class EntrypointPluginFileSchema(Schema):
metadata=dict(description="URL for accessing the full PluginFile snapshot."),
relative=True,
)
tasks = fields.Nested(
PluginTaskSchema,
attribute="tasks",
metadata=dict(description="Tasks associated with the PluginFile resource."),
many=True,
)


class EntrypointPluginSchema(Schema):
Expand All @@ -66,6 +73,10 @@ class EntrypointPluginSchema(Schema):
attribute="snapshot_id",
metadata=dict(description="Snapshot ID for the Plugin resource."),
)
latestSnapshot = fields.Boolean(
attribute="latest_snapshot",
metadata=dict(description="Whether or not the Plugin is the latest version."),
)
url = fields.Url(
attribute="url",
metadata=dict(description="URL for accessing the full Plugin snapshot."),
Expand Down
96 changes: 43 additions & 53 deletions src/dioptra/restapi/v1/entrypoints/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,15 @@ def create(
creator=current_user,
)

entry_point_plugin_files = [
models.EntryPointPluginFile(
entry_point_plugins = [
models.EntryPointPlugin(
entry_point=new_entrypoint,
plugin=plugin["plugin"],
plugin_file=plugin_file,
)
for plugin in plugins
for plugin_file in plugin["plugin_files"]
]
new_entrypoint.entry_point_plugin_files = entry_point_plugin_files

new_entrypoint.entry_point_plugins = entry_point_plugins

plugin_resources = [plugin["plugin"].resource for plugin in plugins]
queue_resources = [queue.resource for queue in queues]
Expand Down Expand Up @@ -467,19 +466,18 @@ def modify(
resource=entrypoint.resource,
creator=current_user,
)
new_entrypoint.entry_point_plugin_files = [
models.EntryPointPluginFile(
new_entrypoint.entry_point_plugins = [
models.EntryPointPlugin(
entry_point=new_entrypoint,
plugin=entry_point_plugin_file.plugin,
plugin_file=entry_point_plugin_file.plugin_file,
plugin=entry_point_plugin.plugin,
)
for entry_point_plugin_file in entrypoint.entry_point_plugin_files
for entry_point_plugin in entrypoint.entry_point_plugins
]

plugin_resources = list(
{
plugin.plugin.resource_id: plugin.plugin.resource
for plugin in new_entrypoint.entry_point_plugin_files
for plugin in new_entrypoint.entry_point_plugins
}.values()
)
queue_resources = [queue.resource for queue in queues]
Expand Down Expand Up @@ -630,34 +628,31 @@ def append(
creator=current_user,
)

new_entry_point_plugin_files = [
models.EntryPointPluginFile(
new_entry_point_plugins = [
models.EntryPointPlugin(
entry_point=new_entrypoint,
plugin=plugin["plugin"],
plugin_file=plugin_file,
)
for plugin in self._plugin_ids_service.get(
plugin_ids, error_if_not_found=True
)
for plugin_file in plugin["plugin_files"]
]
existing_entry_point_plugin_files = [
models.EntryPointPluginFile(
existing_entry_point_plugins = [
models.EntryPointPlugin(
entry_point=new_entrypoint,
plugin=entry_point_plugin_file.plugin,
plugin_file=entry_point_plugin_file.plugin_file,
plugin=entry_point_plugin.plugin,
)
for entry_point_plugin_file in entrypoint.entry_point_plugin_files
if entry_point_plugin_file.plugin.resource_id not in set(plugin_ids)
for entry_point_plugin in entrypoint.entry_point_plugins
if entry_point_plugin.plugin.resource_id not in set(plugin_ids)
]
new_entrypoint.entry_point_plugin_files = (
existing_entry_point_plugin_files + new_entry_point_plugin_files
new_entrypoint.entry_point_plugins = (
existing_entry_point_plugins + new_entry_point_plugins
)

plugin_resources = list(
{
plugin.plugin.resource_id: plugin.plugin.resource
for plugin in new_entrypoint.entry_point_plugin_files
for plugin in new_entrypoint.entry_point_plugins
}.values()
)
queue_resources = [
Expand Down Expand Up @@ -727,23 +722,20 @@ def get(
),
)["entry_point"]

plugins = {
entry_point_plugin_file.plugin.resource_id: entry_point_plugin_file.plugin
for entry_point_plugin_file in entrypoint.entry_point_plugin_files
}
if plugin_id not in plugins:
plugin = [
entry_point_plugin.plugin
for entry_point_plugin in entrypoint.entry_point_plugins
if plugin_id == entry_point_plugin.plugin.resource_id
]

if not plugin:
raise EntityDoesNotExistError(
PLUGIN_RESOURCE_TYPE, entrypoint_id=entrypoint_id, plugin_id=plugin_id
)

plugin = utils.PluginWithFilesDict(
plugin=plugins[plugin_id], plugin_files=[], has_draft=None
return utils.PluginWithFilesDict(
plugin=plugin[0], plugin_files=plugin[0].plugin_files, has_draft=None
)
for entry_point_plugin_file in entrypoint.entry_point_plugin_files:
if entry_point_plugin_file.plugin.resource_id == plugin_id:
plugin["plugin_files"].append(entry_point_plugin_file.plugin_file)

return plugin

def delete(
self,
Expand Down Expand Up @@ -775,7 +767,7 @@ def delete(
)["entry_point"]

plugin_ids = set(
plugin.plugin.resource_id for plugin in entrypoint.entry_point_plugin_files
plugin.plugin.resource_id for plugin in entrypoint.entry_point_plugins
)
if plugin_id not in plugin_ids:
raise EntityDoesNotExistError(
Expand All @@ -800,14 +792,13 @@ def delete(
resource=entrypoint.resource,
creator=current_user,
)
new_entrypoint.entry_point_plugin_files = [
models.EntryPointPluginFile(
new_entrypoint.entry_point_plugins = [
models.EntryPointPlugin(
entry_point=new_entrypoint,
plugin=entry_point_plugin_file.plugin,
plugin_file=entry_point_plugin_file.plugin_file,
plugin=entry_point_plugin.plugin,
)
for entry_point_plugin_file in entrypoint.entry_point_plugin_files
if entry_point_plugin_file.plugin.resource_id != plugin_id
for entry_point_plugin in entrypoint.entry_point_plugins
if entry_point_plugin.plugin.resource_id != plugin_id
]

# remove the plugin resource dependency association
Expand Down Expand Up @@ -1193,14 +1184,13 @@ def get(
def _get_entrypoint_plugin_snapshots(
entrypoint: models.EntryPoint,
) -> list[utils.PluginWithFilesDict]:
plugins_dict = {
entry_point_plugin_file.plugin.resource_id: utils.PluginWithFilesDict(
plugin=entry_point_plugin_file.plugin, plugin_files=[], has_draft=False
plugins = [
utils.PluginWithFilesDict(
plugin=entry_point_plugin.plugin,
plugin_files=entry_point_plugin.plugin.plugin_files,
has_draft=False,
)
for entry_point_plugin_file in entrypoint.entry_point_plugin_files
}
for entry_point_plugin_file in entrypoint.entry_point_plugin_files:
resource_id = entry_point_plugin_file.plugin.resource_id
plugin_file = entry_point_plugin_file.plugin_file
plugins_dict[resource_id]["plugin_files"].append(plugin_file)
return list(plugins_dict.values())
for entry_point_plugin in entrypoint.entry_point_plugins
]

return plugins
40 changes: 23 additions & 17 deletions src/dioptra/restapi/v1/plugins/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,6 @@ class PluginSnapshotRefSchema(PluginSnapshotRefBaseSchema): # type: ignore
)


PluginFileRefBaseSchema = generate_base_resource_ref_schema("PluginFile")


class PluginFileRefSchema(PluginFileRefBaseSchema): # type: ignore
"""The reference schema for the data stored in a PluginFile."""

pluginId = fields.Int(
attribute="plugin_id",
data_key="plugin",
metadata=dict(description="ID for the Plugin resource this file belongs to."),
)
filename = fields.String(
attribute="filename",
metadata=dict(description="Filename of the PluginFile resource."),
)


class PluginTaskParameterSchema(Schema):
"""The schema for the data stored in a PluginTaskParameter"""

Expand Down Expand Up @@ -168,6 +151,29 @@ class PluginTaskSchema(Schema):
)


PluginFileRefBaseSchema = generate_base_resource_ref_schema("PluginFile")


class PluginFileRefSchema(PluginFileRefBaseSchema): # type: ignore
"""The reference schema for the data stored in a PluginFile."""

pluginId = fields.Int(
attribute="plugin_id",
data_key="plugin",
metadata=dict(description="ID for the Plugin resource this file belongs to."),
)
filename = fields.String(
attribute="filename",
metadata=dict(description="Filename of the PluginFile resource."),
)
tasks = fields.Nested(
PluginTaskSchema,
attribute="tasks",
metadata=dict(description="Tasks associated with the PluginFile resource."),
many=True,
)


PluginBaseSchema = generate_base_resource_schema("Plugin", snapshot=True)


Expand Down
Loading

0 comments on commit 755cff1

Please sign in to comment.