Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update UI to indicate when a plugin attached to an entrypoint is out-of-date and provide a mechanism to sync to the latest version of plugins. #678

Open
wants to merge 22 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f2003aa
feat: split entry_point_plugin_files table into two linking tables
jkglasbrenner Nov 8, 2024
60b5e74
fix: update service for entrypoints
Nov 19, 2024
f2ac826
fix: updated plugin service
Nov 24, 2024
45f1c91
feat: add sync to latest plugin btn
Nov 26, 2024
ecfe6a7
fix: simplify gets in plugins service
Nov 26, 2024
4a6e257
fix: update job tests to use id not snapshot
keithmanville Dec 23, 2024
b1bfd05
refactor: use Plugin -> PluginFiles relationship
keithmanville Dec 12, 2024
14ecd01
fix: remove unneeded query
keithmanville Dec 13, 2024
5dbf1a3
chore: flake8/mypy
keithmanville Dec 13, 2024
dbb4f2d
fix: correct confusion over id/snapshotId in job response
keithmanville Dec 13, 2024
7c9cef9
refactor: delete plugin files when parent plugin is deleted
keithmanville Dec 13, 2024
d9764ec
fix: minor schema fix
keithmanville Dec 13, 2024
ceccccc
fix: id not needed in schema
keithmanville Dec 13, 2024
b8ed8fc
feat: add id into snapshot ref schemas
keithmanville Dec 13, 2024
a12c51b
chore: flake8/mypy
keithmanville Dec 13, 2024
3bcddad
fix: corrected tests where snapshotId was used instead of id
keithmanville Dec 24, 2024
5da4f85
refactor: update implementation to avoid creation of unecessary dict
keithmanville Jan 30, 2025
912a1fc
refactor: remove unecessary list comprehension
keithmanville Jan 30, 2025
76142b1
refactor: make plugin snapshot and plugin file association clearer
keithmanville Jan 30, 2025
a4bcffd
refactor: rename variables for clarity
keithmanville Jan 30, 2025
a5b91b0
refactor: simplify query
keithmanville Jan 30, 2025
99396db
test: fix identifier checks
keithmanville Jan 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
"""Separate entry_point_plugin_files table into 2 many-to-many tables

Revision ID: f1d231f7ef15
Revises: 6a75ede23821
Create Date: 2024-11-08 09:55:20.650243

"""

from typing import Annotated

import sqlalchemy as sa
from alembic import op
from sqlalchemy.orm import (
DeclarativeBase,
Mapped,
MappedAsDataclass,
mapped_column,
sessionmaker,
)

# revision identifiers, used by Alembic.
revision = "f1d231f7ef15"
down_revision = "6a75ede23821"
branch_labels = None
depends_on = None


# Migration data models
intpk = Annotated[
int,
mapped_column(sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
]
bigint = Annotated[
int, mapped_column(sa.BigInteger().with_variant(sa.Integer, "sqlite"))
]
text_ = Annotated[str, mapped_column(sa.Text())]


class UpgradeBase(DeclarativeBase, MappedAsDataclass):
pass


class DowngradeBase(DeclarativeBase, MappedAsDataclass):
pass


class EntryPointPluginUpgrade(UpgradeBase):
__tablename__ = "entry_point_plugins"

# Database fields
entry_point_resource_snapshot_id: Mapped[intpk]
plugin_resource_snapshot_id: Mapped[intpk]


class EntryPointPluginFileUpgrade(UpgradeBase):
__tablename__ = "entry_point_plugin_files"

# Database fields
entry_point_resource_snapshot_id: Mapped[intpk]
plugin_resource_snapshot_id: Mapped[intpk]
plugin_file_resource_snapshot_id: Mapped[intpk]


class PluginPluginFileUpgrade(UpgradeBase):
__tablename__ = "plugin_plugin_files"

# Database fields
plugin_resource_snapshot_id: Mapped[intpk]
plugin_file_resource_snapshot_id: Mapped[intpk]


class EntryPointPluginFileDowngrade(DowngradeBase):
__tablename__ = "entry_point_plugin_files"

# Database fields
entry_point_resource_snapshot_id: Mapped[intpk]
plugin_resource_snapshot_id: Mapped[intpk]
plugin_file_resource_snapshot_id: Mapped[intpk]


class PluginPluginFileDowngrade(DowngradeBase):
__tablename__ = "plugin_plugin_files"

# Database fields
plugin_resource_snapshot_id: Mapped[intpk]
plugin_file_resource_snapshot_id: Mapped[intpk]


class EntryPointPluginDowngrade(DowngradeBase):
__tablename__ = "entry_point_plugins"

# Database fields
entry_point_resource_snapshot_id: Mapped[intpk]
plugin_resource_snapshot_id: Mapped[intpk]


def upgrade():
bind = op.get_bind()
Session = sessionmaker(bind=bind)

# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"entry_point_plugins",
sa.Column(
"entry_point_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.Column(
"plugin_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.ForeignKeyConstraint(
["entry_point_resource_snapshot_id"],
["entry_points.resource_snapshot_id"],
name=op.f(
"fk_entry_point_plugins_entry_point_resource_snapshot_id_entry_points"
),
),
sa.ForeignKeyConstraint(
["plugin_resource_snapshot_id"],
["plugins.resource_snapshot_id"],
name=op.f("fk_entry_point_plugins_plugin_resource_snapshot_id_plugins"),
),
sa.PrimaryKeyConstraint(
"entry_point_resource_snapshot_id",
"plugin_resource_snapshot_id",
name=op.f("pk_entry_point_plugins"),
),
)
op.create_table(
"plugin_plugin_files",
sa.Column(
"plugin_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.Column(
"plugin_file_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.ForeignKeyConstraint(
["plugin_file_resource_snapshot_id"],
["plugin_files.resource_snapshot_id"],
name=op.f(
"fk_plugin_plugin_files_plugin_file_resource_snapshot_id_plugin_files"
),
),
sa.ForeignKeyConstraint(
["plugin_resource_snapshot_id"],
["plugins.resource_snapshot_id"],
name=op.f("fk_plugin_plugin_files_plugin_resource_snapshot_id_plugins"),
),
sa.PrimaryKeyConstraint(
"plugin_resource_snapshot_id",
"plugin_file_resource_snapshot_id",
name=op.f("pk_plugin_plugin_files"),
),
)

with Session() as session:
entry_point_plugin_stmt = sa.select(
EntryPointPluginFileUpgrade.entry_point_resource_snapshot_id,
EntryPointPluginFileUpgrade.plugin_resource_snapshot_id,
).distinct()

for row in session.execute(entry_point_plugin_stmt):
session.add(
EntryPointPluginUpgrade(
entry_point_resource_snapshot_id=row.entry_point_resource_snapshot_id,
plugin_resource_snapshot_id=row.plugin_resource_snapshot_id,
)
)

plugin_plugin_files_stmt = sa.select(
EntryPointPluginFileUpgrade.plugin_resource_snapshot_id,
EntryPointPluginFileUpgrade.plugin_file_resource_snapshot_id,
).distinct()

for row in session.execute(plugin_plugin_files_stmt):
session.add(
PluginPluginFileUpgrade(
plugin_resource_snapshot_id=row.plugin_resource_snapshot_id,
plugin_file_resource_snapshot_id=row.plugin_file_resource_snapshot_id,
)
)

session.commit()

op.drop_table("entry_point_plugin_files")
# ### end Alembic commands ###


def downgrade():
bind = op.get_bind()
Session = sessionmaker(bind=bind)

# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"entry_point_plugin_files",
sa.Column(
"entry_point_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.Column(
"plugin_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.Column(
"plugin_file_resource_snapshot_id",
sa.BigInteger().with_variant(sa.Integer(), "sqlite"),
nullable=False,
),
sa.PrimaryKeyConstraint(
"entry_point_resource_snapshot_id",
"plugin_resource_snapshot_id",
"plugin_file_resource_snapshot_id",
name=op.f("pk_entry_point_plugin_files"),
),
)
with op.batch_alter_table("entry_point_plugin_files", schema=None) as batch_op:
batch_op.create_foreign_key(
batch_op.f(
"fk_entry_point_plugin_files_entry_point_resource_snapshot_id_entry_points"
),
"entry_points",
["entry_point_resource_snapshot_id"],
["resource_snapshot_id"],
)
batch_op.create_foreign_key(
batch_op.f(
"fk_entry_point_plugin_files_plugin_file_resource_snapshot_id_plugin_files"
),
"plugin_files",
["plugin_file_resource_snapshot_id"],
["resource_snapshot_id"],
)
batch_op.create_foreign_key(
batch_op.f(
"fk_entry_point_plugin_files_plugin_resource_snapshot_id_plugins"
),
"plugins",
["plugin_resource_snapshot_id"],
["resource_snapshot_id"],
)

with Session() as session:
entry_point_plugin_files_stmt = sa.select(
EntryPointPluginDowngrade.entry_point_resource_snapshot_id,
EntryPointPluginDowngrade.plugin_resource_snapshot_id,
PluginPluginFileDowngrade.plugin_file_resource_snapshot_id,
).join_from(
PluginPluginFileDowngrade,
EntryPointPluginDowngrade,
EntryPointPluginDowngrade.plugin_resource_snapshot_id
== PluginPluginFileDowngrade.plugin_resource_snapshot_id,
)

for row in session.execute(entry_point_plugin_files_stmt):
session.add(
EntryPointPluginFileDowngrade(
entry_point_resource_snapshot_id=row.entry_point_resource_snapshot_id,
plugin_resource_snapshot_id=row.plugin_resource_snapshot_id,
plugin_file_resource_snapshot_id=row.plugin_file_resource_snapshot_id,
)
)

session.commit()

op.drop_table("plugin_plugin_files")
op.drop_table("entry_point_plugins")
# ### end Alembic commands ###
6 changes: 4 additions & 2 deletions src/dioptra/restapi/db/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
EntryPoint,
EntryPointParameter,
EntryPointParameterValue,
EntryPointPluginFile,
EntryPointPlugin,
entry_point_parameter_types_table,
)
from .experiments import Experiment
Expand All @@ -44,6 +44,7 @@
from .plugins import (
Plugin,
PluginFile,
PluginPluginFile,
PluginTask,
PluginTaskInputParameter,
PluginTaskOutputParameter,
Expand Down Expand Up @@ -71,7 +72,7 @@
"EntryPointJob",
"EntryPointParameter",
"EntryPointParameterValue",
"EntryPointPluginFile",
"EntryPointPlugin",
"Experiment",
"ExperimentJob",
"Group",
Expand All @@ -84,6 +85,7 @@
"MlModelVersion",
"Plugin",
"PluginFile",
"PluginPluginFile",
"PluginTask",
"PluginTaskInputParameter",
"PluginTaskOutputParameter",
Expand Down
14 changes: 5 additions & 9 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 @@ -146,8 +146,8 @@ class EntryPointParameterValue(db.Model): # type: ignore[name-defined]
)


class EntryPointPluginFile(db.Model): # type: ignore[name-defined]
__tablename__ = "entry_point_plugin_files"
class EntryPointPlugin(db.Model): # type: ignore[name-defined]
__tablename__ = "entry_point_plugins"

# Database fields
entry_point_resource_snapshot_id: Mapped[intpk] = mapped_column(
Expand All @@ -156,13 +156,9 @@ class EntryPointPluginFile(db.Model): # type: ignore[name-defined]
plugin_resource_snapshot_id: Mapped[intpk] = mapped_column(
ForeignKey("plugins.resource_snapshot_id"), init=False
)
plugin_file_resource_snapshot_id: Mapped[intpk] = mapped_column(
ForeignKey("plugin_files.resource_snapshot_id"), init=False
)

# 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")
plugin_file: Mapped["PluginFile"] = relationship(lazy="joined")
30 changes: 30 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 Expand Up @@ -102,6 +116,22 @@ class PluginFile(ResourceSnapshot):
}


class PluginPluginFile(db.Model): # type: ignore[name-defined]
__tablename__ = "plugin_plugin_files"

# Database fields
plugin_resource_snapshot_id: Mapped[intpk] = mapped_column(
ForeignKey("plugins.resource_snapshot_id"), init=False
)
plugin_file_resource_snapshot_id: Mapped[intpk] = mapped_column(
ForeignKey("plugin_files.resource_snapshot_id"), init=False
)

# Relationships
plugin: Mapped["Plugin"] = relationship(lazy="joined")
plugin_file: Mapped["PluginFile"] = relationship(lazy="joined")


class PluginTask(db.Model): # type: ignore[name-defined]
__tablename__ = "plugin_tasks"

Expand Down
Loading
Loading