Thank you for that explanation. I was completely misunderstanding the -broken hook, thinking it would run for each unit like -departed and just indicated that the unit was finally gone. I didn't realize that it didn't fire until there were no remaining units and the relation was torn down in its entirety.
I think that you're right that we should do some automatic cleanup, because if the charm author forgets to do so, it can lead to subtle and confusing bugs. I know, because I ran up against that already. :) On Sat, Dec 19, 2015 at 5:31 PM, Stuart Bishop <stuart.bis...@canonical.com> wrote: > On 20 December 2015 at 02:13, Cory Johns <cory.jo...@canonical.com> wrote: > > On Sat, Dec 19, 2015 at 3:45 AM, Stuart Bishop < > stuart.bis...@canonical.com> > > wrote: > >> > >> Which unit name would you use? -relation-departed gets run multiple > >> times, once for each unit. -relation-broken gets run once, after all > >> the -departed hooks have been run. > > > > > > That can't be right. Surely it must run at least once on each unit still > > remaining in the relation. Every relation consists of two end-points, > and > > A relation consists of several end-points. A relation is between two > services, which means it is between several units (several on the > 'local' side, and several on the 'remote' side). It is not a > conversation between two units, where two units are passing messages > between each other, but a conference involving several units, where > each unit is yelling at every other unit. I find the > relations-are-conversations metaphor breaks down as soon as you have > two or more units to a service. > > From the Juju docs: > > "" > [name]-relation-broken indicates that the current relation is no > longer valid, and that the charm's software must be configured as > though the relation had never existed. It will only be called after > every necessary -departed hook has been run; if it's being executed, > you can be sure that no remote units are currently known locally. It > is important to note that the -broken hook might run even if no other > units have ever joined the relation. This is not a bug: even if no > remote units have ever joined, the fact of the unit's participation > can be detected in other hooks via the relation-ids tool, and the > -broken hook needs to execute to give the charm an opportunity to > clean up any optimistically-generated configuration. > """ > > A unit appears in the relation. For every unit in the remote service, > the relation-joined and relation-changed hooks are triggered. If a new > unit is added to the remote service, the relation-joined and > relation-changed hooks are triggered. If a unit in the remote service > departs, the relation-departed hook is triggered. If the relation is > destroyed, the relation-departed hook is triggered once for each unit > in the remote service and the relation-broken hook triggered a single > time, after all the relation-departed hooks have been triggered. > > > > even if the implementation of Juju means that it's difficult or > impossible > > for the agent to populate that variable, there's still an objectively > > correct value to put there. And it doesn't seem unreasonable to have > > expected Juju to do so, like it does for every relation hook. > > > Also, as I referenced previously, I'm pretty sure that I could > reconstruct > > the expected value by saving the list of departing unit(s) in the charm > and > > comparing that to the list during the -broken hook. But my point was > that > > I don't think there is a correct value to put there. In the -broken > hook, the there will be zero units in the remote service. At this > point, there is no longer a remote service at all. The only thing you > would be doing is setting $REMOTE_UNIT to the last unit to depart, > which is arbitrary. > > > > I'm not sure it's worth doing that because I'm not sure I see a use-case > for > > this hook that couldn't just as easily be done with the -departed hook > > alone. > > relation-departed is when a remote *unit* has gone. > relation-broken is when the remote *service* has gone (or never > appeared in the first place) > > In theory, you can use it to clean up resources required by the remote > service. For example, you could shut down daemons no longer required > or destroy the database used by the remote service. In theory, you > don't do this from the relation-departed hook, because the remote > service still exists (even if it has no units) and new units could be > added. > > In practice, I don't think I've ever seen this done and suspect > relation-broken hooks are unnecessary atavisms like 'start' and 'stop' > hooks. In particular, cleaning up for $SERVICE in relation-broken is > tricky as Juju does not tell us what $SERVICE actually was - I think > all you know is the former relation id and relation name. > > > > >> As far as the reactive framework is concerned, I don't think it fits > >> as a handler on a RelationBase subclass. It would work fine as a > >> 'standard' parameterless handler. Maybe you want some magic to destroy > >> conversations and such from the now defunct and useless relation > >> object. > > > > > > I'm not sure I understand what you mean here. I don't see the need for > any > > "magic" here. During a relation hook, charms.reactive needs to be able > to > > determine what two units the relation applied to in order to know what > > conversations they may have been participating in and those > conversations' > > associated states. If it can't determine that for -broken, then -broken > > can't be used with charms.reactive. > > By magic I meant you may want to destroy any remaining conversations. > If the charm does not implement the relation-departed hook, or the > RelationBase.depart() method not called, you are going to end up with > garbage in unitdata.kv() for conversations in a relation that no > longer exists. We could probably ignore this garbage. > > The relation-broken hook does not have a remote unit as context > (unlike relation-joined, relation-changed and relation-departed). It > could still be used in charms.reactive though, just like 'install', > 'config-changed', 'leader-elected' and any other hook that does not > have a remote unit. > > class FooRelation(BaseRelation): > scope = scopes.GLOBAL > @hook('{provides:foo}-relation-changed') > def configure(self): > [...] > > @hook('{provides:foo}-relation-broken') > def foo_cleanup(): > [...] > > > > But, again, my question is whether it is even useful to do anything with > > -broken in reactive charms? > > It is just as necessary to handle relation-broken hooks in reactive > charms as it is to handle relation-broken hooks in non-reactive > charms. Which is to say, perhaps ;) My personal advice is never use > relation-joined or relation-broken hooks, as I find they do nothing > but add unnecessary complexity. I don't know if charms.reactive should > be that opinionated though. > > -- > Stuart Bishop <stuart.bis...@canonical.com> >
-- Juju mailing list Juju@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/juju