LoginSignup
7
6

More than 5 years have passed since last update.

Subscribe to Eventボックスにちゃんとunsubscribeさせる

Last updated at Posted at 2015-10-03

先日イベントで「Subscribe to EventボックスがonStop入力後もイベントを出力してしまう」みたいな指摘があったのですが、Record Videoを直してみたみたいな投稿にもある通り、Choregrapheに添付されたボックスライブラリ群は簡単にAPIの機能などにアクセスできる一方、少々扱いが面倒な部分があります。

今回は、Subscribe to Eventボックスの現在の動きの確認と、所望の動きをする(onStopされたらunsubscribeされる)ボックスへとどのように修正すべきかを個人的に考えてみたのでそのメモ。

Subscribe to Eventボックスの現在の動き

動作確認用ビヘイビアを作りました。動作確認は Choregraphe 2.3.1.25 とバーチャルロボットでおこなっています。
また、今回作成したChoregrapheプロジェクトは、GitHub https://github.com/yacchin1205/pepper-subscribe-to-event に置いてあります。

動作確認用プロジェクトは test で、ビヘイビアの構成はこんな感じ。

root.png

Testボックス内でSubscribe to Eventボックスを実行しています。

Test.png

Subscribe to Eventボックスはテスト用のイベント TestKey1 を購読するよう設定しています。
Raise Eventボックスにより、以下の3つのタイミングで TestKey1 のイベントを発火し、それぞれにSubscribe to Eventボックスがどう反応するかを見ています。

なお、Subscribe to EventボックスがどのRaise Eventボックスに反応したかをわかりやすくするため、それぞれタイミングによりイベントに与える値を変えています。

  1. Subscribe to EventボックスにonStartが入力された後 - Raise EventによりExpected を発火
  2. Subscribe to EventボックスにonStopを入力された後(停止状態) - Unexpected を発火
  3. Subscribe to Eventボックスの親ボックスが停止し、ボックスがアンロードされた後 - Unload を発火

挙動の確認はログビューアにより行っています。Subscribe to Eventボックスには以下のような接続、修正をおこなっています。

  • Subscribe to EventボックスにLogボックスを接続(Message textは Test)
  • Subscribe to EventボックスのonEventCallback に以下の行を追加

    def onEventCallback(self, key, value, message):
        # テストのため追加-ここから
        self.logger.info('Called: key=%s value=%s' % (key, value))
        # テストのため追加-ここまで
        self.onEvent(value)
    

このように、動作確認した内容もビヘイビアとして残しておくことで、テストした内容を残しておくことができ、「以前はどんな動きしてたんだっけ」といったことを確認しやすくなります。

出力されたログ

バーチャルロボットで実行したところ、以下のようなログが得られました。

[INFO ] behavior.box :onInput_message:26 ...__Test_9__Log_1: Test: Expected
[INFO ] behavior.box :onEventCallback:21 ...__Test_9__SubscribetoEvent_7: Called: key=TestKey1 value=Expected
[INFO ] behavior.box :onInput_message:26 ...__Test_9__Log_1: Test: Unexpected
[INFO ] behavior.box :onEventCallback:21 ...__Test_9__SubscribetoEvent_7: Called: key=TestKey1 value=Unexpected
[INFO ] behavior.box :onUnload:10 ...__Test_9__Log_1: Unloaded: Test box
[INFO ] behavior.box :onEventCallback:21 ...__Test_9__SubscribetoEvent_7: Called: key=TestKey1 value=Unloaded

簡単にまとめるとこんな感じ。

状況 Subscribe to Eventに続くボックスの反応 onEventCallbackの反応
onStartが入力された後 あり あり
onStopが入力された後 あり あり
アンロードされた後 なし あり

Testボックス内のLogボックスはアンロードされていることをログから確認しているので、Subscribe to Eventボックスがアンロードされなかったということは考えにくそう。
ということは、アンロードされた後も onEventCallback が呼ばれているような・・・

現在のSubscribe to Eventボックスの停止・アンロード処理における課題

以上からわかった挙動と、Subscribe to Eventボックスのコードを考慮すると、以下の2つの課題がありそうです。

  1. Subscribe to EventボックスはonStop入力がされても、onStopped出力を発火するだけで、特に購読の停止処理をおこなうことはない
  2. Subscribe to Eventボックスはアンロードされても購読の停止処理をおこなわず、onEventCallbackの呼び出し自体は継続される

実際の利用上は、Subscribe to Eventボックスがアンロードされるのに合わせて、onEvent出力の出力先のボックスもアンロードされるため、購読自体はアンロードにともない停止されたように見える。ということなのかなと思います。

Subscribe to Eventボックスの修正例

Subscribe to Eventボックスは、現在の実装でも、回避策(適切に他のボックスをアンロードする)をとればまあ利用できないわけではないわけですが、アプリ中での予期しない挙動を防ぐためにも、単純に、

  • onStart入力がされると、イベント発生に応じてonEvent出力がされる(開始状態)
  • onStop入力がされると、イベントが発生してもonEvent出力がなされなくなる(停止状態)

みたいにしておきたいよね、となるのが開発者の心情です。

そこで、以下のような修正をすることにします。

  1. onStop入力がされた際にアンロード相当の処理を実行する

    def onInput_onStop(self):
        # 修正: onStop時にonUnloadを呼び出す
        self.onUnload()
        self.onStopped()    
    
  2. onUnload時に ALMemory.unsubscribeToEvent() を実行する

    def onUnload(self):
        # 修正: unsubscribeToEventを実行する
        if self.memory is not None:
            self.memory.unsubscribeToEvent(self.getParameter("key"), self.getName())
        self.memory = None
    

まあ、新規作成直後のPythonボックスの onStop の記述にも self.onUnload() #it is recommended to reuse the clean-up as the box is stopped って書いてあることだし・・・ということと、ハンドラを追加したら、適切に削除しましょう。ということで。

修正例の動作確認

testプロジェクトのうち、Subscribe to Eventボックスを上記のような修正をしたバージョンに置き換えたのが、GitHubにおいたコード中の fixed プロジェクトです。

これを実行すると、以下のように期待した動作(Unexpected, Unloadイベントは無視)をするようになります。

[INFO ] behavior.box :onEventCallback:26 ...__Test_9__SubscribetoEvent_7: Called: key=TestKey1 value=Expected
[INFO ] behavior.box :onInput_message:26 ...__Test_9__Log_1: Test: Expected
[INFO ] behavior.box :onUnload:10 ...__Test_9__Log_1: Unloaded: Test box

このように修正したボックスを、 独自ボックスライブラリの作成と管理 などを参考に管理していくと、よりボックスでのアプリ作成が楽になるのでは・・・と思います。

ちなみに、このようなテストや、問題発生時の修正は、独自ボックスでも同じように必要になってくる作業です。他にも個人的におこなっているトライアルがあるので、キリがいいところで投稿していこうと考え中・・・

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6