Node-RED v0.19のPersistable contextを使ってみた
イントロ
先日、Node-REDの新バージョンv0.19がリリースされたので、新機能を使ってみました。
今回試してみたのは、Persistable contextです。 Persistable contextとは、これまではメモリのみで管理されてきたglobalコンテキストやflowコンテキストと言った、大域変数的なものを、ファイルや外部のストレージに保存できる仕組みのことです。 この機能により、何らかのトラブルでNode-REDのプロセスが止まっても、コンテキストの情報が消滅する事を防げます。
Context browser
まず、Persistable contextの前に、Context browserというPersistable contextに付随する新機能に注目しましょう。 これは、コンテキストの値を表示する、エディター内のエリアのことです。 下の画面の右側です。
このフローでは、Changeノードでflowコンテキストにmsg.payload
の値を入れています。
Injectノードを叩いた後に右側のFlowの更新ボタンを押すと、flowコンテキストの値を見ることが出来ます。
フローは、こちらの通りです。
[{"id":"f71cbc29.c580e","type":"inject","z":"1af50515.7fc843","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":120,"wires":[["fa489cb4.7685c8"]]},{"id":"fa489cb4.7685c8","type":"change","z":"1af50515.7fc843","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"test","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":120,"wires":[["57b6b2bc.8879ec"]]},{"id":"57b6b2bc.8879ec","type":"debug","z":"1af50515.7fc843","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":490,"y":120,"wires":[]}]
これまではエディターではコンテキストの値を確認することができませんでした。
そのため、コンテキストの値を確認するためには、ChangeノードかFunctionノードを利用してmsg
内にコンテキストの値を入れ、Debugノードで表示する、といった手間が必要でした。
Context browserによって、そのような確認用のフローを設置する必要がなくなるため、デバッグのためだけに必要な余計な処理を、記述したり除去したりしなくてすみます。
printfデバッグから、デバッガーに進歩した印象です。
Persistable contextの有効化
次に、Persistable contextです。
まずはPersistable contextをenableにするために、settings.js
を修正しましょう。
$ vim $HOME/.node-red/settings.js
そして、以下の行を下のように編集します。
// Context Storage // The following property can be used to enable context storage. The configuration // provided here will enable file-based context that flushes to disk every 30 seconds. // Refer to the documentation for further options: https://nodered.org/docs/api/context/ // contextStorage: { default: { module:"localfilesystem" }, },
localfilesystemに設定することで、ファイルにコンテキストの情報を書き出すようになります。
settings.js
の修正が終わったら、Node-REDを(再)起動して、修正を反映させましょう。
出力ファイルを確認
先ほどと同じフローのInjectノードをクリックすると、コンテキストの値がファイルに永続化されます。
このファイルは、$HOME/.node_red/context
ディレクトリに存在します。
フローID (タブのID)と同じディレクトリが作られ、その中にフローコンテキストの情報を格納するファイルが生成されます。
centos:~/.node-red/context/1af50515.7fc843 $ cat flow.json { "test": 1534504312108 }
ここでいうフローとは、Node-REDのタブの事です。 flowコンテキストは、一つのタブの中で共有されるので、タブ毎にコンテキスト情報が出力されます。
globalコンテキストは、context
ディレクトリ直下にglobal.json
が置かれました。
これは、Node-RED毎にglobalコンテキストは一つだからでしょう。
その他、詳細はこちらの通りです。
Node-RED : Local Filesystem Context Store
Context storeプラグイン
Persistable contextの重要なポイントは、どこにコンテキストの値を外部出力するかを、プラグインとして、Node-REDに追加で設定できる点です。 そのため、ビルトインでは、メモリへの格納とファイルへの永続化のみが用意されていますが、任意のDBへのデータ格納などを、ユーザーが自分で作って使うことが出来ます。 このプラグインを、Context storeプラグイン、もしくはContext storeモジュールと呼びます。
このドキュメントは、こちらに記載されています。
実装しなければならないAPIが多いので、今回は、localfilesystemをパクったlocalfilesystem2を用意してみましょう。 localfilesystemは、GitHub上で、以下のディレクトリにコードがあります。
Persistable contextプラグインの開発
実装手順は、本家のガイドラインには書かれていませんが、簡単です。
まず任意のディレクトリを作成して、npmのプロジェクトを作成しましょう。
$ mkdir localfilesystem2; cd $_ $ npm init
プロジェクト名は、localfilesystem2にします。
エンドポイントは、index.js
でも構いません。
次に、index.js
を作成し、その中に、上のGitHubのlocalfilesystem.js
の中身をコピーしましょう。
このままでは、localfilesystem.js
内で参照している別のライブラリの依存関係が解決出来ません。
var fs = require('fs-extra'); var path = require("path"); var util = require("../../util"); var log = require("../../log"); var safeJSONStringify = require("json-stringify-safe"); var MemoryStore = require("./memory");
依存しているモジュールは、上記の通りですが、util, log, MemoryStoreはNode-RED内の別のコードなので、今は手っ取り早く、コメントアウトしましょう。 また、これらのモジュールを利用している箇所もコメントアウトしておきます。
残りのfs-extra, path, json-stringify-safeは、npmでインストールしましょう。
$ npm install --save-dev fs-extra path json-stringify-safe
Node-REDへの反映
あとは、作ったContext storeプラグインを、Node-REDに反映させるだけです。
手順は、独自ノードの開発とほぼ同じです。 Node-RED内部から、自作したモジュールをrequire出来るように、自作したモジュールへのリンクを張ります。
$ sudo npm link $ cd $HOME/.node-red $ npm link localfilesystem2
これで、Node-RED内部でlocalfilesystem2をrequire出来る状態になりました。
あとは、settings.js
を編集します。
contextStorage: { // default: { // module:"localfilesystem" // }, custom: { module:require("localfilesystem2") }, },
確認作業の時に紛らわしいので、defaultのlocalfilesystemはコメントアウトしておきました。
Node-REDを起動し、Injectノードを押してみましょう。
期待通りに、$HOME/.node-red/context
内に、コンテキストの情報が出力されている事が確認できると思います。
おわりに
Persistable contextには、他の特徴として、コンテキストの出力を同期的にも非同期的にも出来る、Changeノードだけでなくその他のノードでも利用出来る、などなどありますが、そこは割愛しました。
Node-REDの非機能面も、少しずつ拡充されていっている印象です。