Include the URL of your launchpad blueprint:
We need to precalculate the graph of dependencies between all extant resources in the stack, including versions of resources that are now out of date.
When applying a transformation to a stack, load all extant resources for that stack from the DB. If one or more versions of a resource in the template already exist, select the most up-to-date one to update provided it is in a valid state. If no versions of a resource in the template exist in the database, create one for it.
Calculate the dependency graph, such that we will visit all of the selected resources in dependency order to update them where neccessary and visit all of the resources in reverse dependency order to clean them up where neccessary. Clean-up operations on a resource must always happen after any update operation on the same resource.
Finally, replace the traversal ID with a new UUID and create a SyncPoint for each node in the graph with this traversal ID. It should also create a SyncPoint for the stack itself, which will be used to indicate when the update portion of the traversal is complete, at which time the stack status can be updated.
This code should largely follow the prototype in https://github.com/zaneb/heat-convergence-prototype/blob/resumable/converge/stack.py
If two updates are racing, one of them will fail to atomically update the Stack row with its own newly-generated traversal ID. In this case it should roll back the database changes, by deleting any newly-created Resource rows that it added as well as all of the SyncPoints.