Open merlijn-sebrechts opened 6 years ago
I tend to agree. There are other ways to achieve a true "run this only once" (e.g. use your own sentinel file). But there is a basic issue with the imperative nature of writing code in charms being in 'conflict' with juju's approach of retrying failed hooks.
Your example shows how very, very subtle bugs can be introduced into a charm. Perhaps, in the docs, a more 'declarative' / 'goal-seeking' approach should be considered, where every shown function is written in a way that results in the same state regardless of how many times it is called (successfully)
I've created patches explaining this behavior for both the Juju docs and the charms.reactive docs. However, writing these patches, some things started to bother me about this behavior..
From email thread: https://lists.ubuntu.com/archives/juju/2017-October/009548.html
The reactive framework resets state changes when a handler fails. This surprises charm authors. States are often used to ensure idempotency such as in the following example.
After
this_call_fails
fails, theinitialized
state gets removed again, causing theinit
function to be called again during the next run. As a result of this behavior, all handlers must be idempotent and states cannot be used to achieve that.The reason the charm state needs to be rolled back on hook failure is that the changes made to the Juju environment get rolled back on hook failure. However, since hooks are hidden from the charm author it is not clear when a hook starts and when it finishes, and this transactional nature isn't explained in the docs nor are the names of the commands self-explanatory.