プロジェクト

全般

プロフィール

バグ #1231

アカウント切り替えがメニューから実行できない場合がある

Akira Ouchi7ヶ月前に追加. 4ヶ月前に更新.

ステータス:
終了
優先度:
通常
担当者:
対象バージョン:
プラグイン名:
current_world
ブランチ:
topic/1231-fix-rarely-world-shifter-does-not-work
クラッシュする:
いいえ

説明

アカウント切り替えを画面左上のメニューから実行すると、タイミングによってできない場合があります。
切り替えができないときは、以下のエラーが出力されます(--debugでmikutterを起動)。

error: {MIKUTTER_DIR}/core/plugin/current_world/current_world.rb:21:in `rescue in block (2 levels) in <top (required)>': RuntimeError
from {MIKUTTER_DIR}/core/plugin/current_world/current_world.rb:42:in `current_world='
from {MIKUTTER_DIR}/core/plugin/current_world/current_world.rb:17:in `block (2 levels) in <top (required)>'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/listener.rb:25:in `call'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:97:in `block (2 levels) in call_all_listeners'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:96:in `each'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:96:in `block in call_all_listeners'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:95:in `catch'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:95:in `call_all_listeners'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pluggaloid-1.1.1/lib/pluggaloid/event.rb:39:in `block in call'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/delayer-0.0.2/lib/delayer/procedure.rb:24:in `run'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/delayer-0.0.2/lib/delayer/extend.rb:58:in `run_once'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/delayer-0.0.2/lib/delayer/extend.rb:30:in `run'
from /Users/akkie/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/delayer-0.0.2/lib/delayer.rb:43:in `method_missing'
from {MIKUTTER_DIR}/core/plugin/gtk/delayer.rb:10:in `block in boot'
from {MIKUTTER_DIR}/core/plugin/gtk/mainloop.rb:10:in `main'
from {MIKUTTER_DIR}/core/plugin/gtk/mainloop.rb:10:in `mainloop'
from mikutter.rb:68:in `boot!'
from mikutter.rb:104:in `<main>'

実際にどういうタイミングならできるのかは不明(しばらく待てば出来るようになる?とか)です。
感覚的には起動直後のアカウント切り替えはできない印象です。
ただし、ショートカットキーからアカウントを切り替えることは起動直後でもできるようです。

1231.log (99.6 KB) 1231.log ろぐ kagura1050 てお, 2018-06-11 17:37
DeepinScreenshot_select-area_20180615091645.png (69.6 KB) DeepinScreenshot_select-area_20180615091645.png toshi_a 初音, 2018-06-15 09:16

再現手順

起動直後にアカウント切り替えを画面左上のメニューからおこなう

関係しているリビジョン

リビジョン d42e24d3 (差分)
toshi_a 初音5ヶ月前に追加

Twitter: Twitter Worldはuriとして一意な値を返す refs #1231

リビジョン 49b4e6b4 (差分)
toshi_a 初音5ヶ月前に追加

world: World Modelを作り直した時、URIが変わっていたら警告を出力する refs #1231

リビジョン 74277aee (差分)
toshi_a 初音5ヶ月前に追加

current_world: アカウント切替時のエラーをActivityに表示 refs #1231

リビジョン ba07605e (差分)
toshi_a 初音5ヶ月前に追加

current_world: 遷移先のworldとしてnilを渡されることを考慮する refs #1231

履歴

#1 toshi_a 初音7ヶ月前に更新

  • ステータス分類待ち から 実装待ち に変更

起動直後に再現することを確認しました。

World系Modelが再生成されているようで、Portalのようなuriをちゃんと生成していないやつは、インスタンスが再生成されるたびに違うURIになるため、切り替え先のWorldと==メソッドで一致するWorldが見つからないという状態になってるようです。

やることとしては

  • Worldのインスタンスは起動時一度だけ作ればいいので、何度も作られている原因を探り、一度だけにする
  • RuntimeErrorじゃなくて、もうちょっと丁寧なエラーメッセージを出す

くらいかなぁ

#2 kagura1050 てお5ヶ月前に更新

僕の環境でも再現しましたので起動->再現->終了までのログ添付しておきます

#3 toshi_a 初音5ヶ月前に更新

原因がわかりました。Twitter, World, Current World, GUIプラグインをそれぞれ修正するコミットをして、それぞれ検証していきます。

対応

Twitterプラグイン

uriメソッドを実装し、一意な値を返す。

Worldプラグイン

デバッグモード時、World slugが同じなのにuriが変わってしまうことを検出し、警告を出す。
今のところはWorldプラグインのドキュメントを書けていないため、このチケットのURLを表示する?

Current Worldプラグイン

RuntimeErrorではなく独自の例外を投げる。または、エラーメッセージを設定し、何が起こっているかを書く(切り替えようとしているWorldはリストに存在しない、といった内容)

切り替えはユーザによって行われるはずなので、失敗した場合には例外をstderrに出力するのもいいが、Activityでユーザにその旨を報告したほうが良いと思う。

GUIプラグイン

source:core/plugin/gtk/world_shifter.rb@707c4e65#L56 で、Worldリストがリフレッシュされるタイミングをイベントで監視し、それに合わせてGtkウィジェットを作り直している。

しかし、world_modifyで作り直される可能性は考慮されていない。厳密にはWorldリストは再生成しているので、world_modifyが発生したときにもリフレッシュすると今回の問題は緩和できる。

より良い解決策として、 source:core/plugin/world/world.rb@707c4e65#L90 のWorld Modelのリストを作り直したタイミングで、リスト内のWorldのuriが一つでも変わったら発生するイベントを新設して、World Shifterはそちらを利用するようにしたほうが良さそう。

サードパーティプラグイン

Twitterプラグインに行った実装を参考に、一意な値を返すようにWorld Modelのuriメソッドを再実装してもらう。

原因

world_modifyイベントなどでWorldが更新された時に実行される source:core/plugin/world/world.rb@707c4e65#L79 で、Worldリストが初期化されている。

次回Worldリストが要求された時にWorld Modelが作り直されて変更が反映されるが、作り直されるWorldがuriメソッドを実装していない場合、uriが毎回ランダムに生成される。

current_worldプラグインの source:core/plugin/current_world/current_world.rb@707c4e65#L42 では、 Enumerable#include? による比較を行っているため、uriが異なると対象のWorldが見つけられずRutimeErrorが発生する。こうなるとWorldの切り替えはできないため、World Shifterでアカウントを切り替えても反応がなく、切り替えができないという問題が起こる。

#4 toshi_a 初音5ヶ月前に更新

twitter, world, current_worldの変更は実装しました。
今回、この問題は私は再現できてません。 @Akkiesoft 以外でも、この問題が再現できていた人は確認してフィードバックをください。

変更内容と確認方法

Worldプラグイン

mikutterを起動した時に、標準エラー出力に以下のような出力が出ていれば、WorldのURIが定義されていないことを検出しているということになります。

warning: {MIKUTTER_DIR}/core/plugin/world/world.rb:114:in `block in check_world_uri': The URI of World `a20e42bd-8e5c-4d9b-b3bb-dc274935d840' is not defined. You must define a consistent URI for World Model. see: https://dev.mikutter.hachune.net/issues/1231

しかし、Twitter Worldは今回で対応を入れたので上記のようなエラーメッセージは出ません。Worldonもこのチケットを見て早々に対応されたようです。Portalプラグイン( https://github.com/toshia/portal )によるWorldが含まれていれば再現できます。

current_worldプラグイン

World Shifter(アカウント切り替えメニュー)でメニューからアカウントを選んだのにアカウントが切り替わらなかった時、アクティビティタブに「アカウントを切り替えようとしましたが、切り替えようとしたアカウントは存在しませんでした。」というようなメッセージが表示されます。

このシステムメッセージは、以下のコードをmikutterコンソールで実行すると確実に再現できます。

Plugin.call(:world_change_current, Skin['notfound.png'])

twitterプラグイン

World Shifterで、PortalなどのWorldに切り替え出来ない状態の時でも、Twitter Worldになら切り替えができるはずです。

GUIプラグインの変更をしなかったことについて

GUIプラグインですが、やはり筋が悪いかなと思い直して実装していません。

World Modelは同じ値をコンストラクタに与えられたら同じものが作られるべきです。
したがって内部的にWorld Modelのインスタンスが再生成されることを検出する意味はありません。

また、このような実装をしてしまうと、今後他のサードパーティプラグインもWorld Modelを特別扱いする必要が出てきて、余計なルールが増えます。worldやcurrent_worldに今回実装したように、World Modelにuriを定義することを促すような形のほうがスッキリすると思います。

#5 Akira Ouchi5ヶ月前に更新

  • ステータスレビュー待ち から まだダメ に変更

checkoutして確認しようとしたところ、以下のエラーでクラッシュしました。

/Users/akkie/mikutter/core/plugin/current_world/current_world.rb:17:in `block (2 levels) in <top (required)>': undefined method `uri' for nil:NilClass (NoMethodError)

コードを確認したところ、on_world_change_currentのrescueでnew.urlがなくてコケているように見えます。
(なんかこれが出るかどうかで再現してるしてないかが分かれていそうな気もしますね。)
newを使わないようにしてやると、こけなくなりました。

    rescue Plugin::CurrentWorld::WorldNotfoundError
      activity :system, _('アカウントを存在しないアカウント(%{uri})に切り替えようとしました') % {uri: "あ"},
               description: _('アカウントを切り替えようとしましたが、切り替えようとしたアカウントは存在しませんでした。') + "\n\n" +
               _("切り替え先のアカウント:\n%{uri}") % {uri: "あ"} + "\n\n" +
               _('現在存在するアカウント:') + "\n" +
               Enumerator.new{|y| Plugin.filtering(:worlds, y) }.map{|w| "#{w.slug} (#{w.uri})" }.to_a.join("\n") + "\n\n" +
               _('%{world_class}#uri を定義することでこのエラーを回避できます。詳しくは %{see} を参照してください') % {world_class: "い", see: 'https://dev.mikutter.hachune.net/issues/1231'}

情報量ゼロになるのでやくに立たないですが、一応こういう出力が起動直後に1つ出るようになります。

アカウントを切り替えようとしましたが、切り替えようとしたアカウントは存在しませんでした。

切り替え先のアカウント:
あ

現在存在するアカウント:
worldon:akkiesoft@social.mikutter.hachune.net (plugin://world.worldon/social.mikutter.hachune.net/akkiesoft/******)
worldon:poop_parrot@social.mikutter.hachune.net (plugin://world.worldon/social.mikutter.hachune.net/poop_parrot/******)
twitter34582322 (plugin://world.twitter/twitter******)
7958e4e8-4315-4b9e-9754-5e5fb7d06b2e (plugin://world.portal/******)
haiku--3826178559572183616 (plugin://world.haiku/******)
worldon:Akkiesoft@pawoo.net (plugin://world.worldon/pawoo.net/Akkiesoft/******)
worldon:Akkeisoft@mstdn.maud.io (plugin://world.worldon/mstdn.maud.io/Akkeisoft/******)

い#uri を定義することでこのエラーを回避できます。詳しくは https://dev.mikutter.hachune.net/issues/1231 を参照してください

printデバッグでnewを確認しても、まじで何も入ってないっぽかったです。

#6 Akira Ouchi5ヶ月前に更新

  • 担当者Akira Ouchi から toshi_a 初音 に変更

#7 toshi_a 初音5ヶ月前に更新

  • ステータスまだダメ から レビュー待ち に変更
  • 担当者toshi_a 初音 から Akira Ouchi に変更

nilガードは付けられるので付けてみました。

しかし、world_change_currentイベントの引数にnilが与えられる状況がわからないです。サードパーティプラグインなんかで、このイベントを発生させているものをインストールしてませんか。

#8 Izumi Tsutsui5ヶ月前に更新

とりあえずで
topic/1231-fix-rarely-world-shifter-does-not-work ba07605 をチェックアウト
worldon を fbdcab44 に更新 https://github.com/cobodo/mikutter-worldon/commit/fbdcab44f9b081a278948fc0f74d8d37958d6981
という状態、かつ、
1つ目のアカウントがマストドン
2つ目のアカウントが Twitter
という mikutter 設定でテストしてみました。

3回ほど起動してみた範囲では起動直後にそれぞれ world 変更できるようです。

元の 3.7.2 の環境では起動後しばらく(条件不明)はマストドンアカウントから Twitter に変更できませんでした。
topic/1231-fix-rarely-world-shifter-does-not-work と worldon の変更前 (6/9 くらい) の組み合わせでは
Twitter → マストドンへの変更ができない場合がありました。

ということで、こちらでは意図通り修正されているように見えます。

#9 Akira Ouchi5ヶ月前に更新

  • ステータスレビュー待ち から マージ待ち に変更

toshi_a 初音 さんは書きました:

nilガードは付けられるので付けてみました。

しかし、world_change_currentイベントの引数にnilが与えられる状況がわからないです。サードパーティプラグインなんかで、このイベントを発生させているものをインストールしてませんか。

https://github.com/namotch/world_primary のせいっぽそうです。
world_primaryを無効にしたらnilガード無しでも起動することを確認できました。
また、nilガードを適用した状態でworld_primaryを有効にしても起動できました。

#10 cob odo5ヶ月前に更新

mikutterを起動した時に、標準エラー出力に以下のような出力が出ていれば、WorldのURIが定義されていないことを検出しているということになります。

warning: {MIKUTTER_DIR}/core/plugin/world/world.rb:114:in `block in check_world_uri': The URI of World `a20e42bd-8e5c-4d9b-b3bb-dc274935d840' is not defined. You must define a consistent URI for World Model. see: https://dev.mikutter.hachune.net/issues/1231

しかし、Twitter Worldは今回で対応を入れたので上記のようなエラーメッセージは出ません。Worldonもこのチケットを見て早々に対応されたようです。Portalプラグイン( https://github.com/toshia/portal )によるWorldが含まれていれば再現できます。

こちらの環境でもこの方法で動作確認できました。world_primaryをインストールした状態でもクラッシュしていません。

また、最近のmikutterでは、起動後しばらくtwitterのリストによるストリーム受信ができていなかったように見受けられていたのですが、このパッチによって解消しているのも確認しました。

#11 toshi_a 初音4ヶ月前に更新

  • ステータスマージ待ち から 終了 に変更

merged.

他の形式にエクスポート: Atom PDF