RxJavaのイベントリソースの解放とisUnsubscribed()の関係について

いまいち釈然としないものの、unsubscribeのタイミングでcancel処理をしたりイベントを投げるまえにisUnsubscribed()でチェックするのがセオリーっぽい雰囲気?まだ納得しきっていないのであとで自分でも検証してみる。
3
Hiroshi SAKURAI @anolivetree

@__gfx__ executeAsObservable()の中で、isUnsubscribed()のチェックは要らないのでしょうか? RxJavaにあまり詳しくないので、見当違いだったらすみません。

2016-02-26 09:30:01
FUJI Goro @__gfx__

@anolivetree unsubscribeされていたらコールバックは呼ばれないので必要ないですね。

2016-02-26 09:32:35
Hiroshi SAKURAI @anolivetree

@__gfx__ onNext()の中でExceptionが発生するとunsubscribeされます。現状だとその場合でもonNext()が呼ばれ続けます。

2016-02-26 09:47:10
FUJI Goro @__gfx__

@anolivetree なるほど。問題になるケースをコードでください!なるべく小さなコード片で。ormaに依存してなくてもかまいません。

2016-02-26 09:50:45
Hiroshi SAKURAI @anolivetree

@__gfx__ こんなコードです。"map called"が表示された後onErrorが呼ばれますが、その後も"map called"が表示され続けます。 gist.github.com/anolivetree/44…

2016-02-26 09:51:36
FUJI Goro @__gfx__

@anolivetree mapの関数はイベントが流れ続ける限り呼ばれるんですね。その挙動は知りませんでしたが、それはonError(Throwable throwable)で `throw Exceptions.propagate(throwable);` して止めてください。

2016-02-26 10:11:30
FUJI Goro @__gfx__

@anolivetree RxJava的には、mapの中の例外でストリームを殺すかどうかは使う側が決めるべきという挙動のようですね。

2016-02-26 10:12:13
Hiroshi SAKURAI @anolivetree

@__gfx__ 公式ページのサンプルでもisUnsubscribed()で逐次チェックしているので、Observer.createの作法なのだと思っていました。 github.com/ReactiveX/RxJa…

2016-02-26 10:48:30
FUJI Goro @__gfx__

@anolivetree おお…本当ですね!まさかそんな…という気持ちです。unsubscribedはチェックスべきなのかも…。ちょっと調べます。

2016-02-26 11:01:04
FUJI Goro @__gfx__

RxJava subscriberでイベントを投げるまえに `isUnsubscribed()` でチェックすべきかもしれない…ということにいまさら気づいて愕然としてる。うーん、しかし個人的には全然しっくりこないぞ。そんなバカな。 twitter.com/anolivetree/st…

2016-02-26 11:03:26
amay077@mastodon.cloud @amay077

@__gfx__ Rx.NET のCreateは、IDisposable.Disposeが呼ばれる仕組みなんですが、それでもそれをチェックしてOnXXXを呼ばなくしてますね。 msdn.microsoft.com/en-us/library/…

2016-02-26 11:29:29
amay077@mastodon.cloud @amay077

@__gfx__ Rx.NET のCreateは、IDisposable.Disposeが呼ばれる仕組みなんですが、それでもそれをチェックしてOnXXXを呼ばなくしてますね。 msdn.microsoft.com/en-us/library/…

2016-02-26 11:29:29
amay077@mastodon.cloud @amay077

@__gfx__ 個人的には確保したリソースを解放するタイミングがisUnsubscribedだという認識なんですけど、RxJavaのそれがしっくりこないのは、Pollingしないと確認できないことですね。createの中で別の非同期メソッド呼んでたらどうすんの?という。

2016-02-26 11:32:21
FUJI Goro @__gfx__

@amay077 なるほど本家もそうなんですね。ううーん。違和感というのはおっしゃるとおりです。push的にunsubscribeが送られるならたとえばhttp requestを中断とかできますが、そうじゃないわけじゃないですか。

2016-02-26 11:37:14
amay077@mastodon.cloud @amay077

@__gfx__ そうなんですよ。RxNETの方は、Observableの購読が解除された時点でDisposeが呼ばれるので、requestの中断ができます。が、 RxJava の createではそれができないようで… Retrofitのコードでも読めばいいのかな?

2016-02-26 11:44:36
Hiroshi Kurokawa @hydrakecat

@__gfx__ @amay077 RxJava も SafeSubscriber は unsubscribe 後は何もしなくなるので、実質不要ですが、お作法として必要なのかなと思っていました。こんなのありましたが判然としないですね。groups.google.com/forum/#!topic/…

2016-02-26 11:48:10
FUJI Goro @__gfx__

@amay077 Retrofitみると、Subscriptions.create()でunsubscribeを受け取れるようになってるっぽいすな。うーんなるほど…。 github.com/square/retrofi…

2016-02-26 11:50:51
FUJI Goro @__gfx__

@hydrakecat @amay077 それが、イベントは生き続けるのでリソースを無駄に使いたくないなら実質不要とも言いがたいんですよね。

2016-02-26 11:51:49
amay077@mastodon.cloud @amay077

@__gfx__ @hydrakecat github.com/square/retrofi… 僕も見てましたw 面白いすね、なるほどという感じです。

2016-02-26 11:55:11
FUJI Goro @__gfx__

@anolivetree とりあえずunsubscribeはちゃんとハンドルしないといけなそう、ということがわかりました…。 v2.1.0 で対応します!

2016-02-26 12:01:01
Hiroshi Kurokawa @hydrakecat

@amay077 @__gfx__ うむむ。SafeSubscriber がチェックしてくれるから実際は不要かなと思っていたのですが。何か全然違う話してたらすみません。github.com/ReactiveX/RxJa…

2016-02-26 12:04:56
amay077@mastodon.cloud @amay077

@hydrakecat @__gfx__ えっと、createの中でDBをopenしてたら、いつcloseするの?という話と、createの中で非同期リクエストをしてる場合、unsubscribeされたら’可能であれば’リクエストを実行前にキャンセルしたい、という話です。

2016-02-26 12:20:53
Hiroshi Kurokawa @hydrakecat

@amay077 @__gfx__ あー、なるほど。isUnscribed() でチェックすべきか否かという話かと思っていました。すみません。確かに unsubscribe のタイミングでリソースの解放と処理中のものはキャンセルしたいですね。

2016-02-26 12:25:09
amay077@mastodon.cloud @amay077

@__gfx__ @hydrakecat さんが紹介してくれたトピで新たに沸いた疑問は「isUnsubscribedとonNextの間にunsubscribe()される」で、 SafeSubscriber もですが、Thread-safe にできてるのかな?と思いました。

2016-02-26 12:40:16
Hiroshi Kurokawa @hydrakecat

@amay077 @__gfx__ SafeSubscriber はコード見る限り thread-safe じゃなさそうですね。onNext() を concurrent に呼ばないという規約なのでそういう前提なのかもしれません。github.com/reactive-strea…

2016-02-26 16:37:37