Alex,

Thank you for the detailed explanations and examples.

After reading Tilman's and Cory's replies, I think the confusion is at continuous evaluation (thus execution) of a True state. So a pair of @when and @when_not will result in one of them being executed over and over despite adding a remove_state("myself") in the @when block.

I'm still trying to grasp the idea of this "state" instead of treating it as an event handler.

So for states, I usually draw a state machine diagram. In this case, it feels rather unnatural that all True states will inherently loop to themselves.

But I don't what alternative is in charm's context.


On 07/27/2017 04:13 AM, Alex Kavanagh wrote:
Hi

On Thu, Jul 27, 2017 at 2:37 AM, fengxia <fx...@lenovo.com <mailto:fx...@lenovo.com>> wrote:

    Hi Juju,

    Once I set a state, set_state("here"), I want to make sure its
    @when will only be executed ONCE (when "here" from False->True).

    So my thought is to remove_state("here") in its @when("here") code
    block. If I don't, will this @when be called multiple times if I
    don't reset this state? What's the good practice here?


You have a couple of options here depending on the nature of the handler.

 1. If, in the lifetime of the unit's existence, the handler only has
    to execute ONCE.  (and I mean EVER), then there is a @only_once
    decorator that can be used.  It can be used in combination with
    other decorators to set up a condition, but it guarantees that the
    handler will only be called once.  However, what you probably want
    is ...
 2. Use a @when_not('flag') and then set it the 'flag' in the body of
    the handler.

The first would look something like:

@when('some-condition-flag')
@only_once
def do_something_only_once_when_some_condition_flag_is_set_for_the_first_time():
     ... do something once ...

The second treats a flag as a 'have I done this yet' condition, and allows you to reset the flag at some other point in the charm's life cycle so that you can do it again. 'installed' is a good example of this:

@when_not('installed-something')
def do_install_of_something():
    ... do the installation ...
# when it is fully successful, set the installed-something flag. Don't set it early as # if it errors, a future handler invocation may be able to continue the installation.
    set_state('installed-something')


@when(some other conditions indicating do an upgrade)
def do_upgrade():
     ... set upgrade sources, or other pre upgrade actions
     remove_state('installed-something')

In this situation, hopefully you can see that we can re-use 'do_install_of_something()' when we do upgrades.

I think it's useful to think about states (flags) as being a 'memory' that something has happened, and use them to either gate on not doing things again, or to trigger the next action is a graph of actions that need to take place to get the charm's payload to the desired operational state. I tend to name them, and use them, to indicate when something has happened, rather than when it hasn't, and so tend to use @when_not('some-flag') on the handler that eventually sets that flag.

Hope that this helps.
Alex.



-- Feng xia
    Engineer
    Lenovo USA

    Phone: 5088011794 <tel:5088011794>
    fx...@lenovo.com <mailto:fx...@lenovo.com>

    Lenovo.com
    Twitter | Facebook | Instagram | Blogs | Forums


-- Juju mailing list
    Juju@lists.ubuntu.com <mailto:Juju@lists.ubuntu.com>
    Modify settings or unsubscribe at:
    https://lists.ubuntu.com/mailman/listinfo/juju
    <https://lists.ubuntu.com/mailman/listinfo/juju>




--
Alex Kavanagh - Software Engineer
Cloud Dev Ops - Solutions & Product Engineering - Canonical Ltd

--
Feng xia
Engineer
Lenovo USA

Phone: 5088011794
fx...@lenovo.com
        
Lenovo.com
Twitter | Facebook | Instagram | Blogs | Forums

-- 
Juju mailing list
Juju@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/juju

Reply via email to