Repository navigation
Paket-Migrationen #194
Description
QuestionPy-Pakete sollten* nach den Semantic Versioning Regeln versioniert werden. Daraus abgeleitet, müssen Migrationen entweder explizit angegeben werden oder können implizit geschehen.
Es sollen folgende Operationen ermöglicht werden:
upgrade
von (X) |
zu (Y) |
Art |
|---|---|---|
| 1.5.0 | 1.5.1 | implizit |
| 1.5.* | 1.6.* | implizit |
| 1.*.* | 2.*.* | explizit |
Wenn der Question-State von Version X auf Version Y geupgraded werden soll, muss die Migration im Paket Y erfolgen.
Hierfür muss im "expliziten-Fall" und muss nicht* im "impliziten-Fall" eine upgrade_to-Funktion in Y implementiert sein, die die Migrations-Logik enthält.
downgrade
von (X) |
zu (Y) |
Art |
|---|---|---|
| 1.5.1 | 1.5.0 | implizit |
| 1.6.* | 1.5.* | explizit |
| 2.*.* | 1.*.* | explizit |
Wenn der Question-State von Version X auf Version Y gedowngraded werden soll, muss die Migration im Paket X erfolgen.
Hierfür muss im "expliziten-Fall" und muss nicht* im "impliziten-Fall" eine downgrade_to-Funktion in X implementiert sein, die die Migrations-Logik enthält.
sidegrade
Wenn man sidegraden möchte, muss das immer explizit geschehen. Will man den State von Paket X nach Paket Y sidegraden, dann sollte im Paket Y eine sidegrade_from-Funktion implementiert sein. Hier könnte man noch überlegen, ob X auch eine sidegrade_to-Funktion implementieren darf. Eine sidegrade_from-Funktion sollte dabei nicht nur den Namespace und Shortname des Pakets entgegennehmen, sondern auch die Version, z.B.:
X möchte zu Y migrieren und Y hat einesidegrade_from("X", Version(1, 0, 0))-Funktion. - Y kann also alle States mit Paketversion 1.0.* direkt* migrieren. Ideal wäre es, wenn die upgrade_to- oder downgrade_to-Funktionen von X aufgerufen werden, um bei Inkompatibilität einen kompatiblen State zu erzielen.
* Wenn wir es nicht als Bedingung sehen, dass Pakete strikt nach SemVer versioniert werden, dann können wir zusätzliche upgrade_to-/downgrade_to-Funktionen erlauben (z.B.: upgrade_to(Version(1, 5, 1)). Allerdings wäre dann die beschriebene sidegrade_from-Logik so nicht umsetzbar.
Activity
tumidi commentedon Nov 21, 2025
Inwieweit kann aus der (SemVer-)Paketversion abgeleitet werden ob eine Migration verpflichtend oder optional ist (bzw. explizit/implizit)?
SemVer bezieht sich doch auf die Public API Surface, und trifft keinerlei Garantien über das interne Datenmodell.
Ich würde da spontan eine Versionierung der Migrationen wie aus anderen Software-Paketen einfallen:
raise NotImplementedErrormarkiert o.ä.Warum ist diese Tabelle asymmetrisch zur upgrade-Tabelle?
Für eine Spec/Doku halte ich die Bezeichnungen "implizit/explizit" für nicht so hilfreich. Was genau bedeutet eine "implizite Migration"? Eine No-op, also keine Migration? Eine automatische Migration? Nach welchen Regeln?
Idee: ändern in "
upgrade_to-Funktion verpflichtend (mandatory) oder optional".Fände ich persönlich etwas klarer und implizit/explizit müsste auch nicht extra definiert werden.
janbritz commentedon Nov 24, 2025
Meinst du mit deinem Vorschlag konkret, dass z.B. im Manifest neben der Paketversion auch eine einfache State-Version (Migrationsversion?) angegeben werden muss, die getrennt voneinander betrachtet werden sollen?
Ich würde vorschlagen, dass nur Migrationen angegeben werden müssen, die möglich sind. Andernfalls wird eine Migration als unmöglich interpretiert. Oder wie würdest du im Falle einer fehlenden Migration handeln?
Eine zusätzliche State-Version halte ich auch im Hinblick auf die DX schöner, da sofort ersichtlich ist, wann eine Migration implementiert werden kann und man auch diese wirklich nur implementieren muss, wenn es nötig ist.
@MHajoha hatte vorgeschlagen, dass die möglichen Migrationen in der
qpy_manifest.jsonabgelegt werden sollten, um diese in der UI zu verwenden. Das könnte dann so aussehen:Im Code könnte das so aussehen:
Der Vorteil daran wäre, dass die Migrationsfunktionen außerhalb der Question definiert werden können, da diese mit der Zeit stark wachsen können und dass die IDE meckert, sobald für eine Version / einen Identifier mehrere Migrationsfunktionen angegeben wurden.
MartinGauk commentedon Nov 25, 2025
Nach unserer heutigen Diskussion geht mir jetzt ein Beispiel durch den Kopf:
Bei einer Einstellung mit Dropdown-Menü wird eine neue Option hinzugefügt. Sagen wir es gibt ein Feld für "Währung" mit Auswahl USD und EUR, und ergänzt nun um CHF. Für diese Ergänzung würde man keinen Update-Code schreiben, weil die bestehenden Einstellungen ja erhalten bleiben sollen. Allerdings müsste man eigentlich einen Downgrade-Code schreiben, der States mit CHF auf eine andere Währung setzt oder den Downgrade ganz unterbindet.
Ich fürchte aber, dass man als Paket-Entwickler an diesen Fall zu dem Zeitpunkt häufig gar nicht denkt und keine neue state_version einführt, einfach weil man eher Updates im Kopf hat und Downgrades zweitrangig sind.
Wenn keine neue state_version existiert, wird davon ausgegangen, dass beliebig zwischen diesen Paket-Versionen mit derselben state_version gewechselt werden kann. Es kann aber gut sein, dass eine niedrigere Version nicht mit CHF klarkommt und die Ausführung in eine Exception endet.
janbritz commentedon Nov 25, 2025
Im heutigen Meeting sind wir zum Entschluss gekommen, dass im Paket ein
migrations-Package erstellt werden kann, in welchem alle verfügbaren Migrations in mehreren Dateien leben. Aus der Anzahl der Migrations kann dann geschlussfolgert werden, welche State-Version das aktuelle Paket verwendet.Durch die Bennenung der Dateien oder der Klassen soll mittels (alpha-)numerischer Sortierung die Reihenfolge der Migrations bestimmt werden.
Sidegraden:
TODO
MartinGauk commentedon Dec 1, 2025
Nach einigem Überlegen und Diskussion mit Claude 4.5 Sonnet komme ich zu dem Entschluss, dass wir Downgrades lieber gar nicht erst unterstützen sollten. Der Aufwand auf unserer Seite für die Grundlagen dazu und auf Seiten der Paketentwickler lohnt sich nicht. Die KI hat es gut auf den Punkt gebracht: "Die Realität: Die meisten Downgrades werden nie ausgeführt und sind beim ersten echten Bedarf kaputt.".
Ich denke, es ist wichtiger, dass im LMS ein Konzept vorgesehen ist, dass vor einem Paket-Update ein Backup erstellt wird und man später dieses Backup wieder einspielen kann.
Downgrades auf Paket-Versionen mit derselben State-Version könnten trotzdem mit Warnung ja zugelassen werden.
Wie seht ihr das?