Sync req/res REST API with async workers based on MQTT (sequential and parallel workers)
Example implements two REST API endpoins to show example design for sequential and parallel flows. Please open issue if you find a bug or contact me if you have questions, you can find me on Node-RED slack.
Requirements
- node-red-contrib-uuid
- node-red-contrib-digitaloak-mqtt
Support & Discussion
Please join: https://riot.digitaloak.it/#/room/#node-red_sync-rest-with-async-workers:digitaloak.it
[{"id":"3b604b1e.85a704","type":"tab","label":"Sync req/res REST API with async workers","disabled":false,"info":""},{"id":"615e2815.fe6b28","type":"inject","z":"3b604b1e.85a704","name":"POST /users","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":100,"wires":[["6ae5b4b6.e9866c"]]},{"id":"6ae5b4b6.e9866c","type":"change","z":"3b604b1e.85a704","name":"Create CreateUser Request Object","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"name\":\"takeshi\",\"password\":\"osaka1!S\",\"e-mail\":\"[email protected]\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":100,"wires":[["214e6456.caabfc"]]},{"id":"214e6456.caabfc","type":"http request","z":"3b604b1e.85a704","name":"POST /users","method":"POST","ret":"obj","paytoqs":false,"url":"http://localhost:1880/users","tls":"","proxy":"","authType":"","x":670,"y":100,"wires":[["c134bd15.7d5b9"]]},{"id":"c134bd15.7d5b9","type":"debug","z":"3b604b1e.85a704","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":830,"y":100,"wires":[]},{"id":"330df9a6.41dd06","type":"comment","z":"3b604b1e.85a704","name":"Make REST API request - sync single","info":"","x":190,"y":40,"wires":[]},{"id":"5c4be087.2d837","type":"comment","z":"3b604b1e.85a704","name":"API","info":"","x":90,"y":160,"wires":[]},{"id":"c5746554.9f2318","type":"http in","z":"3b604b1e.85a704","name":"","url":"/users","method":"post","upload":false,"swaggerDoc":"","x":150,"y":220,"wires":[["cf71b6ac.cd8de8"]]},{"id":"cf71b6ac.cd8de8","type":"uuid","z":"3b604b1e.85a704","uuidVersion":"v1","namespaceType":"","namespace":"","namespaceCustom":"","name":"Generate Unique Request Id","field":"request_id","fieldType":"msg","x":380,"y":220,"wires":[["346da67d.9c73ba"]]},{"id":"346da67d.9c73ba","type":"change","z":"3b604b1e.85a704","name":"Create Job Object","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"operationId\": \"CreateUser\",\t \"data\": msg.payload,\t \"meta\": {\t \"request_id\": msg.request_id\t }\t}","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"request_id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":220,"wires":[["ebb18221.702d6","29137468.cfa81c"]]},{"id":"ebb18221.702d6","type":"change","z":"3b604b1e.85a704","name":"Set Publish Topic to Validation Service","rules":[{"t":"set","p":"topic","pt":"msg","to":"validation","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":280,"wires":[["f2a9065a.f7f298"]]},{"id":"f2a9065a.f7f298","type":"mqtt out","z":"3b604b1e.85a704","name":"Publish Job to Validation Service (Validate Request Schema)","topic":"validation","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":1320,"y":280,"wires":[]},{"id":"223cb877.2624b8","type":"switch","z":"3b604b1e.85a704","name":"Is Valid?","property":"payload.error","propertyType":"msg","rules":[{"t":"istype","v":"undefined","vt":"undefined"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":1440,"y":220,"wires":[["f11e7bf.f951b88","72db496b.97a278"],["745f60b4.ae80e"]]},{"id":"f11e7bf.f951b88","type":"function","z":"3b604b1e.85a704","name":"Get Job Object","func":"msg.payload = flow.get(msg.topic).job_object;\nreturn msg;","outputs":1,"noerr":0,"x":1620,"y":100,"wires":[["e4f5e442.da0fb8"]],"info":"Data sent by client to this REST endpoint"},{"id":"cabbe3cf.62994","type":"switch","z":"3b604b1e.85a704","name":"Is User Created?","property":"payload.error","propertyType":"msg","rules":[{"t":"istype","v":"undefined","vt":"undefined"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":1950,"y":180,"wires":[["6053bde2.928ef4"],["a660f365.31e76"]]},{"id":"e4f5e442.da0fb8","type":"change","z":"3b604b1e.85a704","name":"Set Publish Topic to Database Service","rules":[{"t":"set","p":"topic","pt":"msg","to":"database-service","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1890,"y":100,"wires":[["3651cbe1.8f7ad4"]]},{"id":"745f60b4.ae80e","type":"change","z":"3b604b1e.85a704","name":"Create CreateUserFailed Response Object","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"error\": msg.payload.error\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1730,"y":260,"wires":[["7dd96fdc.52652"]]},{"id":"6053bde2.928ef4","type":"change","z":"3b604b1e.85a704","name":"Create UserCreated Response Object","rules":[{"t":"set","p":"payload.result","pt":"msg","to":"{\"Id\":12332}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":2210,"y":160,"wires":[["cdcf2d0c.c18aa"]]},{"id":"a660f365.31e76","type":"change","z":"3b604b1e.85a704","name":"Create CreateUserFailed Response Object","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"result\":\"Database error\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":2230,"y":200,"wires":[["2053b721.6b07d8"]]},{"id":"3651cbe1.8f7ad4","type":"mqtt out","z":"3b604b1e.85a704","name":"Publish Job to Database Service (Save User)","topic":"database","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":2250,"y":100,"wires":[]},{"id":"7dd96fdc.52652","type":"function","z":"3b604b1e.85a704","name":"Get Response Object","func":"msg.res = flow.get(msg.topic).req_res;\nflow.set(msg.topic,undefined);\nreturn msg;","outputs":1,"noerr":0,"x":2020,"y":260,"wires":[["37f721b5.9fa38e"]]},{"id":"cdcf2d0c.c18aa","type":"function","z":"3b604b1e.85a704","name":"Get Response Object","func":"msg.res = flow.get(msg.topic).req_res;\nflow.set(msg.topic,undefined);\nreturn msg;","outputs":1,"noerr":0,"x":2500,"y":160,"wires":[["9c664b17.e94668"]]},{"id":"2053b721.6b07d8","type":"function","z":"3b604b1e.85a704","name":"Get Response Object","func":"msg.res = flow.get(msg.topic).req_res;\nflow.set(msg.topic,undefined);\nreturn msg;","outputs":1,"noerr":0,"x":2540,"y":200,"wires":[["a76ebe1a.5793e"]]},{"id":"37f721b5.9fa38e","type":"http response","z":"3b604b1e.85a704","name":"Anwer to Client (422)","statusCode":"422","headers":{},"x":2260,"y":260,"wires":[]},{"id":"9c664b17.e94668","type":"http response","z":"3b604b1e.85a704","name":"UserCreated (201)","statusCode":"201","headers":{},"x":2730,"y":160,"wires":[]},{"id":"a76ebe1a.5793e","type":"http response","z":"3b604b1e.85a704","name":"CreateUserField (400)","statusCode":"400","headers":{},"x":2780,"y":200,"wires":[]},{"id":"7577009d.8a597","type":"comment","z":"3b604b1e.85a704","name":"Workers","info":"","x":100,"y":360,"wires":[]},{"id":"3256bbc1.6c81e4","type":"mqtt in","z":"3b604b1e.85a704","name":"","topic":"$share/service/validation","qos":"2","datatype":"json","broker":"b4b33d11.75535","x":170,"y":460,"wires":[["771aa1e1.46a35"]]},{"id":"a9adbbdd.6e9878","type":"change","z":"3b604b1e.85a704","name":"Create Response Object & Set Topic to Publish to <req_id>","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"id\":4423\t}","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"job_object.meta.request_id","tot":"msg"},{"t":"set","p":"payload.error","pt":"msg","to":"schemaError","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1180,"y":440,"wires":[["2ee9876a.f6abb8"]]},{"id":"2ee9876a.f6abb8","type":"mqtt out","z":"3b604b1e.85a704","name":"<request_id>","topic":"","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":1510,"y":440,"wires":[]},{"id":"771aa1e1.46a35","type":"switch","z":"3b604b1e.85a704","name":"","property":"payload.operationId","propertyType":"msg","rules":[{"t":"eq","v":"CreateUser","vt":"str"},{"t":"eq","v":"UpdateUserPassword","vt":"str"},{"t":"eq","v":"ActivateUser","vt":"str"},{"t":"eq","v":"DeactivateUser","vt":"str"},{"t":"eq","v":"ResetPassword","vt":"str"},{"t":"eq","v":"DeleteUser","vt":"str"},{"t":"eq","v":"UpdateUserEmail","vt":"str"}],"checkall":"false","repair":false,"outputs":7,"x":370,"y":460,"wires":[["78109cca.7d2724"],[],[],[],[],[],[]]},{"id":"84d651ba.c5e15","type":"switch","z":"3b604b1e.85a704","name":"","property":"payload.operationId","propertyType":"msg","rules":[{"t":"eq","v":"CreateUser","vt":"str"},{"t":"eq","v":"DeleteUser","vt":"str"},{"t":"eq","v":"UpdateUserPassword","vt":"str"}],"checkall":"false","repair":false,"outputs":3,"x":370,"y":640,"wires":[["32b61e2.cca58e2"],[],[]]},{"id":"32b61e2.cca58e2","type":"delay","z":"3b604b1e.85a704","name":"Writing User to Database","pauseType":"random","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"2","randomUnits":"seconds","drop":false,"x":570,"y":640,"wires":[["ee4d607c.ae8c4"]]},{"id":"21bb454d.6ab28a","type":"mqtt out","z":"3b604b1e.85a704","name":"<request_id>","topic":"","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":1270,"y":640,"wires":[]},{"id":"6ca9b89d.067128","type":"mqtt in","z":"3b604b1e.85a704","name":"","topic":"$share/service/database","qos":"2","datatype":"json","broker":"71939770.266178","x":170,"y":640,"wires":[["84d651ba.c5e15"]]},{"id":"fe81c767.27b678","type":"comment","z":"3b604b1e.85a704","name":"Make REST API request - sync parallel","info":"","x":190,"y":880,"wires":[]},{"id":"3b872b54.22b3d4","type":"inject","z":"3b604b1e.85a704","name":"POST /dothemath","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":940,"wires":[["c419c402.7a7ba8"]]},{"id":"c419c402.7a7ba8","type":"change","z":"3b604b1e.85a704","name":"Create DoTheMath Request Object","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"numbers\":[{\"number\":1,\"multiplyBy\":3},{\"number\":3,\"multiplyBy\":11},{\"number\":44,\"multiplyBy\":34},{\"number\":4,\"multiplyBy\":666},{\"number\":55,\"multiplyBy\":4},{\"number\":35,\"multiplyBy\":563},{\"number\":12,\"multiplyBy\":42},{\"number\":111,\"multiplyBy\":22},{\"number\":75,\"multiplyBy\":1}]}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":940,"wires":[["91d314dd.0935c8"]]},{"id":"91d314dd.0935c8","type":"http request","z":"3b604b1e.85a704","name":"/dothemath","method":"POST","ret":"obj","paytoqs":false,"url":"http://localhost:1880/dothemath","tls":"","proxy":"","authType":"","x":710,"y":940,"wires":[["867551a7.f8e22"]]},{"id":"867551a7.f8e22","type":"debug","z":"3b604b1e.85a704","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":870,"y":940,"wires":[]},{"id":"87042921.bdcb28","type":"comment","z":"3b604b1e.85a704","name":"API","info":"","x":90,"y":1000,"wires":[]},{"id":"7c7136fa.842c88","type":"http in","z":"3b604b1e.85a704","name":"","url":"/dothemath","method":"post","upload":false,"swaggerDoc":"","x":170,"y":1060,"wires":[["d02bb256.ed74a"]]},{"id":"d02bb256.ed74a","type":"uuid","z":"3b604b1e.85a704","uuidVersion":"v1","namespaceType":"","namespace":"","namespaceCustom":"","name":"Generate Unique Request Id","field":"request_id","fieldType":"msg","x":420,"y":1060,"wires":[["e865746.aa85888","ede17222.cb486"]]},{"id":"e865746.aa85888","type":"function","z":"3b604b1e.85a704","name":"Store HTTP Response Object","func":"\nflow.set(msg.request_id, {\"job_object\":msg.payload, \"req_res\":msg.res} );\nmsg.topic = msg.request_id;\nreturn msg;","outputs":1,"noerr":0,"x":710,"y":1060,"wires":[["f94926a5.5426c8"]]},{"id":"a9dc04ef.394148","type":"mqtt out","z":"3b604b1e.85a704","name":"Publish Job to Math Service (Multiply Numbers)","topic":"","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":1540,"y":1120,"wires":[]},{"id":"d670c0e2.7f10d","type":"mqtt in","z":"3b604b1e.85a704","name":"","topic":"$share/service/math","qos":"2","datatype":"json","broker":"b4b33d11.75535","x":170,"y":1280,"wires":[["5fb49640.d126b8"]]},{"id":"5fb49640.d126b8","type":"switch","z":"3b604b1e.85a704","name":"","property":"payload.operationId","propertyType":"msg","rules":[{"t":"eq","v":"DoTheMath","vt":"str"}],"checkall":"false","repair":false,"outputs":1,"x":350,"y":1280,"wires":[["86a2b81f.46b1d8"]]},{"id":"86a2b81f.46b1d8","type":"change","z":"3b604b1e.85a704","name":"Create Response Object & Set Topic to Publish to <req_id>","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.meta.request_id","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{\t \"data\": {\t \"number\": msg.payload.data.number,\t \"multiplyBy\":msg.payload.data.multiplyBy,\t \"result\": msg.payload.data.number * msg.payload.data.multiplyBy\t },\t \"meta\": {\t \"parts\":msg.payload.meta.parts\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1280,"wires":[["5f5e2f0d.317dc"]]},{"id":"5f5e2f0d.317dc","type":"mqtt out","z":"3b604b1e.85a704","name":"<request_id>","topic":"","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":990,"y":1280,"wires":[]},{"id":"72e54756.c09408","type":"http response","z":"3b604b1e.85a704","name":"DidTheMath (200)","statusCode":"200","headers":{},"x":2430,"y":1060,"wires":[]},{"id":"cb2d61cd.61114","type":"function","z":"3b604b1e.85a704","name":"Get Response Object & Delete Meta Property","func":"msg.res = flow.get(msg.topic).req_res;\nflow.set(msg.topic,undefined);\n\nfor (let i = 0; i<msg.payload.length; i++) {\n console.log(msg.payload[i].meta);\n msg.payload[i].meta = undefined;\n}\nreturn msg;","outputs":1,"noerr":0,"x":1780,"y":1060,"wires":[["6a6ee1da.b1d81"]]},{"id":"c36fa6f5.8c49c8","type":"change","z":"3b604b1e.85a704","name":"Create Job Object & Set Topic to Subscribe","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"operationId\": \"DoTheMath\",\t \"data\": msg.payload,\t \"meta\": {\t \"request_id\": msg.request_id,\t \"parts\":msg.parts\t }\t}","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"math","tot":"str"},{"t":"delete","p":"req","pt":"msg"},{"t":"delete","p":"res","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1150,"y":1120,"wires":[["a9dc04ef.394148"]]},{"id":"3fd23e6f.e22842","type":"split","z":"3b604b1e.85a704","name":"Split","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":890,"y":1120,"wires":[["c36fa6f5.8c49c8"]]},{"id":"ede17222.cb486","type":"change","z":"3b604b1e.85a704","name":"Reassign Request Data","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.numbers","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":1120,"wires":[["3fd23e6f.e22842"]]},{"id":"7e72f959.054568","type":"join","z":"3b604b1e.85a704","name":"Join Parts into Array","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1440,"y":1060,"wires":[["ff922624.5344d8","cb2d61cd.61114"]]},{"id":"b7c7fe48.f0b1c","type":"change","z":"3b604b1e.85a704","name":"Collect Parts","rules":[{"t":"set","p":"parts","pt":"msg","to":"payload.meta.parts","tot":"msg"},{"t":"delete","p":"meta","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1230,"y":1060,"wires":[["7e72f959.054568"]]},{"id":"5a7cc528.38d0bc","type":"mqtt out","z":"3b604b1e.85a704","name":"Unsubscribe from Math Service","topic":"","qos":"","retain":"","broker":"311f12a4.3d2b9e","x":2010,"y":980,"wires":[]},{"id":"ff922624.5344d8","type":"change","z":"3b604b1e.85a704","name":"Set Command _unsubscribe","rules":[{"t":"set","p":"payload","pt":"msg","to":"_unsubscribe:Wait for Math Service Result","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1720,"y":980,"wires":[["5a7cc528.38d0bc"]]},{"id":"edffca90.34f6e8","type":"mqtt in","z":"3b604b1e.85a704","name":"","topic":"$share/service/math","qos":"2","datatype":"json","broker":"71939770.266178","x":170,"y":1400,"wires":[["35b72250.7fd8be"]]},{"id":"35b72250.7fd8be","type":"switch","z":"3b604b1e.85a704","name":"","property":"payload.operationId","propertyType":"msg","rules":[{"t":"eq","v":"DoTheMath","vt":"str"}],"checkall":"false","repair":false,"outputs":1,"x":350,"y":1400,"wires":[["67d21bd.64cd6e4"]]},{"id":"67d21bd.64cd6e4","type":"change","z":"3b604b1e.85a704","name":"Create Response Object & Set Topic to Publish to <req_id>","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.meta.request_id","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{\t \"data\": {\t \"number\": msg.payload.data.number,\t \"multiplyBy\":msg.payload.data.multiplyBy,\t \"result\": msg.payload.data.number * msg.payload.data.multiplyBy\t },\t \"meta\": {\t \"parts\":msg.payload.meta.parts\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1400,"wires":[["9477994f.e68f18"]]},{"id":"9477994f.e68f18","type":"mqtt out","z":"3b604b1e.85a704","name":"<request_id>","topic":"","qos":"2","retain":"","broker":"311f12a4.3d2b9e","x":990,"y":1400,"wires":[]},{"id":"889d9035.a6263","type":"digitaloak-mqtt-in","z":"3b604b1e.85a704","name":"Wait for Validation Service Result","qos":"2","datatype":"json","unsubscribe-after-first-msg-recv":true,"broker":"311f12a4.3d2b9e","x":1200,"y":220,"wires":[["223cb877.2624b8"]]},{"id":"78109cca.7d2724","type":"change","z":"3b604b1e.85a704","name":"Set Schema Validation","rules":[{"t":"set","p":"schema","pt":"msg","to":"{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"title\":\"CreateUser-RequestSchema\",\"type\":\"object\",\"required\":[\"e-mail\",\"password\",\"name\"],\"properties\":{\"name\":{\"type\":\"string\",\"minLength\":3},\"e-mail\":{\"type\":\"string\",\"format\":\"email\"},\"password\":{\"type\":\"string\",\"minLength\":8,\"pattern\":\"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\\\d)(?=.*[$@#!%*?&])[A-Za-z\\\\d$@$!%*?&]\"}},\"additionalProperties\":false}","tot":"json"},{"t":"set","p":"job_object","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"job_object.data","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":440,"wires":[["e3ff3427.0081c8"]]},{"id":"e3ff3427.0081c8","type":"json","z":"3b604b1e.85a704","name":"Validate Request Schema","property":"payload","action":"","pretty":false,"x":810,"y":440,"wires":[["a9adbbdd.6e9878"]]},{"id":"f91010c6.06dbb","type":"catch","z":"3b604b1e.85a704","name":"Catch Schema Validation Error","scope":["e3ff3427.0081c8"],"uncaught":false,"x":790,"y":480,"wires":[["a9adbbdd.6e9878"]]},{"id":"29137468.cfa81c","type":"function","z":"3b604b1e.85a704","name":"Store HTTP Response Object","func":"flow.set(msg.request_id, {\"job_object\":msg.payload, \"req_res\":msg.res} );\nreturn msg;","outputs":1,"noerr":0,"x":890,"y":220,"wires":[["889d9035.a6263"]]},{"id":"ee4d607c.ae8c4","type":"change","z":"3b604b1e.85a704","name":"Create Response Object & Set Topic to Publish to <req_id>","rules":[{"t":"set","p":"job_data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"job_data.meta.request_id","tot":"msg"},{"t":"set","p":"payload.error","pt":"msg","to":"error","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":940,"y":640,"wires":[["21bb454d.6ab28a"]]},{"id":"72db496b.97a278","type":"digitaloak-mqtt-in","z":"3b604b1e.85a704","name":"Wait for Database Service Result","qos":"2","datatype":"json","unsubscribe-after-first-msg-recv":true,"broker":"311f12a4.3d2b9e","x":1700,"y":180,"wires":[["cabbe3cf.62994"]]},{"id":"f94926a5.5426c8","type":"digitaloak-mqtt-in","z":"3b604b1e.85a704","name":"Wait for Math Service Result","qos":"2","datatype":"json","unsubscribe-after-first-msg-recv":false,"broker":"311f12a4.3d2b9e","x":1000,"y":1060,"wires":[["b7c7fe48.f0b1c"]]},{"id":"6a6ee1da.b1d81","type":"change","z":"3b604b1e.85a704","name":"Create DoTheMath Resopnse Object","rules":[{"t":"set","p":"data","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.result","pt":"msg","to":"data","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":2150,"y":1060,"wires":[["72e54756.c09408"]]},{"id":"311f12a4.3d2b9e","type":"mqtt-broker","z":"","name":"MQTT 1","broker":"mqtt","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"b4b33d11.75535","type":"mqtt-broker","z":"","name":"MQTT Service 1","broker":"mqtt","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"71939770.266178","type":"mqtt-broker","z":"","name":"MQTT Service 2","broker":"mqtt","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]