<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Alex,</p>
    <p>Thank you for the detailed explanations and examples.</p>
    <p>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.</p>
    <p>I'm still trying to grasp the idea of this "state" instead of
      treating it as an event handler.</p>
    <p>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. <br>
    </p>
    <p>But I don't what alternative is in charm's context.<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 07/27/2017 04:13 AM, Alex Kavanagh
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAO3V+Om+HVPZPttJqVVtXJut9nTmKGky7wAgacMGZrfRBxPUDw@mail.gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div dir="ltr">Hi
        <div class="gmail_extra"><br>
          <div class="gmail_quote">On Thu, Jul 27, 2017 at 2:37 AM,
            fengxia <span dir="ltr"><<a
                href="mailto:fxia1@lenovo.com" target="_blank"
                moz-do-not-send="true">fxia1@lenovo.com</a>></span>
            wrote:<br>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Juju,<br>
              <br>
              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).<br>
              <br>
              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?</blockquote>
            <div><br>
            </div>
            <div>You have a couple of options here depending on the
              nature of the handler.</div>
            <div><br>
            </div>
            <div>
              <ol>
                <li>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 ...<br>
                </li>
                <li>Use a @when_not('flag') and then set it the 'flag'
                  in the body of the handler.</li>
              </ol>
              <div>The first would look something like:</div>
            </div>
            <div><br>
            </div>
            <div>@when('some-condition-flag')</div>
            <div>@only_once</div>
            <div>def
do_something_only_once_when_some_condition_flag_is_set_for_the_first_time():</div>
            <div>     ... do something once ...</div>
            <div><br>
            </div>
            <div>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:</div>
            <div><br>
            </div>
            <div>@when_not('installed-something')</div>
            <div>def do_install_of_something():</div>
            <div>    ... do the installation ...</div>
            <div>    # when it is fully successful, set the
              installed-something flag.  Don't set it early as</div>
            <div>    # if it errors, a future handler invocation may be
              able to continue the installation.</div>
            <div>    set_state('installed-something')</div>
            <div><br>
            </div>
            <div><br>
            </div>
            <div>@when(some other conditions indicating do an upgrade)</div>
            <div>def do_upgrade():</div>
            <div>     ... set upgrade sources, or other pre upgrade
              actions</div>
            <div>     remove_state('installed-something')</div>
            <div><br>
            </div>
            <div>In this situation, hopefully you can see that we can
              re-use 'do_install_of_something()' when we do upgrades.</div>
            <div><br>
            </div>
            <div>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.</div>
            <div><br>
            </div>
            <div>Hope that this helps.</div>
            <div>Alex.</div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex"><span
                class="HOEnZb"><font color="#888888"><br>
                  <br>
                  -- <br>
                  Feng xia<br>
                  Engineer<br>
                  Lenovo USA<br>
                  <br>
                  Phone: <a href="tel:5088011794" value="+15088011794"
                    target="_blank" moz-do-not-send="true">5088011794</a><br>
                  <a href="mailto:fxia1@lenovo.com" target="_blank"
                    moz-do-not-send="true">fxia1@lenovo.com</a><br>
                          <br>
                  Lenovo.com<br>
                  Twitter | Facebook | Instagram | Blogs | Forums<br>
                  <br>
                  <br>
                  -- <br>
                  Juju mailing list<br>
                  <a href="mailto:Juju@lists.ubuntu.com" target="_blank"
                    moz-do-not-send="true">Juju@lists.ubuntu.com</a><br>
                  Modify settings or unsubscribe at: <a
                    href="https://lists.ubuntu.com/mailman/listinfo/juju"
                    rel="noreferrer" target="_blank"
                    moz-do-not-send="true">https://lists.ubuntu.com/mailm<wbr>an/listinfo/juju</a><br>
                </font></span></blockquote>
          </div>
          <br>
          <br clear="all">
          <div><br>
          </div>
          -- <br>
          <div class="gmail_signature" data-smartmail="gmail_signature">
            <div dir="ltr">Alex Kavanagh - Software Engineer
              <div>Cloud Dev Ops - Solutions & Product Engineering -
                Canonical Ltd</div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="72">-- 
Feng xia
Engineer
Lenovo USA

Phone: 5088011794
<a class="moz-txt-link-abbreviated" href="mailto:fxia1@lenovo.com">fxia1@lenovo.com</a>
        
Lenovo.com 
Twitter | Facebook | Instagram | Blogs | Forums
</pre>
  </body>
</html>