From @helgi on June 8, 2016 14:54
deis/controller#792 has uncovered some inconsistencies in our data model on Release.
Problem
Currently things are set up so that Release is the child object of Config and Build via ForeignKey with CASCADE delete set.
Each Config and Build object can be re-used across multiple Release objects, if nothing changes on the respective object. Such as: User A does 50 releases but they are only config changes, then the build object will always stay the same.
In many parts of the code when doing deploy and that fails we only delete the Release object, thinking the ForeignKey relationship is going to take care of it but that doesn't happen since Release is a child object, not a parent.
Why is this a problem?
If only the Release object is remove then the Config object stays behind. When creating new releases it seems we are doing things like selecting the latest Config from the App or something... If the latest Config object is poisoned in a way that is hard to fix then.
Basically the User ends up in a situation where it becomes pretty hard / impossible to recover from
Experiment
I did a quick experiment and used the DB directly after creating a few releases with combinations of config and build changes - First I tried deleting a release by hand, no config / build objects went away, and then I went and deleted a config object attached to 2 releases and both releases went away.
Potential solutions
I reviewed a few solutions and how they would affect us
- Flip the FK relationship around
- This would require the biggest rewrite as
Config and Build objects can't be created without Release
- Start programmatically handling the "when to delete config / build as well" and such
- Brittle as I will also have to look at all the
latest() usages and try to reconcile things
- Create a 1:1 between Release and Config/Build and severing the Config/Build tie with the
app_id making Release the only connection, turning a Release into a ledger of sorts
- Allows us to treat the
Release as an artefact but will make the DB bigger
Copied from original issue: deis/controller#798
From @helgi on June 8, 2016 14:54
deis/controller#792 has uncovered some inconsistencies in our data model on
Release.Problem
Currently things are set up so that
Releaseis the child object ofConfigandBuildvia ForeignKey with CASCADE delete set.Each
ConfigandBuildobject can be re-used across multipleReleaseobjects, if nothing changes on the respective object. Such as: User A does 50 releases but they are only config changes, then the build object will always stay the same.In many parts of the code when doing
deployand that fails we only delete theReleaseobject, thinking the ForeignKey relationship is going to take care of it but that doesn't happen sinceReleaseis a child object, not a parent.Why is this a problem?
If only the
Releaseobject is remove then theConfigobject stays behind. When creating new releases it seems we are doing things like selecting thelatestConfigfrom theAppor something... If the latestConfigobject is poisoned in a way that is hard to fix then.Basically the User ends up in a situation where it becomes pretty hard / impossible to recover from
Experiment
I did a quick experiment and used the DB directly after creating a few releases with combinations of config and build changes - First I tried deleting a release by hand, no config / build objects went away, and then I went and deleted a config object attached to 2 releases and both releases went away.
Potential solutions
I reviewed a few solutions and how they would affect us
ConfigandBuildobjects can't be created withoutReleaselatest()usages and try to reconcile thingsapp_idmaking Release the only connection, turning a Release into a ledger of sortsReleaseas an artefact but will make the DB biggerCopied from original issue: deis/controller#798