fix: retain plugin lifecycle ownership and recover installation state (#7146)

* fix: retain plugin lifecycle ownership and recover installation state

* test: cover plugin rollback and uninstall lifecycle boundaries

---------

Co-authored-by: jxxghp <jxxghp@gmail.com>
This commit is contained in:
Aqr-K
2026-10-23 07:44:07 +08:00
committed by GitHub
parent bcbf79f030
commit 6610a8c008
49 changed files with 1811 additions and 197 deletions

View File

@@ -0,0 +1,48 @@
"""
合并插件同键旧重复数据,并为安装补偿保留本体启用位快照。
"""
import sqlalchemy as sa
from alembic import op
revision = "b8d2f5a01962"
down_revision = "e6a4c9f20813"
branch_labels = None
depends_on = None
_INDEX = "ix_plugindata_plugin_id_key"
def upgrade() -> None:
"""
保留原同步读取最先可见的最低ID记录,去除其余同插件同键重复行后创建唯一索引。
"""
connection = op.get_bind()
table = sa.table("plugindata", sa.column("id", sa.Integer), sa.column("plugin_id", sa.String),
sa.column("key", sa.String))
keep_ids = sa.select(sa.func.min(table.c.id)).group_by(table.c.plugin_id, table.c.key)
connection.execute(table.delete().where(table.c.id.not_in(keep_ids)))
indexes = {index["name"]: index for index in sa.inspect(connection).get_indexes("plugindata")}
if _INDEX in indexes and not indexes[_INDEX].get("unique"):
op.drop_index(_INDEX, table_name="plugindata")
if _INDEX not in indexes or not indexes[_INDEX].get("unique"):
op.create_index(_INDEX, "plugindata", ["plugin_id", "key"], unique=True)
if "plugininstallation" in sa.inspect(connection).get_table_names():
columns = {column["name"] for column in sa.inspect(connection).get_columns("plugininstallation")}
if "host_enabled_before" not in columns:
# 旧journal无法推断被提前覆盖的启用位,保留NULL表示需人工复核。
op.add_column("plugininstallation", sa.Column("host_enabled_before", sa.Boolean, nullable=True))
def downgrade() -> None:
"""
恢复非唯一索引;升级已合并的旧重复值不重新制造。
"""
connection = op.get_bind()
if "plugininstallation" in sa.inspect(connection).get_table_names():
columns = {column["name"] for column in sa.inspect(connection).get_columns("plugininstallation")}
if "host_enabled_before" in columns:
op.drop_column("plugininstallation", "host_enabled_before")
op.drop_index(_INDEX, table_name="plugindata")
op.create_index(_INDEX, "plugindata", ["plugin_id", "key"], unique=False)