@alwaysai/device-agent 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/lib/application-control/config.d.ts.map +1 -1
  2. package/lib/application-control/config.js +10 -5
  3. package/lib/application-control/config.js.map +1 -1
  4. package/lib/application-control/environment-variables.d.ts +1 -5
  5. package/lib/application-control/environment-variables.d.ts.map +1 -1
  6. package/lib/application-control/environment-variables.js +9 -26
  7. package/lib/application-control/environment-variables.js.map +1 -1
  8. package/lib/application-control/environment-variables.test.js +27 -7
  9. package/lib/application-control/environment-variables.test.js.map +1 -1
  10. package/lib/application-control/index.d.ts +4 -4
  11. package/lib/application-control/index.d.ts.map +1 -1
  12. package/lib/application-control/index.js +1 -4
  13. package/lib/application-control/index.js.map +1 -1
  14. package/lib/application-control/install.d.ts.map +1 -1
  15. package/lib/application-control/install.js +9 -7
  16. package/lib/application-control/install.js.map +1 -1
  17. package/lib/application-control/models.d.ts +5 -11
  18. package/lib/application-control/models.d.ts.map +1 -1
  19. package/lib/application-control/models.js +27 -64
  20. package/lib/application-control/models.js.map +1 -1
  21. package/lib/application-control/status.d.ts.map +1 -1
  22. package/lib/application-control/status.js +10 -12
  23. package/lib/application-control/status.js.map +1 -1
  24. package/lib/application-control/utils.d.ts +0 -4
  25. package/lib/application-control/utils.d.ts.map +1 -1
  26. package/lib/application-control/utils.js +3 -26
  27. package/lib/application-control/utils.js.map +1 -1
  28. package/lib/cloud-connection/bootstrap-provision.js +3 -2
  29. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  30. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +11 -16
  31. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  32. package/lib/cloud-connection/device-agent-cloud-connection.js +295 -246
  33. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  34. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  35. package/lib/cloud-connection/device-agent.js +11 -9
  36. package/lib/cloud-connection/device-agent.js.map +1 -1
  37. package/lib/cloud-connection/live-updates-handler.d.ts +18 -27
  38. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  39. package/lib/cloud-connection/live-updates-handler.js +58 -170
  40. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  41. package/lib/cloud-connection/live-updates-handler.test.js +76 -54
  42. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  43. package/lib/cloud-connection/passthrough-handler.d.ts +9 -4
  44. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  45. package/lib/cloud-connection/passthrough-handler.js +95 -62
  46. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  47. package/lib/cloud-connection/shadow-handler.d.ts +5 -1
  48. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  49. package/lib/cloud-connection/shadow-handler.js +63 -31
  50. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  51. package/lib/cloud-connection/shadow-handler.test.js +45 -57
  52. package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
  53. package/lib/cloud-connection/shadow.d.ts.map +1 -1
  54. package/lib/cloud-connection/shadow.js +2 -1
  55. package/lib/cloud-connection/shadow.js.map +1 -1
  56. package/lib/cloud-connection/transaction-manager.d.ts +7 -2
  57. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  58. package/lib/cloud-connection/transaction-manager.js +29 -29
  59. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  60. package/lib/cloud-connection/transaction-manager.test.js +105 -3
  61. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  62. package/lib/device-control/device-control.d.ts +14 -6
  63. package/lib/device-control/device-control.d.ts.map +1 -1
  64. package/lib/device-control/device-control.js +172 -72
  65. package/lib/device-control/device-control.js.map +1 -1
  66. package/lib/docker/docker-compose.d.ts +14 -0
  67. package/lib/docker/docker-compose.d.ts.map +1 -0
  68. package/lib/docker/docker-compose.js +57 -0
  69. package/lib/docker/docker-compose.js.map +1 -0
  70. package/lib/index.js +2 -5
  71. package/lib/index.js.map +1 -1
  72. package/lib/infrastructure/agent-config.d.ts +46 -14
  73. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  74. package/lib/infrastructure/agent-config.js +36 -21
  75. package/lib/infrastructure/agent-config.js.map +1 -1
  76. package/lib/infrastructure/agent-config.test.js +6 -1
  77. package/lib/infrastructure/agent-config.test.js.map +1 -1
  78. package/lib/infrastructure/config-check-utility.d.ts +6 -0
  79. package/lib/infrastructure/config-check-utility.d.ts.map +1 -0
  80. package/lib/infrastructure/config-check-utility.js +67 -0
  81. package/lib/infrastructure/config-check-utility.js.map +1 -0
  82. package/lib/infrastructure/config-check-utility.test.d.ts +2 -0
  83. package/lib/infrastructure/config-check-utility.test.d.ts.map +1 -0
  84. package/lib/infrastructure/config-check-utility.test.js +109 -0
  85. package/lib/infrastructure/config-check-utility.test.js.map +1 -0
  86. package/lib/infrastructure/device-certificate.d.ts +10 -0
  87. package/lib/infrastructure/device-certificate.d.ts.map +1 -0
  88. package/lib/infrastructure/device-certificate.js +47 -0
  89. package/lib/infrastructure/device-certificate.js.map +1 -0
  90. package/lib/infrastructure/device-certificate.test.d.ts +2 -0
  91. package/lib/infrastructure/device-certificate.test.d.ts.map +1 -0
  92. package/lib/infrastructure/device-certificate.test.js +24 -0
  93. package/lib/infrastructure/device-certificate.test.js.map +1 -0
  94. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts +2 -0
  95. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts.map +1 -0
  96. package/lib/infrastructure/legacy-migration/legacy-file.test.js +61 -0
  97. package/lib/infrastructure/legacy-migration/legacy-file.test.js.map +1 -0
  98. package/lib/infrastructure/legacy-migration/legacy-files.d.ts +75 -0
  99. package/lib/infrastructure/legacy-migration/legacy-files.d.ts.map +1 -0
  100. package/lib/infrastructure/legacy-migration/legacy-files.js +75 -0
  101. package/lib/infrastructure/legacy-migration/legacy-files.js.map +1 -0
  102. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts +6 -0
  103. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts.map +1 -0
  104. package/lib/infrastructure/legacy-migration/legacy-migration.js +149 -0
  105. package/lib/infrastructure/legacy-migration/legacy-migration.js.map +1 -0
  106. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts +2 -0
  107. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts.map +1 -0
  108. package/lib/infrastructure/legacy-migration/legacy-migration.test.js +226 -0
  109. package/lib/infrastructure/legacy-migration/legacy-migration.test.js.map +1 -0
  110. package/lib/infrastructure/require-files-present-ready.test.d.ts +2 -0
  111. package/lib/infrastructure/require-files-present-ready.test.d.ts.map +1 -0
  112. package/lib/infrastructure/require-files-present-ready.test.js +44 -0
  113. package/lib/infrastructure/require-files-present-ready.test.js.map +1 -0
  114. package/lib/infrastructure/required-config-checks.d.ts +2 -0
  115. package/lib/infrastructure/required-config-checks.d.ts.map +1 -0
  116. package/lib/infrastructure/required-config-checks.js +30 -0
  117. package/lib/infrastructure/required-config-checks.js.map +1 -0
  118. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  119. package/lib/infrastructure/tokens-and-device-cfg.js +11 -8
  120. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  121. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
  122. package/lib/local-connection/rabbitmq-connection.js +21 -21
  123. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  124. package/lib/secure-tunneling/secure-tunneling.d.ts +15 -23
  125. package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
  126. package/lib/secure-tunneling/secure-tunneling.js +52 -47
  127. package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
  128. package/lib/secure-tunneling/secure-tunneling.test.js +29 -31
  129. package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
  130. package/lib/subcommands/app/analytics.d.ts.map +1 -1
  131. package/lib/subcommands/app/analytics.js +1 -2
  132. package/lib/subcommands/app/analytics.js.map +1 -1
  133. package/lib/subcommands/app/env-vars.d.ts +4 -0
  134. package/lib/subcommands/app/env-vars.d.ts.map +1 -1
  135. package/lib/subcommands/app/env-vars.js +52 -6
  136. package/lib/subcommands/app/env-vars.js.map +1 -1
  137. package/lib/subcommands/app/index.d.ts.map +1 -1
  138. package/lib/subcommands/app/index.js +1 -3
  139. package/lib/subcommands/app/index.js.map +1 -1
  140. package/lib/subcommands/app/models.d.ts +0 -11
  141. package/lib/subcommands/app/models.d.ts.map +1 -1
  142. package/lib/subcommands/app/models.js +2 -58
  143. package/lib/subcommands/app/models.js.map +1 -1
  144. package/lib/subcommands/app/shadow.d.ts.map +1 -1
  145. package/lib/subcommands/app/shadow.js +6 -5
  146. package/lib/subcommands/app/shadow.js.map +1 -1
  147. package/lib/subcommands/app/version.d.ts.map +1 -1
  148. package/lib/subcommands/app/version.js +2 -4
  149. package/lib/subcommands/app/version.js.map +1 -1
  150. package/lib/subcommands/config.d.ts +2 -0
  151. package/lib/subcommands/config.d.ts.map +1 -0
  152. package/lib/subcommands/config.js +39 -0
  153. package/lib/subcommands/config.js.map +1 -0
  154. package/lib/subcommands/device/clean.d.ts +1 -1
  155. package/lib/subcommands/device/clean.d.ts.map +1 -1
  156. package/lib/subcommands/device/clean.js +25 -15
  157. package/lib/subcommands/device/clean.js.map +1 -1
  158. package/lib/subcommands/device/get-info.d.ts +2 -0
  159. package/lib/subcommands/device/get-info.d.ts.map +1 -0
  160. package/lib/subcommands/device/get-info.js +36 -0
  161. package/lib/subcommands/device/get-info.js.map +1 -0
  162. package/lib/subcommands/device/index.d.ts.map +1 -1
  163. package/lib/subcommands/device/index.js +13 -2
  164. package/lib/subcommands/device/index.js.map +1 -1
  165. package/lib/subcommands/device/init.d.ts +5 -0
  166. package/lib/subcommands/device/init.d.ts.map +1 -0
  167. package/lib/subcommands/device/{device.js → init.js} +10 -49
  168. package/lib/subcommands/device/init.js.map +1 -0
  169. package/lib/subcommands/device/migrate.d.ts +2 -0
  170. package/lib/subcommands/device/migrate.d.ts.map +1 -0
  171. package/lib/subcommands/device/migrate.js +24 -0
  172. package/lib/subcommands/device/migrate.js.map +1 -0
  173. package/lib/subcommands/device/refresh.d.ts +2 -0
  174. package/lib/subcommands/device/refresh.d.ts.map +1 -0
  175. package/lib/subcommands/device/refresh.js +25 -0
  176. package/lib/subcommands/device/refresh.js.map +1 -0
  177. package/lib/subcommands/device/restart.d.ts +2 -0
  178. package/lib/subcommands/device/restart.d.ts.map +1 -0
  179. package/lib/subcommands/device/restart.js +14 -0
  180. package/lib/subcommands/device/restart.js.map +1 -0
  181. package/lib/subcommands/index.d.ts +1 -1
  182. package/lib/subcommands/index.d.ts.map +1 -1
  183. package/lib/subcommands/index.js +3 -1
  184. package/lib/subcommands/index.js.map +1 -1
  185. package/lib/subcommands/rabbitmq-connection.d.ts +1 -1
  186. package/lib/subcommands/rabbitmq-connection.d.ts.map +1 -1
  187. package/lib/util/aai-error.d.ts +12 -0
  188. package/lib/util/aai-error.d.ts.map +1 -0
  189. package/lib/util/aai-error.js +11 -0
  190. package/lib/util/aai-error.js.map +1 -0
  191. package/lib/util/aws-regions.d.ts +2 -0
  192. package/lib/util/aws-regions.d.ts.map +1 -0
  193. package/lib/util/{cloud-mode-ready.js → aws-regions.js} +2 -20
  194. package/lib/util/aws-regions.js.map +1 -0
  195. package/lib/util/check-for-updates.d.ts +3 -0
  196. package/lib/util/check-for-updates.d.ts.map +1 -0
  197. package/lib/util/check-for-updates.js +46 -0
  198. package/lib/util/check-for-updates.js.map +1 -0
  199. package/lib/util/clean-certs.d.ts.map +1 -1
  200. package/lib/util/clean-certs.js +5 -4
  201. package/lib/util/clean-certs.js.map +1 -1
  202. package/lib/util/directories.d.ts +4 -18
  203. package/lib/util/directories.d.ts.map +1 -1
  204. package/lib/util/directories.js +18 -32
  205. package/lib/util/directories.js.map +1 -1
  206. package/lib/util/file.d.ts +11 -0
  207. package/lib/util/file.d.ts.map +1 -0
  208. package/lib/util/file.js +127 -0
  209. package/lib/util/file.js.map +1 -0
  210. package/lib/util/file.test.d.ts +2 -0
  211. package/lib/util/file.test.d.ts.map +1 -0
  212. package/lib/util/file.test.js +87 -0
  213. package/lib/util/file.test.js.map +1 -0
  214. package/lib/util/get-device-id.d.ts.map +1 -1
  215. package/lib/util/get-device-id.js +7 -1
  216. package/lib/util/get-device-id.js.map +1 -1
  217. package/lib/util/http-client.js +3 -3
  218. package/lib/util/http-client.js.map +1 -1
  219. package/package.json +22 -19
  220. package/readme.md +15 -35
  221. package/src/application-control/config.ts +10 -13
  222. package/src/application-control/environment-variables.test.ts +28 -7
  223. package/src/application-control/environment-variables.ts +13 -40
  224. package/src/application-control/index.ts +3 -16
  225. package/src/application-control/install.ts +16 -10
  226. package/src/application-control/models.ts +40 -98
  227. package/src/application-control/status.ts +9 -7
  228. package/src/application-control/utils.ts +1 -29
  229. package/src/cloud-connection/bootstrap-provision.ts +7 -7
  230. package/src/cloud-connection/device-agent-cloud-connection.ts +647 -509
  231. package/src/cloud-connection/device-agent.ts +16 -7
  232. package/src/cloud-connection/live-updates-handler.test.ts +137 -64
  233. package/src/cloud-connection/live-updates-handler.ts +103 -234
  234. package/src/cloud-connection/passthrough-handler.ts +134 -75
  235. package/src/cloud-connection/shadow-handler.test.ts +45 -57
  236. package/src/cloud-connection/shadow-handler.ts +114 -56
  237. package/src/cloud-connection/shadow.ts +4 -1
  238. package/src/cloud-connection/transaction-manager.test.ts +127 -3
  239. package/src/cloud-connection/transaction-manager.ts +68 -39
  240. package/src/device-control/device-control.ts +179 -72
  241. package/src/docker/docker-compose.ts +61 -0
  242. package/src/index.ts +2 -6
  243. package/src/infrastructure/agent-config.test.ts +9 -2
  244. package/src/infrastructure/agent-config.ts +45 -46
  245. package/src/infrastructure/config-check-utility.test.ts +154 -0
  246. package/src/infrastructure/config-check-utility.ts +77 -0
  247. package/src/infrastructure/device-certificate.test.ts +40 -0
  248. package/src/infrastructure/device-certificate.ts +58 -0
  249. package/src/infrastructure/legacy-migration/legacy-file.test.ts +88 -0
  250. package/src/infrastructure/legacy-migration/legacy-files.ts +101 -0
  251. package/src/infrastructure/legacy-migration/legacy-migration.test.ts +396 -0
  252. package/src/infrastructure/legacy-migration/legacy-migration.ts +229 -0
  253. package/src/infrastructure/require-files-present-ready.test.ts +53 -0
  254. package/src/infrastructure/required-config-checks.ts +33 -0
  255. package/src/infrastructure/tokens-and-device-cfg.ts +12 -10
  256. package/src/local-connection/rabbitmq-connection.ts +28 -23
  257. package/src/secure-tunneling/secure-tunneling.test.ts +37 -39
  258. package/src/secure-tunneling/secure-tunneling.ts +74 -69
  259. package/src/subcommands/app/analytics.ts +2 -4
  260. package/src/subcommands/app/env-vars.ts +72 -9
  261. package/src/subcommands/app/index.ts +3 -11
  262. package/src/subcommands/app/models.ts +5 -81
  263. package/src/subcommands/app/shadow.ts +6 -5
  264. package/src/subcommands/app/version.ts +3 -4
  265. package/src/subcommands/config.ts +42 -0
  266. package/src/subcommands/device/clean.ts +32 -18
  267. package/src/subcommands/device/get-info.ts +49 -0
  268. package/src/subcommands/device/index.ts +13 -2
  269. package/src/subcommands/device/{device.ts → init.ts} +11 -69
  270. package/src/subcommands/device/migrate.ts +20 -0
  271. package/src/subcommands/device/refresh.ts +23 -0
  272. package/src/subcommands/device/restart.ts +11 -0
  273. package/src/subcommands/index.ts +3 -1
  274. package/src/util/aai-error.ts +20 -0
  275. package/src/util/{cloud-mode-ready.ts → aws-regions.ts} +0 -24
  276. package/src/util/check-for-updates.ts +53 -0
  277. package/src/util/clean-certs.ts +8 -4
  278. package/src/util/directories.ts +23 -67
  279. package/src/util/file.test.ts +90 -0
  280. package/src/util/file.ts +156 -0
  281. package/src/util/get-device-id.ts +7 -7
  282. package/src/util/http-client.ts +2 -2
  283. package/lib/docker/docker-compose-cmd.d.ts +0 -5
  284. package/lib/docker/docker-compose-cmd.d.ts.map +0 -1
  285. package/lib/docker/docker-compose-cmd.js +0 -16
  286. package/lib/docker/docker-compose-cmd.js.map +0 -1
  287. package/lib/subcommands/device/device.d.ts +0 -7
  288. package/lib/subcommands/device/device.d.ts.map +0 -1
  289. package/lib/subcommands/device/device.js.map +0 -1
  290. package/lib/util/cloud-mode-ready.d.ts +0 -3
  291. package/lib/util/cloud-mode-ready.d.ts.map +0 -1
  292. package/lib/util/cloud-mode-ready.js.map +0 -1
  293. package/lib/util/download-file.d.ts +0 -6
  294. package/lib/util/download-file.d.ts.map +0 -1
  295. package/lib/util/download-file.js +0 -25
  296. package/lib/util/download-file.js.map +0 -1
  297. package/lib/util/fetch-with-timeout.d.ts +0 -4
  298. package/lib/util/fetch-with-timeout.d.ts.map +0 -1
  299. package/lib/util/fetch-with-timeout.js +0 -30
  300. package/lib/util/fetch-with-timeout.js.map +0 -1
  301. package/lib/util/parsing.d.ts +0 -2
  302. package/lib/util/parsing.d.ts.map +0 -1
  303. package/lib/util/parsing.js +0 -17
  304. package/lib/util/parsing.js.map +0 -1
  305. package/lib/util/safe-rimraf.d.ts +0 -2
  306. package/lib/util/safe-rimraf.d.ts.map +0 -1
  307. package/lib/util/safe-rimraf.js +0 -16
  308. package/lib/util/safe-rimraf.js.map +0 -1
  309. package/src/docker/docker-compose-cmd.ts +0 -15
  310. package/src/util/download-file.ts +0 -25
  311. package/src/util/fetch-with-timeout.ts +0 -35
  312. package/src/util/parsing.ts +0 -11
  313. package/src/util/safe-rimraf.ts +0 -14
@@ -1,14 +1,23 @@
1
- // eslint-disable-next-line
2
- const amqp = require('amqplib');
1
+ import {
2
+ DeviceAgentStatusShadowUpdate,
3
+ PassthroughStatusValue
4
+ } from '@alwaysai/device-agent-schemas/lib/shadow-schema';
5
+ import { stringifyError } from 'alwaysai/lib/util';
6
+ import * as amqp from 'amqplib';
7
+ import { ALWAYSAI_ANALYTICS_PASSTHROUGH } from '../environment';
3
8
  import {
4
9
  LOCAL_CONNECTION_HOST,
5
10
  LOCAL_CONNECTION_PORT,
6
11
  LOCAL_CONNECTION_ROUTING_KEY
7
12
  } from '../local-connection/constants';
8
- import { setupRabbitMQContainer } from '../local-connection/rabbitmq-connection';
13
+ import {
14
+ setupRabbitMQContainer,
15
+ stopRabbitMQContainer
16
+ } from '../local-connection/rabbitmq-connection';
9
17
  import { logger } from '../util/logger';
10
18
  import sleep from '../util/sleep';
11
19
  import { Publisher } from './publisher';
20
+ import { ShadowHandler } from './shadow-handler';
12
21
 
13
22
  const messageQueue: any[] = [];
14
23
  const ackQueue: any[] = [];
@@ -16,21 +25,90 @@ const MAX_LOCAL_CONNECTION_ATTEMPTS = 10;
16
25
 
17
26
  export class PassthroughHandler {
18
27
  public publisher: Publisher;
19
- public connection;
20
- public channel;
28
+ public shadowHandler: ShadowHandler;
29
+ public connection: amqp.Connection | undefined;
30
+ public channel: amqp.Channel;
21
31
  public packetQueue;
22
32
 
23
- constructor(publisher: Publisher) {
33
+ constructor(publisher: Publisher, shadowHandler: ShadowHandler) {
24
34
  this.publisher = publisher;
35
+ this.shadowHandler = shadowHandler;
25
36
  }
26
37
 
27
- public async setup() {
28
- await setupRabbitMQContainer();
38
+ runChannel = async () => {
39
+ logger.debug('Beginning to consume packets');
40
+ await this.channel.consume(
41
+ this.packetQueue,
42
+ (msg) => {
43
+ // NOTE: this needs to be an arrow function and then the whole contents of processPublish are below
44
+ if (msg?.content !== undefined) {
45
+ const packet = JSON.parse(msg.content.toString());
46
+ messageQueue.push({ packet, msg });
47
+ while (messageQueue.length > 0) {
48
+ const entry = messageQueue.shift();
49
+ const { packet, msg } = entry;
50
+ try {
51
+ const parsedPacket = JSON.parse(packet);
52
+ if (parsedPacket?.['action']) {
53
+ switch (parsedPacket['action']) {
54
+ case 'analytics':
55
+ ackQueue.push(msg);
56
+ // FIXME: put real topic here
57
+ this.publisher.publishToCloudWithAck(
58
+ packet,
59
+ (errOrResp) => {
60
+ while (ackQueue.length > 0) {
61
+ const msg = ackQueue.shift();
62
+ if (errOrResp === true) {
63
+ this.channel.ack(msg); // acknowledge, allow queue to discard
64
+ } else if (errOrResp === false) {
65
+ this.channel.reject(msg, true); // reject and requeue
66
+ }
67
+ }
68
+ }
69
+ );
70
+ break;
71
+ case 'heartbeat':
72
+ this.channel.ack(msg);
73
+ logger.silly(
74
+ `Heartbeat package received & acknowledged: ${packet}`
75
+ );
76
+ break;
77
+ default:
78
+ this.channel.ack(msg);
79
+ logger.debug(
80
+ `Unknown 'action' package received & acknowledged: ${packet}`
81
+ );
82
+ break;
83
+ }
84
+ } else {
85
+ this.channel.ack(msg);
86
+ logger.debug(
87
+ `Received & acknowledged a RabbitMQ Package of unknown structure: ${parsedPacket}`
88
+ );
89
+ }
90
+ } catch (e) {
91
+ logger.error(
92
+ `There was a problem parsing RabbitMQ packet!\n${stringifyError(
93
+ e
94
+ )}`
95
+ );
96
+ this.channel.ack(msg);
97
+ logger.debug('Problematic packet was acknowledged');
98
+ }
99
+ }
100
+ }
101
+ },
102
+ {
103
+ noAck: false // When true, RabbitMQ deletes message as soon as it is consumed
104
+ }
105
+ );
106
+ };
107
+
108
+ async establishLocalConnection(): Promise<void> {
29
109
  let connectAttempts = 0;
30
110
  let connected = false;
31
- logger.debug(
32
- `Setting up alwaysAI Local Connection on host: ${LOCAL_CONNECTION_HOST} and channel key: ${LOCAL_CONNECTION_ROUTING_KEY}`
33
- );
111
+ logger.debug(`Establishing local connection...`);
34
112
  while (
35
113
  connectAttempts <= MAX_LOCAL_CONNECTION_ATTEMPTS &&
36
114
  this.connection === undefined
@@ -40,6 +118,13 @@ export class PassthroughHandler {
40
118
  `amqp://${LOCAL_CONNECTION_HOST}:${LOCAL_CONNECTION_PORT}`
41
119
  );
42
120
  this.channel = await this.connection.createChannel();
121
+ this.connection.on('error', async () => {
122
+ logger.error(`Local connection failed. Attempting to reconnect...`);
123
+ await stopRabbitMQContainer();
124
+ this.connection = undefined;
125
+ await this.setup();
126
+ });
127
+
43
128
  connected = true;
44
129
  } catch (e) {
45
130
  const timeTillNextAttemptMs = 1000 + 1000 * connectAttempts;
@@ -53,84 +138,58 @@ export class PassthroughHandler {
53
138
  }
54
139
  }
55
140
  if (connected === true) {
56
- this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
141
+ await this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
57
142
  this.packetQueue = `${LOCAL_CONNECTION_ROUTING_KEY}`;
58
143
  await this.channel.assertQueue(this.packetQueue, {
59
144
  durable: true
60
145
  });
146
+ logger.info(`Local connection established.`);
61
147
  } else {
62
148
  throw new Error(
63
149
  'Unable to establish connection to alwaysAI Local Connection, please try restarting Device Agent.'
64
150
  );
65
151
  }
66
152
  }
67
- }
68
153
 
69
- function processPublish(passthroughHandler: PassthroughHandler) {
70
- while (messageQueue.length > 0) {
71
- const entry = messageQueue.shift();
72
- const { packet, msg } = entry;
73
- try {
74
- const parsedPacket = JSON.parse(packet);
75
- if (parsedPacket && parsedPacket['action']) {
76
- switch (parsedPacket['action']) {
77
- case 'analytics':
78
- ackQueue.push(msg);
79
- // FIXME: put real topic here
80
- passthroughHandler.publisher.publishToCloudWithAck(
81
- packet,
82
- (errOrResp) => {
83
- while (ackQueue.length > 0) {
84
- const msg = ackQueue.shift();
85
- if (errOrResp === true) {
86
- passthroughHandler.channel.ack(msg); // acknowledge, allow queue to discard
87
- } else if (errOrResp === false) {
88
- passthroughHandler.channel.reject(msg, true); // reject and requeue
89
- }
90
- }
91
- }
92
- );
93
- break;
94
- case 'heartbeat':
95
- passthroughHandler.channel.ack(msg);
96
- logger.debug(
97
- `Heartbeat package received & acknowledged: ${packet}`
98
- );
99
- break;
100
- default:
101
- passthroughHandler.channel.ack(msg);
102
- logger.debug(
103
- `Unknown 'action' package received & acknowledged: ${packet}`
104
- );
105
- break;
106
- }
107
- } else {
108
- passthroughHandler.channel.ack(msg);
109
- logger.debug(
110
- `Received & acknowledged a RabbitMQ Package of unknown structure: ${parsedPacket}`
111
- );
154
+ private async publishPassthroughStatusUpdate(
155
+ status: PassthroughStatusValue,
156
+ message?: string
157
+ ) {
158
+ const deviceAgentPassthroughStatus: DeviceAgentStatusShadowUpdate = {
159
+ passthrough: {
160
+ status: status,
161
+ message: message ?? ''
112
162
  }
113
- } catch (e) {
114
- logger.error(`There was a problem parsing RabbitMQ packet ${e}`);
115
- passthroughHandler.channel.ack(msg);
116
- logger.debug(`Problematic packet was acknowledged`);
117
- }
163
+ };
164
+ await this.shadowHandler.updateDeviceAgentStatusShadow(
165
+ deviceAgentPassthroughStatus
166
+ );
118
167
  }
119
- }
120
168
 
121
- export async function runChannel(passthroughHandler: PassthroughHandler) {
122
- logger.debug('Beginning to consume packets');
123
- passthroughHandler.channel.consume(
124
- passthroughHandler.packetQueue,
125
- function (msg) {
126
- if (msg.content !== undefined) {
127
- const packet = JSON.parse(msg.content.toString());
128
- messageQueue.push({ packet, msg });
129
- processPublish(passthroughHandler);
169
+ async setup() {
170
+ if (ALWAYSAI_ANALYTICS_PASSTHROUGH === true) {
171
+ logger.debug(
172
+ `Setting up alwaysAI Local Connection on host: ${LOCAL_CONNECTION_HOST} and channel key: ${LOCAL_CONNECTION_ROUTING_KEY}`
173
+ );
174
+ await this.publishPassthroughStatusUpdate('starting');
175
+ await setupRabbitMQContainer();
176
+ try {
177
+ await this.establishLocalConnection();
178
+ await this.runChannel();
179
+ await this.publishPassthroughStatusUpdate(
180
+ 'running',
181
+ `Passthrough running on host: ${LOCAL_CONNECTION_HOST} and channel key: ${LOCAL_CONNECTION_ROUTING_KEY}`
182
+ );
183
+ } catch (e) {
184
+ logger.error(
185
+ `There was a problem maintaining RabbitMQ connection!\n${stringifyError(
186
+ e
187
+ )}`
188
+ );
189
+ await this.publishPassthroughStatusUpdate('error', stringifyError(e));
130
190
  }
131
- },
132
- {
133
- noAck: false // When true, RabbitMQ deletes message as soon as it is consumed
191
+ } else {
192
+ await this.publishPassthroughStatusUpdate('disabled');
134
193
  }
135
- );
194
+ }
136
195
  }
@@ -68,13 +68,11 @@ describe('Test Shadow Handler', () => {
68
68
 
69
69
  test('handle project shadow empty delta', async () => {
70
70
  const payload = {
71
- desired: {
72
- [projectId1]: {}
73
- }
71
+ [projectId1]: {}
74
72
  };
75
73
 
76
74
  const updates = await shadowHandler.handleProjectShadow({
77
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
75
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
78
76
  payload,
79
77
  clientToken: ''
80
78
  });
@@ -104,16 +102,14 @@ describe('Test Shadow Handler', () => {
104
102
 
105
103
  const payload = {
106
104
  state: {
107
- desired: {
108
- [projectId1]: {
109
- appConfig: JSON.stringify(appCfg1)
110
- }
105
+ [projectId1]: {
106
+ appConfig: JSON.stringify(appCfg1)
111
107
  }
112
108
  }
113
109
  };
114
110
 
115
111
  const updates = await shadowHandler.handleProjectShadow({
116
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
112
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
117
113
  payload,
118
114
  clientToken: ''
119
115
  });
@@ -153,16 +149,14 @@ describe('Test Shadow Handler', () => {
153
149
 
154
150
  const payload = {
155
151
  state: {
156
- desired: {
157
- [projectId1]: {
158
- appConfig: JSON.stringify(appCfg1)
159
- }
152
+ [projectId1]: {
153
+ appConfig: JSON.stringify(appCfg1)
160
154
  }
161
155
  }
162
156
  };
163
157
 
164
158
  const updates = await shadowHandler.handleProjectShadow({
165
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
159
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
166
160
  payload,
167
161
  clientToken: ''
168
162
  });
@@ -220,19 +214,17 @@ describe('Test Shadow Handler', () => {
220
214
  };
221
215
  const payload = {
222
216
  state: {
223
- desired: {
224
- [projectId1]: {
225
- appConfig: JSON.stringify(appCfg1)
226
- },
227
- [projectId2]: {
228
- appConfig: JSON.stringify(appCfg2)
229
- }
217
+ [projectId1]: {
218
+ appConfig: JSON.stringify(appCfg1)
219
+ },
220
+ [projectId2]: {
221
+ appConfig: JSON.stringify(appCfg2)
230
222
  }
231
223
  }
232
224
  };
233
225
 
234
226
  const updates = await shadowHandler.handleProjectShadow({
235
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
227
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
236
228
  payload,
237
229
  clientToken: ''
238
230
  });
@@ -281,16 +273,14 @@ describe('Test Shadow Handler', () => {
281
273
 
282
274
  const payload = {
283
275
  state: {
284
- desired: {
285
- [projectId1]: {
286
- appConfig: JSON.stringify(appCfg1)
287
- }
276
+ [projectId1]: {
277
+ appConfig: JSON.stringify(appCfg1)
288
278
  }
289
279
  }
290
280
  };
291
281
 
292
282
  const updates = await shadowHandler.handleProjectShadow({
293
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
283
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
294
284
  payload,
295
285
  clientToken: ''
296
286
  });
@@ -365,10 +355,8 @@ describe('Test Shadow Handler', () => {
365
355
 
366
356
  const payload = {
367
357
  state: {
368
- desired: {
369
- [projectId1]: {
370
- appConfig: appCfg1 // This is missing JSON.stringify() making this an unparsable object.
371
- }
358
+ [projectId1]: {
359
+ appConfig: appCfg1 // This is missing JSON.stringify() making this an unparsable object.
372
360
  }
373
361
  }
374
362
  };
@@ -378,7 +366,7 @@ describe('Test Shadow Handler', () => {
378
366
  .mockReturnValue({} as unknown as Logger);
379
367
 
380
368
  const updates = await shadowHandler.handleProjectShadow({
381
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
369
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
382
370
  payload,
383
371
  clientToken: ''
384
372
  });
@@ -393,13 +381,15 @@ describe('Test Shadow Handler', () => {
393
381
  describe('handle project shadow env vars', () => {
394
382
  test('handle a response from the getAccepted from the cloud', async () => {
395
383
  const envVars1 = {
396
- VAR0: 'value0'
384
+ service: {
385
+ VAR0: 'value0'
386
+ }
397
387
  };
398
388
  const payload = {
399
389
  state: {
400
390
  reported: {
401
391
  [projectId1]: {
402
- envVars: { service: envVars1 }
392
+ envVars: JSON.stringify(envVars1)
403
393
  }
404
394
  }
405
395
  }
@@ -414,22 +404,20 @@ describe('Test Shadow Handler', () => {
414
404
  });
415
405
  test('handle project shadow env vars update delta', async () => {
416
406
  const envVars1 = {
417
- VAR1: 'value1'
407
+ service: {
408
+ VAR1: 'value1'
409
+ }
418
410
  };
419
411
  const payload = {
420
412
  state: {
421
- desired: {
422
- [projectId1]: {
423
- envVars: {
424
- service: envVars1
425
- }
426
- }
413
+ [projectId1]: {
414
+ envVars: JSON.stringify(envVars1)
427
415
  }
428
416
  }
429
417
  };
430
418
 
431
419
  const updates = await shadowHandler.handleProjectShadow({
432
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
420
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
433
421
  payload,
434
422
  clientToken: ''
435
423
  });
@@ -438,36 +426,36 @@ describe('Test Shadow Handler', () => {
438
426
  projectId: projectId1,
439
427
  txId: expect.any(String),
440
428
  envVarUpdate: {
441
- envVars: { service: envVars1 }
429
+ envVars: envVars1
442
430
  }
443
431
  });
444
432
  });
445
433
 
446
434
  test('handle project shadow env vars update delta for two projects', async () => {
447
435
  const service1 = {
448
- VAR1: 'value1'
436
+ service: {
437
+ VAR1: 'value1'
438
+ }
449
439
  };
450
440
  const service2 = {
451
- VAR2: 'value2'
441
+ service: {
442
+ VAR2: 'value2'
443
+ }
452
444
  };
453
445
 
454
446
  const payload = {
455
447
  state: {
456
- desired: {
457
- [projectId1]: {
458
- envVars: {
459
- service: service1
460
- }
461
- },
462
- [projectId2]: {
463
- envVars: { service: service2 }
464
- }
448
+ [projectId1]: {
449
+ envVars: JSON.stringify(service1)
450
+ },
451
+ [projectId2]: {
452
+ envVars: JSON.stringify(service2)
465
453
  }
466
454
  }
467
455
  };
468
456
 
469
457
  const updates = await shadowHandler.handleProjectShadow({
470
- topic: getShadowTopic(clientId, 'projects', 'update/accepted'),
458
+ topic: getShadowTopic(clientId, 'projects', 'update/delta'),
471
459
  payload,
472
460
  clientToken: ''
473
461
  });
@@ -476,14 +464,14 @@ describe('Test Shadow Handler', () => {
476
464
  projectId: projectId1,
477
465
  txId: expect.any(String),
478
466
  envVarUpdate: {
479
- envVars: { service: service1 }
467
+ envVars: service1
480
468
  }
481
469
  });
482
470
  expect(updates[1]).toEqual({
483
471
  projectId: projectId2,
484
472
  txId: expect.any(String),
485
473
  envVarUpdate: {
486
- envVars: { service: service2 }
474
+ envVars: service2
487
475
  }
488
476
  });
489
477
  });