Solrのパッケージ管理機能がクラスタレベルのプラグインに対応しました

はじめに

以前の記事で紹介したパッケージ管理機能ではコレクションレベルのプラグインを管理できました。Solr 8.6 でクラスタレベルのプラグインにも対応しました。クラスタレベルのプラグインとは、クラスタを構成するノード毎に1個だけインスタンスを作るプラグインです。

リファレンスの説明だけでは分かりにくいところもあったので、使い方をまとめてみました。

リポジトリ登録まで

リポジトリを作成して Solr に登録 → インストール →デプロイという流れは同じなので、リポジトリ作成の詳細は前回の記事を参照してください。

プラグインのコード

プラグインが提供する API のエンドポイントに関する情報をアノテーションで記述するところがミソです。path の指定の中で $path-prefix という変数が参照されていますが、これは後述のリポジトリ定義(repository.json)で定義されます。

リポジトリ定義

クラスタレベルをサポートするにあたって type フィールドが追加されたようです。指定しない場合は collection になるので、クラスタレベルの場合は type: cluster を指定しなければうまくデプロイできません。

コレクションレベルのときと大きく異なるのは setup-command と uninstall-command です。それぞれ、以下の API リクエストに対応しています。

curl -X POST -H 'Content-type:application/json' --data-binary '
{
  "add": {
  "name":"myplugin",
  "class": "myplugin:jp.co.splout.solr.plugins.MyPlugin",
  "path-prefix" : "splout",
  "version": "1.0.0"
  }
}' http://localhost:8983/api/cluster/plugin

curl -X POST -H 'Content-type:application/json' --data-binary '
{
  "remove": "myplugin"
}' http://localhost:8983/api/cluster/plugin

verify-command をどう定義すべきかよく分からなかったので省略してありますが、これでも動くようです。

リポジトリ登録

$ bin/solr package add-repo MyPlugin http://localhost/solr/repo1
$ bin/solr package list-available 
Available packages:
-----
myplugin 		Cluster Level Plugin Example
	Version: 1.0.0
	Version: 1.1.0

インストール

-cluster オプションを指定します。

$ bin/solr package install myplugin:1.0.0 -cluster
Posting manifest...
Posting artifacts...
Executing Package API to register this package...
Response: {"responseHeader":{
    "status":0,
    "QTime":56}}
myplugin installed.
$ bin/solr package install myplugin:1.1.0 -cluster
Posting manifest...
Posting artifacts...
Executing Package API to register this package...
Response: {"responseHeader":{
    "status":0,
    "QTime":5}}
myplugin installed.

$ bin/solr package list-installed
Installed packages:
-----
{
  "name":"myplugin",
  "version":"1.0.0"}
{
  "name":"myplugin",
  "version":"1.1.0"}

デプロイ

ここでも -cluster オプションを指定します。

$ bin/solr package deploy myplugin:1.0.0 -cluster
Executing {"add":{"name":"myplugin","class":"myplugin:jp.co.splout.solr.plugins.MyPlugin","path-prefix":"splout","version":"1.0.0"}} for path:/api/cluster/plugin
Execute this command. (If you choose no, you can manually deploy/undeploy this plugin later) (y/n): 
y
1 cluster level plugins setup.
Deployed on [] and verified package: myplugin, version: 1.0.0
Deployment successful

clusterprops.json

クラスタレベルでデプロイされたプラグインの情報は、ZooKeeper に置かれた clusterprops.json から読み出せます。

$ curl http://localhost:8983/api/cluster/zk/data/clusterprops.json
{"plugin":{"myplugin":{
      "name":"myplugin",
      "class":"myplugin:jp.co.splout.solr.plugins.MyPlugin",
      "version":"1.0.0",
      "path-prefix":"splout"}}}

プラグインのAPI呼び出し

ソースコードでエンドポイントのパスを “/$path-prefix/myplugin” と定義しました。repository.json で path-prefix を “splout” と定義したので、このプラグインの API は以下のように呼び出せます。

$ curl http://localhost:8983/api/splout/myplugin
{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "myplugin.version":"1.0.0"}

アップデート

–update -cluster オプションを指定して deploy を実行します。

$ bin/solr package deploy myplugin:1.1.0 --update -cluster
Updating this plugin: org.apache.solr.client.solrj.request.beans.PluginMeta@aa370c48
Posting {"update": {
  "name":"myplugin",
  "class":"myplugin:jp.co.splout.solr.plugins.MyPlugin",
  "version":"1.1.0",
  "path-prefix":"splout"}} to /api/cluster/plugin
1 cluster level plugins updated.
Deployed on [] and verified package: myplugin, version: 1.1.0
Deployment successful

動作確認します。

$ curl http://localhost:8983/api/splout/myplugin
{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "myplugin.version":"1.1.0"}

「AirPods Pro」と「M3IETW2」を買った結果

Web会議や夜中近くのゲームで煩くならないようにBluetoohのイヤホンを購入しました。その過程で単純にBluetoohに対応ってだけ見ると失敗してしまうとわかったのでこちらにまとめました。

無線イヤホン

長くなるので最初に結論

  • Bluetoohはイヤホンである受信側と音を出す側の送信側のコーデックが一致していないと使えない
  • コーデックにはSBC < AAC < AptX < AptxLLなど他にも色々(音質はAptX > AptXLL)
  • PCやゲーム機など自前で送信する部分を持っていない場合はBlutoohのオーディオトランスミッターが必要

最初に購入したのはアクティブノイズキャンセリング目当てで「AirPods Pro」
対応コーデックはAAC

実際使ってみると設定なども簡単でアクティブノイズキャンセリングも評判通り世界が変わるレベルで音が聞こえない。ただゲームだとワンテンポずれて音が聞こえるので微妙、音ゲーは無理。他に家の中とかだとPCの動作音とかは小さくはあるが聞こえるので完全というわけではない(それでもほとんどは聞こえないレベル)
iPhoneの音楽再生だけとかリモートワークぐらいであれば設定も簡単なのでオススメ

次は対応コーデックや音質も気にして「MOMENTUM True Wireless 2」
対応コーデックはAptX

設定はAirPods Proに比べるとトランスミッターも原因ではあるが面倒・・・ただ一回設定したらあとはつけるだけなのであまり変わらない。音質はよく音ズレについては少し気になる程度でそこまで問題はないがゲーム目当てだとAptXLL対応の方を買えばよかったかも

数ヶ月立った結果

個人的にはノイズキャンセラー目当てでSonyの「WF-1000XM3」とAptXLL対応のイヤホンを別々で買った方が良かったかと後悔しましたが・・・数ヶ月経過した今振り返ってみると圧倒的に使ってる機会が少ない!
外:ドラクエウォークをいつもつけてるので不要
内でゲーム:夜中近くにゲームをすること自体がなくなったので不要
たまにWeb会議で使うぐらい・・・
完全にお荷物になっているわけではないが結果的にもっと安めのやつでも問題なかったかも

【Solr】管理UIのZK Status表示問題がSolr 8.6.1で解決しました

Solr 8.6.1 の Changelog を眺めていたら、以下のバグフィックスが含まれていることに気づきました。

SOLR-14671: Parsing dynamic ZK config sometimes cause NumberFormatException (janhoy)

これを読んで思い出したのが、以前の記事にも書いた、Solr 8.5 と ZooKeeper 3.6 の組み合わせだと Solr の管理UIで ZooKeeper のステータスが正しく表示されない問題です。このバグフィックスにより解決するのではないかと思い、試してみました。

前の記事で環境は作ってあるので、”image: zookeeper:3.5.7″ を “image:zookeeper:3.6″ に、”image: solr:8.5” のところを “image: solr:8.6.1” に変更するだけです。

Solr 8.5 と ZooKeeper 3.6 の組み合わせ。

Solr 8.6.1 と ZooKeeper 3.6 の組み合わせ。

予想通り解決しました。この問題に対処するためのバグフィックスだったようです。

Vue.jsと別ライブラリの共存方法(模索中)

こちらの方法は模索中であり一般的な解決方法ではないかもしれません。とりあえず動作するというレベルになります。既存の処理を置き換えつつも代替えライブラリが見つからない、または容易に実装できない際に取れる手段の1つとして考えてください。

まず例として郵便番号を住所に変換するライブラリがあるとします。zip_codeを書き込むと自動でaddressのinput要素に対してvalueで住所を自動的に設定する系になります。

<input type="tel" v-model="zip_code" name="zip_code">
<input type="tel" v-model="address" name="address">

こちらVueで上記を作成しライブラリも同様に利用した場合はzip_codeを入力した時点では自動でaddressにデータは設定されますが、Vue側にデータは渡っていないので他の要素に対して入力等イベントが発生した時にVue側に保存されているデータで上書きされます。

こちらの解決方法として再描写がされる前にVue側にデータを設定する
// 再描写(re-render)される前に呼ばれる関数
beforeUpdate: function(){
  // vueと連携していないinput要素を反映する
  this.reflectInputValues();
}
methods: {
  // vueと連携していないinput要素を反映する
  reflectInputValues: function(){
    this.zip_code = $('[name=zip_code]').val();
    this.address = $('[name=address]').val();
  }
}

ただし注意点として
・入力が完了しただけでは「reflectInputValues」が呼ばれないので対象となるデータを触りたい場合は「reflectInputValues」を明示的に呼ぶ必要がある
・Vue側から直接データを設定しても先にbeforeUpdateが呼ばれる為反映されないのでinput要素に直接valueを設定して「reflectInputValues」を呼び出す必要がある

動作はしますがVueの旨味を消している形になるので基本的にはVue用のライブラリを探す等をお勧めします。他にいい方法はないかな。