@alwaysai/device-agent 1.5.0 → 2.0.1
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.
- package/lib/application-control/config.d.ts.map +1 -1
- package/lib/application-control/config.js +8 -3
- package/lib/application-control/config.js.map +1 -1
- package/lib/application-control/environment-variables.d.ts +5 -5
- package/lib/application-control/environment-variables.d.ts.map +1 -1
- package/lib/application-control/environment-variables.js +25 -38
- package/lib/application-control/environment-variables.js.map +1 -1
- package/lib/application-control/environment-variables.test.js +27 -7
- package/lib/application-control/environment-variables.test.js.map +1 -1
- package/lib/application-control/index.d.ts +4 -4
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +1 -4
- package/lib/application-control/index.js.map +1 -1
- package/lib/application-control/install.d.ts +4 -1
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +24 -8
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +0 -11
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +5 -54
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/utils.d.ts +0 -4
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +12 -22
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/base-message-handler.d.ts +27 -0
- package/lib/cloud-connection/base-message-handler.d.ts.map +1 -0
- package/lib/cloud-connection/base-message-handler.js +72 -0
- package/lib/cloud-connection/base-message-handler.js.map +1 -0
- package/lib/cloud-connection/bootstrap-provision.js +3 -2
- package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
- package/lib/cloud-connection/connection-manager.d.ts +21 -0
- package/lib/cloud-connection/connection-manager.d.ts.map +1 -0
- package/lib/cloud-connection/connection-manager.js +158 -0
- package/lib/cloud-connection/connection-manager.js.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +9 -30
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +69 -508
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/device-agent-message-handler.d.ts +22 -0
- package/lib/cloud-connection/device-agent-message-handler.d.ts.map +1 -0
- package/lib/cloud-connection/device-agent-message-handler.js +357 -0
- package/lib/cloud-connection/device-agent-message-handler.js.map +1 -0
- package/lib/cloud-connection/device-agent.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent.js +11 -9
- package/lib/cloud-connection/device-agent.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +19 -28
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
- package/lib/cloud-connection/live-updates-handler.js +60 -172
- package/lib/cloud-connection/live-updates-handler.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.test.js +71 -165
- package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
- package/lib/cloud-connection/message-dispatcher.d.ts +10 -0
- package/lib/cloud-connection/message-dispatcher.d.ts.map +1 -0
- package/lib/cloud-connection/message-dispatcher.js +27 -0
- package/lib/cloud-connection/message-dispatcher.js.map +1 -0
- package/lib/cloud-connection/passthrough-handler.d.ts +4 -1
- package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
- package/lib/cloud-connection/passthrough-handler.js +30 -11
- package/lib/cloud-connection/passthrough-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.d.ts +11 -3
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
- package/lib/cloud-connection/shadow-handler.js +133 -28
- package/lib/cloud-connection/shadow-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.test.js +45 -57
- package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
- package/lib/cloud-connection/shadow.d.ts.map +1 -1
- package/lib/cloud-connection/shadow.js +2 -1
- package/lib/cloud-connection/shadow.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.d.ts +12 -3
- package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
- package/lib/cloud-connection/transaction-manager.js +29 -28
- package/lib/cloud-connection/transaction-manager.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.test.js +46 -5
- package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
- package/lib/device-control/device-control.d.ts +8 -8
- package/lib/device-control/device-control.d.ts.map +1 -1
- package/lib/device-control/device-control.js +95 -71
- package/lib/device-control/device-control.js.map +1 -1
- package/lib/docker/docker-compose.d.ts.map +1 -1
- package/lib/docker/docker-compose.js +2 -1
- package/lib/docker/docker-compose.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +2 -1
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js +7 -7
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +3 -1
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/infrastructure/config-check-utility.d.ts +6 -0
- package/lib/infrastructure/config-check-utility.d.ts.map +1 -0
- package/lib/infrastructure/config-check-utility.js +67 -0
- package/lib/infrastructure/config-check-utility.js.map +1 -0
- package/lib/infrastructure/config-check-utility.test.d.ts +2 -0
- package/lib/infrastructure/config-check-utility.test.d.ts.map +1 -0
- package/lib/infrastructure/config-check-utility.test.js +109 -0
- package/lib/infrastructure/config-check-utility.test.js.map +1 -0
- package/lib/infrastructure/device-certificate.d.ts +10 -0
- package/lib/infrastructure/device-certificate.d.ts.map +1 -0
- package/lib/infrastructure/device-certificate.js +47 -0
- package/lib/infrastructure/device-certificate.js.map +1 -0
- package/lib/infrastructure/device-certificate.test.d.ts +2 -0
- package/lib/infrastructure/device-certificate.test.d.ts.map +1 -0
- package/lib/infrastructure/device-certificate.test.js +24 -0
- package/lib/infrastructure/device-certificate.test.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts +2 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.js +61 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-files.d.ts +75 -0
- package/lib/infrastructure/legacy-migration/legacy-files.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-files.js +75 -0
- package/lib/infrastructure/legacy-migration/legacy-files.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.d.ts +6 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.js +149 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts +2 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.js +226 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.js.map +1 -0
- package/lib/infrastructure/require-files-present-ready.test.d.ts +2 -0
- package/lib/infrastructure/require-files-present-ready.test.d.ts.map +1 -0
- package/lib/infrastructure/require-files-present-ready.test.js +44 -0
- package/lib/infrastructure/require-files-present-ready.test.js.map +1 -0
- package/lib/infrastructure/required-config-checks.d.ts +2 -0
- package/lib/infrastructure/required-config-checks.d.ts.map +1 -0
- package/lib/infrastructure/required-config-checks.js +30 -0
- package/lib/infrastructure/required-config-checks.js.map +1 -0
- package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
- package/lib/infrastructure/tokens-and-device-cfg.js +11 -8
- package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
- package/lib/jobs/job-handler.d.ts +23 -0
- package/lib/jobs/job-handler.d.ts.map +1 -0
- package/lib/jobs/job-handler.js +131 -0
- package/lib/jobs/job-handler.js.map +1 -0
- package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
- package/lib/local-connection/rabbitmq-connection.js +14 -14
- package/lib/local-connection/rabbitmq-connection.js.map +1 -1
- package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts +8 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts.map +1 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.js +42 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.js.map +1 -0
- package/lib/secure-tunneling/secure-tunneling.d.ts +9 -9
- package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.js +21 -16
- package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.test.js +11 -13
- package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
- package/lib/subcommands/app/analytics.d.ts.map +1 -1
- package/lib/subcommands/app/analytics.js +1 -2
- package/lib/subcommands/app/analytics.js.map +1 -1
- package/lib/subcommands/app/env-vars.d.ts +4 -0
- package/lib/subcommands/app/env-vars.d.ts.map +1 -1
- package/lib/subcommands/app/env-vars.js +52 -6
- package/lib/subcommands/app/env-vars.js.map +1 -1
- package/lib/subcommands/app/index.d.ts.map +1 -1
- package/lib/subcommands/app/index.js +1 -3
- package/lib/subcommands/app/index.js.map +1 -1
- package/lib/subcommands/app/models.d.ts +0 -11
- package/lib/subcommands/app/models.d.ts.map +1 -1
- package/lib/subcommands/app/models.js +2 -58
- package/lib/subcommands/app/models.js.map +1 -1
- package/lib/subcommands/app/shadow.d.ts.map +1 -1
- package/lib/subcommands/app/shadow.js +6 -5
- package/lib/subcommands/app/shadow.js.map +1 -1
- package/lib/subcommands/app/version.d.ts +2 -0
- package/lib/subcommands/app/version.d.ts.map +1 -1
- package/lib/subcommands/app/version.js +16 -6
- package/lib/subcommands/app/version.js.map +1 -1
- package/lib/subcommands/config.d.ts +2 -0
- package/lib/subcommands/config.d.ts.map +1 -0
- package/lib/subcommands/config.js +39 -0
- package/lib/subcommands/config.js.map +1 -0
- package/lib/subcommands/device/clean.d.ts +1 -1
- package/lib/subcommands/device/clean.d.ts.map +1 -1
- package/lib/subcommands/device/clean.js +23 -13
- package/lib/subcommands/device/clean.js.map +1 -1
- package/lib/subcommands/device/index.d.ts.map +1 -1
- package/lib/subcommands/device/index.js +3 -1
- package/lib/subcommands/device/index.js.map +1 -1
- package/lib/subcommands/device/init.js +8 -8
- package/lib/subcommands/device/init.js.map +1 -1
- package/lib/subcommands/device/migrate.d.ts +2 -0
- package/lib/subcommands/device/migrate.d.ts.map +1 -0
- package/lib/subcommands/device/migrate.js +24 -0
- package/lib/subcommands/device/migrate.js.map +1 -0
- package/lib/subcommands/device/refresh.d.ts.map +1 -1
- package/lib/subcommands/device/refresh.js +1 -0
- package/lib/subcommands/device/refresh.js.map +1 -1
- package/lib/subcommands/index.d.ts +1 -1
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/subcommands/index.js +3 -1
- package/lib/subcommands/index.js.map +1 -1
- package/lib/subcommands/rabbitmq-connection.d.ts +1 -1
- package/lib/subcommands/rabbitmq-connection.d.ts.map +1 -1
- package/lib/util/aai-error.d.ts +12 -0
- package/lib/util/aai-error.d.ts.map +1 -0
- package/lib/util/aai-error.js +11 -0
- package/lib/util/aai-error.js.map +1 -0
- package/lib/util/aws-regions.d.ts +2 -0
- package/lib/util/aws-regions.d.ts.map +1 -0
- package/lib/util/{cloud-mode-ready.js → aws-regions.js} +2 -20
- package/lib/util/aws-regions.js.map +1 -0
- package/lib/util/check-for-updates.d.ts.map +1 -1
- package/lib/util/check-for-updates.js +5 -28
- package/lib/util/check-for-updates.js.map +1 -1
- package/lib/util/clean-certs.d.ts.map +1 -1
- package/lib/util/clean-certs.js +5 -4
- package/lib/util/clean-certs.js.map +1 -1
- package/lib/util/directories.d.ts +4 -18
- package/lib/util/directories.d.ts.map +1 -1
- package/lib/util/directories.js +18 -32
- package/lib/util/directories.js.map +1 -1
- package/lib/util/file.d.ts +4 -0
- package/lib/util/file.d.ts.map +1 -1
- package/lib/util/file.js +65 -4
- package/lib/util/file.js.map +1 -1
- package/lib/util/get-device-id.d.ts.map +1 -1
- package/lib/util/get-device-id.js +7 -1
- package/lib/util/get-device-id.js.map +1 -1
- package/lib/util/http-client.js +3 -3
- package/lib/util/http-client.js.map +1 -1
- package/package.json +19 -17
- package/readme.md +12 -32
- package/src/application-control/config.ts +9 -12
- package/src/application-control/environment-variables.test.ts +28 -7
- package/src/application-control/environment-variables.ts +42 -59
- package/src/application-control/index.ts +3 -16
- package/src/application-control/install.ts +39 -13
- package/src/application-control/models.ts +6 -87
- package/src/application-control/utils.ts +10 -25
- package/src/cloud-connection/base-message-handler.ts +118 -0
- package/src/cloud-connection/bootstrap-provision.ts +7 -7
- package/src/cloud-connection/connection-manager.ts +187 -0
- package/src/cloud-connection/device-agent-cloud-connection.ts +130 -723
- package/src/cloud-connection/device-agent-message-handler.ts +642 -0
- package/src/cloud-connection/device-agent.ts +16 -7
- package/src/cloud-connection/live-updates-handler.test.ts +121 -189
- package/src/cloud-connection/live-updates-handler.ts +105 -232
- package/src/cloud-connection/message-dispatcher.ts +33 -0
- package/src/cloud-connection/passthrough-handler.ts +55 -18
- package/src/cloud-connection/shadow-handler.test.ts +45 -57
- package/src/cloud-connection/shadow-handler.ts +224 -54
- package/src/cloud-connection/shadow.ts +4 -1
- package/src/cloud-connection/transaction-manager.test.ts +68 -6
- package/src/cloud-connection/transaction-manager.ts +69 -41
- package/src/device-control/device-control.ts +102 -70
- package/src/docker/docker-compose.ts +3 -2
- package/src/infrastructure/agent-config.test.ts +6 -2
- package/src/infrastructure/agent-config.ts +8 -7
- package/src/infrastructure/config-check-utility.test.ts +154 -0
- package/src/infrastructure/config-check-utility.ts +77 -0
- package/src/infrastructure/device-certificate.test.ts +40 -0
- package/src/infrastructure/device-certificate.ts +58 -0
- package/src/infrastructure/legacy-migration/legacy-file.test.ts +88 -0
- package/src/infrastructure/legacy-migration/legacy-files.ts +101 -0
- package/src/infrastructure/legacy-migration/legacy-migration.test.ts +396 -0
- package/src/infrastructure/legacy-migration/legacy-migration.ts +229 -0
- package/src/infrastructure/require-files-present-ready.test.ts +53 -0
- package/src/infrastructure/required-config-checks.ts +33 -0
- package/src/infrastructure/tokens-and-device-cfg.ts +12 -10
- package/src/jobs/job-handler.ts +146 -0
- package/src/local-connection/rabbitmq-connection.ts +22 -17
- package/src/secure-tunneling/secure-tunnel-message-handler.ts +56 -0
- package/src/secure-tunneling/secure-tunneling.test.ts +20 -22
- package/src/secure-tunneling/secure-tunneling.ts +41 -29
- package/src/subcommands/app/analytics.ts +2 -4
- package/src/subcommands/app/env-vars.ts +72 -9
- package/src/subcommands/app/index.ts +3 -11
- package/src/subcommands/app/models.ts +5 -81
- package/src/subcommands/app/shadow.ts +6 -5
- package/src/subcommands/app/version.ts +23 -6
- package/src/subcommands/config.ts +42 -0
- package/src/subcommands/device/clean.ts +31 -17
- package/src/subcommands/device/index.ts +3 -1
- package/src/subcommands/device/init.ts +11 -11
- package/src/subcommands/device/migrate.ts +20 -0
- package/src/subcommands/device/refresh.ts +1 -0
- package/src/subcommands/index.ts +3 -1
- package/src/util/aai-error.ts +20 -0
- package/src/util/{cloud-mode-ready.ts → aws-regions.ts} +0 -24
- package/src/util/check-for-updates.ts +14 -30
- package/src/util/clean-certs.ts +8 -4
- package/src/util/directories.ts +23 -67
- package/src/util/file.ts +83 -3
- package/src/util/get-device-id.ts +7 -7
- package/src/util/http-client.ts +2 -2
- package/lib/util/cloud-mode-ready.d.ts +0 -3
- package/lib/util/cloud-mode-ready.d.ts.map +0 -1
- package/lib/util/cloud-mode-ready.js.map +0 -1
- package/lib/util/download-file.d.ts +0 -6
- package/lib/util/download-file.d.ts.map +0 -1
- package/lib/util/download-file.js +0 -25
- package/lib/util/download-file.js.map +0 -1
- package/lib/util/fetch-with-timeout.d.ts +0 -4
- package/lib/util/fetch-with-timeout.d.ts.map +0 -1
- package/lib/util/fetch-with-timeout.js +0 -30
- package/lib/util/fetch-with-timeout.js.map +0 -1
- package/lib/util/parsing.d.ts +0 -2
- package/lib/util/parsing.d.ts.map +0 -1
- package/lib/util/parsing.js +0 -17
- package/lib/util/parsing.js.map +0 -1
- package/src/util/download-file.ts +0 -25
- package/src/util/fetch-with-timeout.ts +0 -35
- package/src/util/parsing.ts +0 -11
|
@@ -1,288 +1,161 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AppLogsPayload,
|
|
3
|
-
keyMirrors,
|
|
4
|
-
LiveStateUpdatesTogglePayload,
|
|
5
|
-
ToClientMessage,
|
|
6
|
-
buildAppLogsMessage,
|
|
7
|
-
buildAppStateMessage,
|
|
8
|
-
buildDeviceStatsMessage,
|
|
9
|
-
StatusResponsePayload,
|
|
10
|
-
buildToClientStatusResponseMessage,
|
|
11
|
-
ToClientMessageTypeValue
|
|
12
|
-
} from '@alwaysai/device-agent-schemas';
|
|
13
|
-
import { getAppLogs } from '../application-control';
|
|
1
|
+
import { ToClientMessageTypeValue } from '@alwaysai/device-agent-schemas';
|
|
14
2
|
import { logger } from '../util/logger';
|
|
15
3
|
import sleep from '../util/sleep';
|
|
16
|
-
import { Publisher } from './publisher';
|
|
17
|
-
import { getAppStatePayload, getDeviceStatsPayload } from './messages';
|
|
18
4
|
import { ALWAYSAI_LIVE_UPDATES_TIMEOUT_MS } from '../environment';
|
|
5
|
+
import { stringifyError } from 'alwaysai/lib/util';
|
|
19
6
|
|
|
20
|
-
const
|
|
7
|
+
const KILL_ALL_TIMEOUT_MS = ALWAYSAI_LIVE_UPDATES_TIMEOUT_MS
|
|
21
8
|
? parseInt(ALWAYSAI_LIVE_UPDATES_TIMEOUT_MS)
|
|
22
9
|
: 80000;
|
|
23
10
|
|
|
11
|
+
export const DEFAULT_INTERVALS_MS = 5000;
|
|
12
|
+
|
|
13
|
+
interface IntervalOptions {
|
|
14
|
+
ms?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
24
17
|
export class LiveUpdatesHandler {
|
|
25
|
-
private
|
|
26
|
-
private
|
|
18
|
+
private killAllTimeout: ReturnType<typeof setTimeout>;
|
|
19
|
+
private livingIntervals: Record<string, ReturnType<typeof setInterval>> = {};
|
|
20
|
+
private livingStreams = new Set<string>();
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
[keyMirrors.toClientMessageType.status_response]: false
|
|
34
|
-
};
|
|
35
|
-
private liveUpdatesSleepIntervals = {
|
|
36
|
-
[keyMirrors.toClientMessageType.device_stats]: 5000,
|
|
37
|
-
[keyMirrors.toClientMessageType.app_state]: 5000,
|
|
38
|
-
[keyMirrors.toClientMessageType.app_logs]: 5000,
|
|
39
|
-
[keyMirrors.toClientMessageType.status_response]: 5000
|
|
40
|
-
};
|
|
22
|
+
constructor() {
|
|
23
|
+
logger.debug(
|
|
24
|
+
`Toggle live updates timeout set to ${KILL_ALL_TIMEOUT_MS} ms`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
41
27
|
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
public async enable(
|
|
29
|
+
intervalType: ToClientMessageTypeValue,
|
|
30
|
+
publishingFn: () => Promise<void>,
|
|
31
|
+
transactionId?: string,
|
|
32
|
+
options?: IntervalOptions
|
|
33
|
+
) {
|
|
34
|
+
this.restartKillAllTimeout();
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
return await getAppLogs({
|
|
52
|
-
projectId,
|
|
53
|
-
args: ['--tail', '100', '--no-log-prefix']
|
|
54
|
-
});
|
|
55
|
-
} catch (e) {
|
|
56
|
-
logger.info(
|
|
57
|
-
`Failed to start app logs, retrying in 1 second. Error: ${e}`
|
|
58
|
-
);
|
|
59
|
-
await sleep(1000);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// Case where logs were disabled prior to connecting
|
|
63
|
-
return null;
|
|
36
|
+
const key = this.generateIntervalKey(intervalType, transactionId);
|
|
37
|
+
|
|
38
|
+
this.safeSetInterval(key, publishingFn, options);
|
|
39
|
+
|
|
40
|
+
await publishingFn();
|
|
64
41
|
}
|
|
65
42
|
|
|
66
|
-
|
|
43
|
+
public disable(
|
|
44
|
+
intervalType: ToClientMessageTypeValue,
|
|
45
|
+
transactionId?: string
|
|
46
|
+
) {
|
|
47
|
+
const key = this.generateIntervalKey(intervalType, transactionId);
|
|
48
|
+
clearInterval(this.livingIntervals[key]);
|
|
49
|
+
delete this.livingIntervals[key];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async startStream(
|
|
53
|
+
projectId: string,
|
|
54
|
+
streamGetter: () => Promise<NodeJS.ReadableStream | null>,
|
|
55
|
+
publishingFn: (logChunk: string) => void
|
|
56
|
+
) {
|
|
67
57
|
logger.info(`Starting log stream for ${projectId}`);
|
|
68
58
|
|
|
69
|
-
this.
|
|
59
|
+
this.livingStreams.add(projectId);
|
|
70
60
|
|
|
71
|
-
const readable = await this.
|
|
61
|
+
const readable = await this.getStreamWithRetry(projectId, streamGetter);
|
|
72
62
|
|
|
73
63
|
if (readable === null) {
|
|
74
64
|
logger.info(
|
|
75
|
-
`
|
|
65
|
+
`Stream terminated prior to starting. Readable stream is null. ProjectId: ${projectId}`
|
|
76
66
|
);
|
|
77
67
|
return;
|
|
78
68
|
}
|
|
79
69
|
|
|
80
70
|
readable.on('data', async (chunk: Buffer) => {
|
|
81
|
-
if (!this.
|
|
71
|
+
if (!this.livingStreams.has(projectId)) {
|
|
82
72
|
// why doesn't typescript know about this function?
|
|
83
73
|
// @ts-ignore
|
|
84
74
|
readable.destroy();
|
|
85
|
-
logger.info(`
|
|
75
|
+
logger.info(`Stream terminated. ProjectId: ${projectId}`);
|
|
86
76
|
return;
|
|
87
77
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
projectId,
|
|
91
|
-
logChunk: logStr
|
|
92
|
-
};
|
|
93
|
-
const message = buildAppLogsMessage(this.clientId, payload, txId);
|
|
94
|
-
this.publisher.publishToClient(message, logger.silly);
|
|
78
|
+
|
|
79
|
+
publishingFn(chunk.toString());
|
|
95
80
|
});
|
|
96
81
|
|
|
97
82
|
readable.on('error', (error) => {
|
|
98
|
-
logger.error(
|
|
99
|
-
`App log stream terminated for project ${projectId}: ${error}`
|
|
100
|
-
);
|
|
83
|
+
logger.error(`Stream terminated. ProjectId: ${projectId} - ${error}`);
|
|
101
84
|
});
|
|
102
85
|
|
|
103
86
|
readable.on('finished', () => {
|
|
104
|
-
logger.info(`
|
|
87
|
+
logger.info(`Strean complete. ProjectId: ${projectId}`);
|
|
105
88
|
});
|
|
106
89
|
}
|
|
107
90
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
txId?: string
|
|
111
|
-
): boolean {
|
|
112
|
-
switch (flag) {
|
|
113
|
-
case keyMirrors.toClientMessageType.device_stats:
|
|
114
|
-
case keyMirrors.toClientMessageType.app_state:
|
|
115
|
-
return this.liveUpdatesAlive[flag];
|
|
116
|
-
case keyMirrors.toClientMessageType.status_response: {
|
|
117
|
-
if (!txId) {
|
|
118
|
-
throw new Error(`Transaction ID not provided to continuePublishing!`);
|
|
119
|
-
}
|
|
120
|
-
return this.transactionStatuses.has(txId);
|
|
121
|
-
}
|
|
122
|
-
default:
|
|
123
|
-
logger.error(`Unrecognized publishable flag ${flag}`);
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private getLiveUpdatesInterval(flag: ToClientMessageTypeValue): number {
|
|
129
|
-
const exists = this.liveUpdatesSleepIntervals[flag];
|
|
130
|
-
if (exists) {
|
|
131
|
-
return exists;
|
|
132
|
-
}
|
|
133
|
-
logger.error(`Unrecognized live updates flag ${flag}`);
|
|
134
|
-
return -1;
|
|
91
|
+
public stopStream(streamId: string) {
|
|
92
|
+
this.livingStreams.delete(streamId);
|
|
135
93
|
}
|
|
136
94
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.disableAppStateLiveUpdates();
|
|
141
|
-
this.disableDeviceStatsLiveUpdates();
|
|
142
|
-
this.appLogStreams.clear();
|
|
143
|
-
}, LIVE_UPDATES_TIMEOUT);
|
|
144
|
-
}
|
|
95
|
+
/*=================================================================
|
|
96
|
+
Private interface
|
|
97
|
+
=================================================================*/
|
|
145
98
|
|
|
146
|
-
private async
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
while (this.continuePublishing(messageType, txId)) {
|
|
99
|
+
private async getStreamWithRetry(
|
|
100
|
+
streamId: string,
|
|
101
|
+
streamGetter: () => Promise<NodeJS.ReadableStream | null>
|
|
102
|
+
): Promise<NodeJS.ReadableStream | null> {
|
|
103
|
+
// Retry starting logs until it starts successfully or is terminated
|
|
104
|
+
while (this.livingStreams.has(streamId)) {
|
|
153
105
|
try {
|
|
154
|
-
|
|
155
|
-
this.publisher.publishToClient(message, logger.silly);
|
|
156
|
-
|
|
157
|
-
await sleep(this.getLiveUpdatesInterval(messageType));
|
|
106
|
+
return await streamGetter();
|
|
158
107
|
} catch (e) {
|
|
159
|
-
logger.
|
|
160
|
-
`
|
|
108
|
+
logger.info(
|
|
109
|
+
`Failed to start app logs, retrying in 1 second.\n${stringifyError(
|
|
110
|
+
e
|
|
111
|
+
)}`
|
|
161
112
|
);
|
|
113
|
+
await sleep(1000);
|
|
162
114
|
}
|
|
163
115
|
}
|
|
164
|
-
|
|
116
|
+
// Case where logs were disabled prior to connecting
|
|
117
|
+
return null;
|
|
165
118
|
}
|
|
166
119
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
|
|
120
|
+
// do not await any functions in the setSafeInterval other than inside setInterval() as per EI-1694.
|
|
121
|
+
private safeSetInterval(
|
|
122
|
+
key: string,
|
|
123
|
+
publishingFn: () => Promise<void>,
|
|
124
|
+
options?: IntervalOptions
|
|
125
|
+
) {
|
|
126
|
+
clearInterval(this.livingIntervals[key]);
|
|
127
|
+
|
|
128
|
+
this.livingIntervals[key] = setInterval(
|
|
129
|
+
async () => {
|
|
130
|
+
try {
|
|
131
|
+
await publishingFn();
|
|
132
|
+
} catch (e) {
|
|
133
|
+
logger.error(
|
|
134
|
+
`Error getting live updates: ${JSON.stringify(
|
|
135
|
+
e
|
|
136
|
+
)}: intervalKey: ${key}. Continuing...`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
options?.ms ? options.ms : DEFAULT_INTERVALS_MS
|
|
176
141
|
);
|
|
177
142
|
}
|
|
178
143
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
logger.info('Disabled live updates for device_stats');
|
|
185
|
-
this.liveUpdatesAlive.device_stats = false;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
public getAppStateLiveUpdates(): boolean {
|
|
189
|
-
return this.liveUpdatesAlive.app_state;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
public disableAppStateLiveUpdates() {
|
|
193
|
-
logger.info('Disabled live updates for app_state');
|
|
194
|
-
this.liveUpdatesAlive.app_state = false;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
public getAppLogsLiveUpdates() {
|
|
198
|
-
return this.liveUpdatesAlive.app_logs;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
public async enableTransactionStatus(props: { txId: string }) {
|
|
202
|
-
const { txId } = props;
|
|
203
|
-
this.liveUpdatesAlive.status_response = true;
|
|
204
|
-
if (!this.transactionStatuses.has(txId)) {
|
|
205
|
-
this.transactionStatuses.add(txId);
|
|
206
|
-
// Don't wait for this call to finish since it loops until disabled
|
|
207
|
-
void this.startPublishingLiveUpdates(
|
|
208
|
-
keyMirrors.toClientMessageType.status_response,
|
|
209
|
-
async () => {
|
|
210
|
-
const payload: StatusResponsePayload = {
|
|
211
|
-
status: keyMirrors.statusResponse.in_progress
|
|
212
|
-
};
|
|
213
|
-
return buildToClientStatusResponseMessage(
|
|
214
|
-
this.clientId,
|
|
215
|
-
payload,
|
|
216
|
-
txId
|
|
217
|
-
);
|
|
218
|
-
},
|
|
219
|
-
txId
|
|
144
|
+
private restartKillAllTimeout() {
|
|
145
|
+
clearTimeout(this.killAllTimeout);
|
|
146
|
+
this.killAllTimeout = setTimeout(() => {
|
|
147
|
+
Object.values(this.livingIntervals).forEach((interval) =>
|
|
148
|
+
clearInterval(interval)
|
|
220
149
|
);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
public async disableTransactionStatus(props: { txId: string }) {
|
|
225
|
-
const { txId } = props;
|
|
226
|
-
this.transactionStatuses.delete(txId);
|
|
227
|
-
|
|
228
|
-
if (this.transactionStatuses.size === 0) {
|
|
229
|
-
this.liveUpdatesAlive.status_response = false;
|
|
230
|
-
}
|
|
150
|
+
this.livingIntervals = {};
|
|
151
|
+
this.livingStreams.clear();
|
|
152
|
+
}, KILL_ALL_TIMEOUT_MS);
|
|
231
153
|
}
|
|
232
154
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
) {
|
|
237
|
-
|
|
238
|
-
this.restartLiveUpdatesTimeout();
|
|
239
|
-
|
|
240
|
-
const promises: Promise<void>[] = [];
|
|
241
|
-
|
|
242
|
-
if (deviceStats !== undefined) {
|
|
243
|
-
const currentDeviceStats = this.getDeviceStatsLiveUpdates();
|
|
244
|
-
this.liveUpdatesAlive.device_stats = deviceStats;
|
|
245
|
-
if (deviceStats && currentDeviceStats !== true) {
|
|
246
|
-
// Don't wait for this call to finish since it loops until disabled
|
|
247
|
-
const deviceStatsPromise = this.startPublishingLiveUpdates(
|
|
248
|
-
keyMirrors.toClientMessageType.device_stats,
|
|
249
|
-
async () => {
|
|
250
|
-
const payload = await getDeviceStatsPayload();
|
|
251
|
-
return buildDeviceStatsMessage(this.clientId, payload, txId);
|
|
252
|
-
},
|
|
253
|
-
txId
|
|
254
|
-
);
|
|
255
|
-
promises.push(deviceStatsPromise);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (appState !== undefined) {
|
|
260
|
-
const currentAppState = this.getAppStateLiveUpdates();
|
|
261
|
-
this.liveUpdatesAlive.app_state = appState;
|
|
262
|
-
if (appState && currentAppState !== true) {
|
|
263
|
-
// Don't wait for this call to finish since it loops until disabled
|
|
264
|
-
const appStatePromise = this.startPublishingLiveUpdates(
|
|
265
|
-
keyMirrors.toClientMessageType.app_state,
|
|
266
|
-
async () => {
|
|
267
|
-
const payload = await getAppStatePayload();
|
|
268
|
-
return buildAppStateMessage(this.clientId, payload, txId);
|
|
269
|
-
},
|
|
270
|
-
txId
|
|
271
|
-
);
|
|
272
|
-
promises.push(appStatePromise);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (appLogs !== undefined) {
|
|
277
|
-
const currentAppLogs = this.getAppLogsLiveUpdates();
|
|
278
|
-
if (appLogs.toggle && currentAppLogs !== true) {
|
|
279
|
-
// Don't wait for this call to finish since it loops until disabled
|
|
280
|
-
const appLogPromise = this.startAppLogStream(appLogs.projectId, txId);
|
|
281
|
-
promises.push(appLogPromise);
|
|
282
|
-
} else {
|
|
283
|
-
this.appLogStreams.delete(appLogs.projectId);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return promises;
|
|
155
|
+
private generateIntervalKey(
|
|
156
|
+
intervalType: ToClientMessageTypeValue,
|
|
157
|
+
transactionId?: string
|
|
158
|
+
): string {
|
|
159
|
+
return intervalType + `${transactionId ? ':' + transactionId : ''}`;
|
|
287
160
|
}
|
|
288
161
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { logger } from '../util/logger';
|
|
2
|
+
|
|
3
|
+
export interface MessageHandler<T = any> {
|
|
4
|
+
handle(payload: T, topic?: string): void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class MessageDispatcher<T = any> {
|
|
8
|
+
private handlers: Map<string, MessageHandler<T>> = new Map();
|
|
9
|
+
|
|
10
|
+
public registerHandler(topic: string, handler: MessageHandler): void {
|
|
11
|
+
this.handlers.set(topic, handler);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public dispatch(topic: string, payload: T): void {
|
|
15
|
+
const handler = this.handlers.get(topic);
|
|
16
|
+
if (handler) {
|
|
17
|
+
handler.handle(payload, topic);
|
|
18
|
+
} else {
|
|
19
|
+
this.handleUnknownMessage(topic, payload);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Handle unknown or unregistered message topic
|
|
24
|
+
private handleUnknownMessage(topic: string, payload: T): void {
|
|
25
|
+
logger.error(
|
|
26
|
+
`No handler found for topic/type: ${topic} for message ${JSON.stringify(
|
|
27
|
+
payload,
|
|
28
|
+
null,
|
|
29
|
+
2
|
|
30
|
+
)}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DeviceAgentStatusShadowUpdate,
|
|
3
|
+
PassthroughStatusValue
|
|
4
|
+
} from '@alwaysai/device-agent-schemas/lib/shadow-schema';
|
|
5
|
+
import { stringifyError } from 'alwaysai/lib/util';
|
|
1
6
|
import * as amqp from 'amqplib';
|
|
7
|
+
import { ALWAYSAI_ANALYTICS_PASSTHROUGH } from '../environment';
|
|
2
8
|
import {
|
|
3
9
|
LOCAL_CONNECTION_HOST,
|
|
4
10
|
LOCAL_CONNECTION_PORT,
|
|
5
11
|
LOCAL_CONNECTION_ROUTING_KEY
|
|
6
12
|
} from '../local-connection/constants';
|
|
7
13
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
setupRabbitMQContainer,
|
|
15
|
+
stopRabbitMQContainer
|
|
10
16
|
} from '../local-connection/rabbitmq-connection';
|
|
11
17
|
import { logger } from '../util/logger';
|
|
12
18
|
import sleep from '../util/sleep';
|
|
13
19
|
import { Publisher } from './publisher';
|
|
20
|
+
import { ShadowHandler } from './shadow-handler';
|
|
14
21
|
|
|
15
22
|
const messageQueue: any[] = [];
|
|
16
23
|
const ackQueue: any[] = [];
|
|
@@ -18,12 +25,14 @@ const MAX_LOCAL_CONNECTION_ATTEMPTS = 10;
|
|
|
18
25
|
|
|
19
26
|
export class PassthroughHandler {
|
|
20
27
|
public publisher: Publisher;
|
|
28
|
+
public shadowHandler: ShadowHandler;
|
|
21
29
|
public connection: amqp.Connection | undefined;
|
|
22
30
|
public channel: amqp.Channel;
|
|
23
31
|
public packetQueue;
|
|
24
32
|
|
|
25
|
-
constructor(publisher: Publisher) {
|
|
33
|
+
constructor(publisher: Publisher, shadowHandler: ShadowHandler) {
|
|
26
34
|
this.publisher = publisher;
|
|
35
|
+
this.shadowHandler = shadowHandler;
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
runChannel = async () => {
|
|
@@ -79,9 +88,13 @@ export class PassthroughHandler {
|
|
|
79
88
|
);
|
|
80
89
|
}
|
|
81
90
|
} catch (e) {
|
|
82
|
-
logger.error(
|
|
91
|
+
logger.error(
|
|
92
|
+
`There was a problem parsing RabbitMQ packet!\n${stringifyError(
|
|
93
|
+
e
|
|
94
|
+
)}`
|
|
95
|
+
);
|
|
83
96
|
this.channel.ack(msg);
|
|
84
|
-
logger.debug(
|
|
97
|
+
logger.debug('Problematic packet was acknowledged');
|
|
85
98
|
}
|
|
86
99
|
}
|
|
87
100
|
}
|
|
@@ -138,21 +151,45 @@ export class PassthroughHandler {
|
|
|
138
151
|
}
|
|
139
152
|
}
|
|
140
153
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
154
|
+
private async publishPassthroughStatusUpdate(
|
|
155
|
+
status: PassthroughStatusValue,
|
|
156
|
+
message?: string
|
|
157
|
+
) {
|
|
158
|
+
const deviceAgentPassthroughStatus: DeviceAgentStatusShadowUpdate = {
|
|
159
|
+
passthrough: {
|
|
160
|
+
status: status,
|
|
161
|
+
message: message ?? ''
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
await this.shadowHandler.updateDeviceAgentStatusShadow(
|
|
165
|
+
deviceAgentPassthroughStatus
|
|
144
166
|
);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
`There was a problem maintaining RabbitMQ connection: ${error}`
|
|
152
|
-
);
|
|
153
|
-
throw new Error(
|
|
154
|
-
`There was a problem maintaining RabbitMQ connection: ${error}`
|
|
167
|
+
}
|
|
168
|
+
|
|
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}`
|
|
155
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));
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
await this.publishPassthroughStatusUpdate('disabled');
|
|
156
193
|
}
|
|
157
194
|
}
|
|
158
195
|
}
|