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

Reply via email to