JavaScript
Node.js
デザインパターン
node-red

Node-redでAPIを呼び出す際のRetry処理(デザインパターン?)

背景

Node-redで外部のAPIを呼び出すことが良くありますが、その時に相手が万が一落ちてた時に速攻失敗にするのは嫌なので、念のためループさせてます。
(あんまりダメだった事ないけど)

そこで使ってるループ処理を晒しておきます。

解説

image.png

set loop params

ループの際のパラメータを指定します。
image.png
delayはミリ秒で指定し、_retryCounterはまんまです。_okStatusCodeは、APIの戻り値がmsg.StatusCodeに入っている前提で、その値が何であればLoopをExitするかという値です。

something

お好きなAPI処理を突っ込んでください。

loop/timeout

image.png
一つめのSwitchでStatusCodeをチェック、NGならカウンター減らし、二つ目のSwitchでカウンターが残っていたら指定秒数Wait、ダメならExitします。

そのあとのOKとERRORはただの箱なので自由に使ってください。

ソースコード

[{"id":"2618b143.9cc716","type":"subflow","name":"loop/timeout","info":"入力項目:  \n  \nmsg._retryCounter  \n  as number\n  ex: 60 (times)\n  \nmsg.delay\n  as number  \n  ex: 10000 (msec)  \n  defalut, 10000(msec)  \n  \nmsg._okStatusCode  \n  as number  \n  ex: 201  \n  describe OK case's http statusCode.  \n  ","category":"","in":[{"x":620,"y":440,"wires":[{"id":"54c8269a.b1e168"}]}],"out":[{"x":880,"y":440,"wires":[{"id":"54c8269a.b1e168","port":0}]},{"x":880,"y":540,"wires":[{"id":"1fc0dbfa.0f2f2c","port":0}]},{"x":820,"y":600,"wires":[{"id":"931d7748.7ebc08","port":1}]}],"outputLabels":["OK","loop","Error"]},{"id":"54c8269a.b1e168","type":"switch","z":"2618b143.9cc716","name":"","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"_okStatusCode","vt":"msg"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":750,"y":440,"wires":[[],["2fffc6ea.8f29c2"]]},{"id":"2fffc6ea.8f29c2","type":"change","z":"2618b143.9cc716","name":"counter -1","rules":[{"t":"set","p":"_retryCounter","pt":"msg","to":"$._retryCounter - 1","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":540,"wires":[["931d7748.7ebc08"]]},{"id":"1fc0dbfa.0f2f2c","type":"delay","z":"2618b143.9cc716","name":"","pauseType":"delayv","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":740,"y":540,"wires":[[]]},{"id":"931d7748.7ebc08","type":"switch","z":"2618b143.9cc716","name":"","property":"_retryCounter","propertyType":"msg","rules":[{"t":"gt","v":"0","vt":"str"},{"t":"lte","v":"0","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":690,"y":600,"wires":[["1fc0dbfa.0f2f2c"],[]]},{"id":"2acfbeec.b22cf2","type":"change","z":"c94f016c.b5bd3","name":"set loop params","rules":[{"t":"set","p":"_retryCounter","pt":"msg","to":"60","tot":"num"},{"t":"set","p":"delay","pt":"msg","to":"2000","tot":"num"},{"t":"set","p":"_okStatusCode","pt":"msg","to":"201","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":700,"wires":[["84a18249.cfe4"]]},{"id":"84a18249.cfe4","type":"function","z":"c94f016c.b5bd3","name":"something","func":"//something\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":700,"wires":[["637a965d.e919d8"]]},{"id":"637a965d.e919d8","type":"subflow:2618b143.9cc716","z":"c94f016c.b5bd3","name":"","x":590,"y":700,"wires":[["43eb1be0.83e32c"],["84a18249.cfe4"],["2815559a.5e347a"]]},{"id":"2815559a.5e347a","type":"function","z":"c94f016c.b5bd3","name":"error","func":"\nreturn msg;","outputs":1,"noerr":0,"x":750,"y":720,"wires":[[]]},{"id":"43eb1be0.83e32c","type":"function","z":"c94f016c.b5bd3","name":"OK","func":"\nreturn msg;","outputs":1,"noerr":0,"x":750,"y":680,"wires":[[]]}]

その他

ExitはLoopが回数越えたらのみにしてありますが、StatusCodeが特定の内容であればさっさとError処理するというのを入れても良いと思います。

以上です

何かあれば突っ込んで頂けると嬉しいです。
ありがとうございます。