<div dir="ltr">fengxia,<div><br></div><div>It's probably more enlightening to think of them as "flags" rather than states.  (Indeed, the next release of charms.reactive will deprecate calling them states and will provide set_flag, remove_flag, etc. functions instead.)</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 27, 2017 at 3:29 PM, fengxia <span dir="ltr"><<a href="mailto:fxia1@lenovo.com" target="_blank">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">
  
    
  
  <div 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><div><div class="h5">
    <br>
    <div class="m_921366770099927250moz-cite-prefix">On 07/27/2017 04:13 AM, Alex Kavanagh
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <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">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_<wbr>some_condition_flag_is_set_<wbr>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-<wbr>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-<wbr>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-<wbr>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="m_921366770099927250HOEnZb"><font color="#888888"><br>
                  <br>
                  -- <br>
                  Feng xia<br>
                  Engineer<br>
                  Lenovo USA<br>
                  <br>
                  Phone: <a href="tel:5088011794" value="+15088011794" target="_blank">5088011794</a><br>
                  <a href="mailto:fxia1@lenovo.com" target="_blank">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">Juju@lists.ubuntu.com</a><br>
                  Modify settings or unsubscribe at: <a href="https://lists.ubuntu.com/mailman/listinfo/juju" rel="noreferrer" target="_blank">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="m_921366770099927250gmail_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="m_921366770099927250moz-signature" cols="72">-- 
Feng xia
Engineer
Lenovo USA

Phone: <a href="tel:(508)%20801-1794" value="+15088011794" target="_blank">5088011794</a>
<a class="m_921366770099927250moz-txt-link-abbreviated" href="mailto:fxia1@lenovo.com" target="_blank">fxia1@lenovo.com</a>
        
Lenovo.com 
Twitter | Facebook | Instagram | Blogs | Forums
</pre>
  </div></div></div>

<br>--<br>
Juju mailing list<br>
<a href="mailto:Juju@lists.ubuntu.com">Juju@lists.ubuntu.com</a><br>
Modify settings or unsubscribe at: <a href="https://lists.ubuntu.com/mailman/listinfo/juju" rel="noreferrer" target="_blank">https://lists.ubuntu.com/<wbr>mailman/listinfo/juju</a><br>
<br></blockquote></div><br></div>