generate
Generateとは
Plugin.call
でイベントを呼び出す時、そのイベントが実際いくつのプラグインで受け取られるかは呼び出し側にはわかりません。これは意図的な仕様で、mikutterの拡張性を担保するための重要な要素です。
Streamの登場によって、イベントを使って断続的に終わりのないデータが流れ続ける、ストリームを実現することができるようになりました。しかし、それはリスナ(受け取り側)の話であって、結局イベントを発生させるのは Plugin.call
を使う必要がありました。
generateメソッドは、Streamを提供する側の表現力を上げ、効率的な実装を実現するための機能です。
以下に例を挙げます。説明のために、 user_stream
というメソッドは、投稿を受信する度にModelを1つ引数にとって呼び出されることとします。
user_stream do |message|
Plugin.call(:appear, [message])
end
generate(:appear) do |yielder|
user_stream do |message|
yielder << message
end
end
Generateが解決すること
イベント発生側もイベント発生回数を意識しなくて良くなる
呼び出し回数の最適化では、リスナがイベントの数を意識することがなくなると説明されています。
確かにsubscribeを使えばリスナの呼び出し回数の最適化の余地はありますが、イベントを発生させる側がn個のイベントを発生させている以上、イベント発生のオーバーヘッドはあります。
generateメソッドを使えば、generateを使った例のように、イベント発生ではなくストリームのような構文になっているため、複数のイベントをまとめることができます。
購読されるまでストリームを提供しない
generateメソッドに渡されたブロックは、他のプラグインでsubscribeや通常のイベントリスナ(on_???)でリスナが登録されるまで実行されません。
generateを使った例の user_stream
メソッドを呼び出すとSNSのサーバにHTTPコネクションを確立するとしましょう。appearイベントを受け取るプラグインが存在しなければ、わざわざインターネットから投稿を取得して居るにも関わらず、それをすべて捨てていることになります。
そこでgenerateを使った例のような実装をすれば、appearイベントが購読されて初めて接続するようになります。実際にこの仕組みはMastodonプラグインに利用されています。あらゆるデータがあらゆるストリームでいつでも受け取れるように見えるにも関わらず、実際には必要とされている情報しかMastodonサーバから取ってこないようになっているのです。
普通、そのような最適化をするなら、イベントが購読されているか常に確認し続け、購読状況に応じてサーバに接続するような実装をする必要があるでしょう。generateメソッドを使えば、そのような判断をPluggaloidに一任できます。
いつGenerateを使うか
まず、generateメソッドの対象のイベントがストリームイベントである必要があります。ストリームイベントではない、または不明な場合は従来のイベント発生方法を使います。
generateメソッド
generate(event_slug, *rest) { |yielder| … } → nil
引数名 | 型 | 意味 |
---|---|---|
event_slug |
subscribeするイベントの識別子 |
|
*rest |
- |
ストリーム引数以外の引数 |
yielder |
ストリーム引数に含める値を受け取るオブジェクト |
subscribeで、 event-slug
と rest
が完全に一致するリスナが一つでも登録されたら、ブロックを実行します。
on_ event_slug
でリスナが定義されると、 rest
の内容に関わらず、即座にブロックが実行されます( rest
が一致したと見做して処理をします)。
解除されるものは以下の通りです。
-
on_??? で登録したイベントリスナ
-
filter_??? で登録したフィルタのリスナ
Pluggaloid::Yielder
generateメソッドのブロックの引数に渡されるオブジェクトです。 このオブジェクトに、ストリームに流したい値を渡すことで、イベントが発行されます。
self << object → self
引数名 | 型 | 意味 |
---|---|---|
object |
- |
ストリームに流すオブジェクト |
戻り値 |
self |
ストリームに一つ値を追加します。generateメソッドに指定したストリーム引数以外の引数を伴ってイベントが発生します。
bulk_add(objects) → self
引数名 | 型 | 意味 |
---|---|---|
objects |
ストリームに流すオブジェクトの配列等 |
|
戻り値 |
self |
ストリームに2つ以上の値を同時に追加します。generateメソッドに指定したストリーム引数以外の引数を伴ってイベントが発生します。一度にたくさんのオブジェクトを追加したい場合、self << object → selfよりこちらのほうが効率的です。
互換性
generateメソッドは、イベントの発生をストリームのような構文で実現するためのものであり、あくまでイベントを発生させているだけです。したがって、generateメソッドを使ったからといって on_???
のような形式で受け取ることができなくなるわけではありません。
受け取り\呼び出し | Plugin.call | generateメソッド |
---|---|---|
|
○ |
○ |
○ |
○ |