New option for managing flags in Endpoints


#1

Managing flags in Endpoint classes with @when etc has always had some edge cases and timing issues which were non-obvious. With the release today of charms.reactive 1.3.0, Endpoint classes can now implement a Endpoint.manage_flags method which is guaranteed to be called before any decorated handlers as part of the instance initialization, after the framework-provided automatic flags are adjusted, and is a good place to do all flag manipulation for the interface layer.

As an example, the kube-control interface provides could be changed from:

    @when_any('endpoint.{endpoint_name}.joined',
              'endpoint.{endpoint_name}.changed')
    def joined_or_changed(self):
        set_flag(self.expand_name('{endpoint_name}.connected'))

        hookenv.log('Checking for gpu-enabled workers')
        if self._get_gpu():
            set_flag(
                self.expand_name(
                    '{endpoint_name}.gpu.available'))
        else:
            clear_flag(
                self.expand_name(
                    '{endpoint_name}.gpu.available'))

        clear_flag(self.expand_name('endpoint.{endpoint_name}.changed'))

    @when_not('endpoint.{endpoint_name}.joined')
    def departed(self):
        """
        Remove all states.
        """
        clear_flag(
            self.expand_name(
                '{endpoint_name}.connected'))
        clear_flag(
            self.expand_name(
                '{endpoint_name}.gpu.available'))

To the more concise:

    def manage_flags(self):
        toggle_flag(self.expand_name('{endpoint_name}.connected'),
                    self.is_joined)
        toggle_flag(self.expand_name('{endpoint_name}.gpu.available'),
                    self.is_joined and self._get_gpu())

Using this approach also avoids a race condition where handlers in the charm could could potentially be called before the interface layer had a chance to do its internal flag adjustments. While this is usually not a problem for most charms, and could also be addressed with triggers, I think the manage_flags approach is more intuitive.

Feedback on this approach is appreciated.


#2

@cory_fu This is awesome and super clean! Definitely a step in the right direction!

pros:

* avoids possible race condition - check
* less generic code - check
* more concise and intuitive - check

I don’t see any cons …