Help us understand the problem. What is going on with this article?

enebularでCacheを使ってフロー上で状態保持を実現する

メリークリスマス!!!(まだです)
この記事はenebular Advent Calendar 2019の5日目の記事です。

はじめに

enebularをバックエンドとして使うとき、みなさんどんな実装されてますか?
例えば状態保持だとかデータ保存とかしたくなったとき、enebularではfileのようなファイルシステムが扱えないかわりに、firebaseや/tmp上のsqliteが使えたりしますよね。
でもfirebaseは別サービスなのでgoogle側での設定が別途必要だったり、sqliteだったらSQL文の知識が必要だったりして、さくっと状態保持の実装ができる方法ってあまりないのでは? と思ってます。

そこで「Cacheノード」を使うことで、簡単な状態保持であればすぐに実現する方法がありますが、実際に使ってそうな人をあまり見かけなかったので書いてみました。

インストール

Screen Shot 2019-12-02 at 22.14.29.png

adminタブにてnode-red-contrib-cacheをインストールします。

Screen Shot 2019-12-02 at 21.00.30.png

Cache inノード、およびCache outノードがインストールされます。

基本的な使い方

Cacheノードは、簡易的なKey-Value形式のデータストアとして利用することができます。
以下のようなフローを組んでみましょう。

Screen Shot 2019-12-02 at 23.50.18.png

こちらのフローは2つのノードチェーンを持っており、
上がCache outを利用したキャッシュ内の特定のKeyへのValue書き込み、
下がCache inを利用したキャッシュ内の特定KeyからのValue読み出しを実現するものです。

Topicの指定

Screen Shot 2019-12-02 at 22.34.36.png

Cache inノードとCache outノードの両方に関して、ノードに入力するメッセージにはキーを示す文字列を設定する必要があります。ここではfunctionノードを利用して、msg.topic = "count"を指定しています。
これが指定されたメッセージをCache outに入れるとcountトピックに対する書き込み、
Cache inに入れるとcountトピックからの読み出し、という操作になります。
キーを示す文字列を格納するメッセージ要素.topicは、以下のキャッシュノードの各設定から変更できます。

*Cache inは「キャッシュへの入力(書き込み)」、Cache outは「キャッシュからの出力(読み出し)」です。

キャッシュへ書き込み(Cache in)

Screen Shot 2019-12-02 at 23.26.29.png

Cache inノードは入力しかありません。
設定項目は以下のようになっています。

  • 名前
  • キャッシュの指定(後述)
  • キープロパティ:キー名はmsgのどの要素に格納されているか
  • バリュープロパティ:キーに対する値はmsgのどの要素に格納されているか
  • TTL:ここで指定したmsgの要素内に数値が含まれていれば、デプロイ後その秒数を超えるとキャッシュがクリアされる

設定2つ目の「キャッシュの指定」は「データベースの指定」のようなもので、鉛筆マークから新たにキャッシュ追加することができます。といっても設定項目は名前ぐらいで、いくつでも作成することができます。

Screen Shot 2019-12-02 at 23.26.36.png

Default TTLは、指定しておくとデプロイ後この秒数がたつとキャッシュが自動でクリアされます。
Check Intervalはよくわかんないです。誰か教えてください。

キャッシュから読み出し(Cache out)

Screen Shot 2019-12-02 at 23.26.42.png

Cache outノードは入出力の両方を備えています。
msg.topic(設定で変更可)に読み出したいキー名を指定して入力すると、msg.payload(設定で変更可)にキー名に対応した値が格納された状態で出力されます。
設定項目は以下のようになっています。

  • 名前
  • キャッシュの設定:既存のキャッシュを選択or新規で作成もできる
  • キープロパティ:読み出したいキー名がmsgのどの要素に格納されているか
  • バリュープロパティ:読み出した値をどこに格納したいか
  • Use string payload:文字列のペイロードを利用?(詳細不明)
  • Route to the second...:出力を2系統にし、通常時は1つめの出力ポートのみに値を出力し、キーに対応する値がもうない(null)ときは2つめの出力ポートのみにnull値を出力する

使ってみる

Screen Shot 2019-12-02 at 23.29.28.png

デプロイしたら、まず上側のinjectをクリックしてみましょう。するとCacheの各ノードの下に「1」と表示が出て、データが1つだけストアされたことが確認できます。
そのあとで下側のinjectをクリックすると、先ほどストアされたtimestampがデバッグノードに出力され、デバッグタブに表示されることが確認できます。

バックエンドとしての利用例

Screen Shot 2019-12-02 at 23.50.10.png

injectをそれぞれhttpに置き換え、各ノードチェーンの末尾にhttp responseを付加するだけで、特定のURLをGETしたときのパラメータ、あるいは特定のURLに対してPOSTしたJSONを、別のURLから参照することができます。

応用例

いくつか応用例を示します。
フローは公開しておきますので、興味ある方はインポートしてご利用ください。

https://enebular.com/discover/flow/3d0dd2a4-8c92-413d-a6a4-319fb57e5660

おそらく、インポート後にエディタを開くと、Cacheノードがインストールされておらずエラーが出るかと思います。

Screen Shot 2019-12-02 at 22.23.48.png

このような場合はそのままadminタブを開いてnode-red-contrib-cacheをインストールしてください。
「Installing...」という表示が出て、インストールが完了すればそのままブラウザをリロードしてください。
いつまでもインストール中の表示が出ている場合は2〜3分ほど待ってからリロードするとインストールに成功している場合があります。うまくできないときは根気よく何回か試してみてください。

Screen Shot 2019-12-03 at 0.17.55.png

更新がうまくいくとこんな感じで復活します。

アクセスカウンタ

Screen Shot 2019-12-03 at 0.04.56.png

/counter にアクセスするたびに数値が増えていきます。カウンタ値を一度読み出して+1し、同じキーに上書きしています。

Screen Shot 2019-12-03 at 0.05.27.png

なんだかちょっと懐かしい感じですね!

JSONをストアしてくれる簡易アップローダ的なもの

Screen Shot 2019-12-03 at 0.57.38.png

/storeにapplication/jsonをPOSTすると、キャッシュ内にどんどん保存してくれます。
/getにindexパラメータつきでアクセスすると、そのindexに対応する保存済みのJSONを出力してくれます。
上記フローのままだと、POST時にストア先のindexを教えてくれないことと、index=0がnullになるという欠点があるため、若干修正したほうがよいかもしれません。

LINE風の簡易チャット

Screen Shot 2019-12-03 at 2.25.36.png

1対1のチャットも簡単に作れます。
こちらのフローでは、/meを自分のエンドポイント、/youを相手のエンドポイントとして、GETパラメータのmessageに投稿したいメッセージを指定してアクセスすると某メッセージングアプリ風のチャット画面が開くようにしてみました。

Screen Shot 2019-12-03 at 3.09.17.png

フロントはtemplateノードを使ってCSSとHTMLでがっつり作ってありますが、記事の主旨と離れますので公開されているフローをインポートして直接確認してみてください。
バックエンドとしては、アクセスがあるたびに投稿されたメッセージを読み取り、キャッシュからログを読み出し、htmlタグで囲んだメッセージをログの末尾に追記し、そのログをまたキャッシュの同じ場所に保存する、という流れとなっています。
アクセスカウンタの文字列版みたいな感じですね。

まとめ

外部サービスに頼ったり、SQLのような追加知識を必要とすることなく、データの簡易保存ができました!
しかしもちろん、使っている人がほぼいないということは、良いところばかりではないということで……

利点

  • enebularだけでデータ保存が実現できる
  • Key-Value形式でシンプルにJSONオブジェクトが保存できる
  • SQLiteのようにSQL文を直接書いたりしなくてもよい

欠点

  • 「キーを示す文字列が入ったmsgの要素」を指定する必要があり、ややこしい
  • デプロイしなおすと中身がすべてクリアされてしまう
  • フローを再読み込みしたときにアンインストールされた状態になってしまうことがある

以上の点をふまえると、データストアが必要だけどさくっとバックエンド組みたい! なんてときに最適なのではないでしょうか。
ハッカソンのように短時間でプロトタイプを作るときなどに向いているかもしれません。
こんな感じで少しクセのあるCacheノードですが、ぜひとも活用してみてくださいね〜。

ukk0
宗教上の理由でアドベントカレンダー以外はQiita執筆しません。弊記事を読みたいという酔狂なかたはこちらへ → https://xor.hateblo.jp/
https://twitter.com/ukokq
dotstudio
全ての人がモノづくりを楽しむ世界を目指して活動しています。
https://dotstud.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした