@alwaysai/device-agent 2.0.1 → 2.0.2
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/install.d.ts.map +1 -1
- package/lib/application-control/install.js +5 -1
- package/lib/application-control/install.js.map +1 -1
- package/lib/cloud-connection/connection-manager.d.ts +4 -6
- package/lib/cloud-connection/connection-manager.d.ts.map +1 -1
- package/lib/cloud-connection/connection-manager.js +23 -35
- package/lib/cloud-connection/connection-manager.js.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +3 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +51 -40
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/publisher.d.ts +3 -2
- package/lib/cloud-connection/publisher.d.ts.map +1 -1
- package/lib/cloud-connection/publisher.js +8 -4
- package/lib/cloud-connection/publisher.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.d.ts +1 -0
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
- package/lib/cloud-connection/shadow-handler.js +3 -0
- package/lib/cloud-connection/shadow-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.test.js +5 -2
- package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.d.ts +1 -3
- package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
- package/lib/cloud-connection/transaction-manager.js +1 -2
- package/lib/cloud-connection/transaction-manager.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.test.js +12 -24
- package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
- package/lib/environment.d.ts +3 -0
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js +12 -1
- package/lib/environment.js.map +1 -1
- package/lib/jobs/job-handler.d.ts +1 -1
- package/lib/jobs/job-handler.d.ts.map +1 -1
- package/lib/jobs/job-handler.js +4 -4
- package/lib/jobs/job-handler.js.map +1 -1
- package/lib/subcommands/app/analytics.d.ts.map +1 -1
- package/lib/subcommands/app/analytics.js +2 -3
- package/lib/subcommands/app/analytics.js.map +1 -1
- package/lib/subcommands/app/env-vars.d.ts.map +1 -1
- package/lib/subcommands/app/env-vars.js +4 -6
- package/lib/subcommands/app/env-vars.js.map +1 -1
- package/lib/subcommands/app/models.d.ts.map +1 -1
- package/lib/subcommands/app/models.js +2 -3
- 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 +4 -6
- package/lib/subcommands/app/shadow.js.map +1 -1
- package/lib/subcommands/app/version.d.ts.map +1 -1
- package/lib/subcommands/app/version.js +6 -9
- package/lib/subcommands/app/version.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +16 -4
- package/src/application-control/install.ts +8 -3
- package/src/cloud-connection/connection-manager.ts +24 -37
- package/src/cloud-connection/device-agent-cloud-connection.ts +94 -88
- package/src/cloud-connection/publisher.ts +28 -23
- package/src/cloud-connection/shadow-handler.test.ts +6 -2
- package/src/cloud-connection/shadow-handler.ts +4 -0
- package/src/cloud-connection/transaction-manager.test.ts +13 -44
- package/src/cloud-connection/transaction-manager.ts +1 -4
- package/src/environment.ts +18 -0
- package/src/jobs/job-handler.ts +4 -4
- package/src/subcommands/app/analytics.ts +2 -3
- package/src/subcommands/app/env-vars.ts +4 -6
- package/src/subcommands/app/models.ts +2 -3
- package/src/subcommands/app/shadow.ts +4 -6
- package/src/subcommands/app/version.ts +7 -8
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EnvVars,
|
|
3
|
-
ToClientStatusResponseMessage,
|
|
4
|
-
generateTxId,
|
|
5
|
-
keyMirrors,
|
|
6
|
-
buildToClientStatusResponseMessage
|
|
7
|
-
} from '@alwaysai/device-agent-schemas';
|
|
1
|
+
import { EnvVars, generateTxId } from '@alwaysai/device-agent-schemas';
|
|
8
2
|
import { TransactionManager } from './transaction-manager';
|
|
9
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
-
import { Publisher } from './publisher';
|
|
11
4
|
import { LiveUpdatesHandler } from './live-updates-handler';
|
|
12
5
|
import { AppConfigUpdate, ShadowUpdate } from './shadow-handler';
|
|
13
6
|
import { AppContent } from './device-agent-message-handler';
|
|
14
7
|
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
15
8
|
|
|
16
|
-
const mockClient = {
|
|
17
|
-
publish: jest.fn()
|
|
18
|
-
};
|
|
19
|
-
const clientId = 'test-client';
|
|
20
|
-
|
|
21
9
|
const mockLiveUpdatesHandler = {
|
|
22
10
|
enable: jest.fn(),
|
|
23
11
|
disable: jest.fn()
|
|
@@ -25,7 +13,6 @@ const mockLiveUpdatesHandler = {
|
|
|
25
13
|
|
|
26
14
|
describe('Test Transaction Manager', () => {
|
|
27
15
|
let txnMgr: TransactionManager;
|
|
28
|
-
let publisher: Publisher;
|
|
29
16
|
const func_complete: () => Promise<boolean> = jest
|
|
30
17
|
.fn()
|
|
31
18
|
.mockResolvedValue(true);
|
|
@@ -34,8 +21,7 @@ describe('Test Transaction Manager', () => {
|
|
|
34
21
|
.mockResolvedValue(false);
|
|
35
22
|
|
|
36
23
|
beforeEach(() => {
|
|
37
|
-
|
|
38
|
-
txnMgr = new TransactionManager(publisher, mockLiveUpdatesHandler);
|
|
24
|
+
txnMgr = new TransactionManager(mockLiveUpdatesHandler);
|
|
39
25
|
jest.clearAllMocks();
|
|
40
26
|
});
|
|
41
27
|
|
|
@@ -63,29 +49,22 @@ describe('Test Transaction Manager', () => {
|
|
|
63
49
|
const txId = generateTxId();
|
|
64
50
|
const projectId = generateRandomProjectId();
|
|
65
51
|
|
|
66
|
-
const successFn = (
|
|
67
|
-
|
|
68
|
-
clientId,
|
|
69
|
-
{ status: keyMirrors.statusResponse.success },
|
|
70
|
-
txId
|
|
71
|
-
);
|
|
72
|
-
publisher.publishToClient(msg);
|
|
73
|
-
};
|
|
52
|
+
const successFn = jest.fn();
|
|
53
|
+
const errorFn = jest.fn();
|
|
74
54
|
|
|
75
55
|
await txnMgr.runTransactionStep({
|
|
76
56
|
func: func_complete,
|
|
77
57
|
projectId,
|
|
78
58
|
txId,
|
|
79
59
|
start: true,
|
|
80
|
-
successFn
|
|
60
|
+
successFn,
|
|
61
|
+
errorFn
|
|
81
62
|
});
|
|
82
63
|
expect(txnMgr.isOngoingTransaction(txId)).toBe(false);
|
|
83
64
|
expect(txnMgr.isOngoingTransactionForProjectID(projectId)).toBe(false);
|
|
84
65
|
expect(txnMgr.isAnyOngoingTransaction()).toBe(false);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
);
|
|
88
|
-
expect(msg.payload.status).toBe(keyMirrors.statusResponse.success);
|
|
66
|
+
expect(successFn).toBeCalledTimes(1);
|
|
67
|
+
expect(errorFn).toBeCalledTimes(0);
|
|
89
68
|
});
|
|
90
69
|
|
|
91
70
|
test('Start a new transaction and complete in second step', async () => {
|
|
@@ -214,17 +193,8 @@ describe('Test Transaction Manager', () => {
|
|
|
214
193
|
const txId = generateTxId();
|
|
215
194
|
const projectId = generateRandomProjectId();
|
|
216
195
|
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
clientId,
|
|
220
|
-
{
|
|
221
|
-
status: keyMirrors.statusResponse.failure,
|
|
222
|
-
message: errorMsg
|
|
223
|
-
},
|
|
224
|
-
txId
|
|
225
|
-
);
|
|
226
|
-
publisher.publishToClient(msg);
|
|
227
|
-
};
|
|
196
|
+
const successFn = jest.fn();
|
|
197
|
+
const errorFn = jest.fn();
|
|
228
198
|
|
|
229
199
|
await txnMgr.runTransactionStep({
|
|
230
200
|
func: jest.fn().mockImplementation(() => {
|
|
@@ -234,15 +204,14 @@ describe('Test Transaction Manager', () => {
|
|
|
234
204
|
txId,
|
|
235
205
|
start: true,
|
|
236
206
|
stepName: 'step1',
|
|
207
|
+
successFn,
|
|
237
208
|
errorFn
|
|
238
209
|
});
|
|
239
210
|
expect(txnMgr.isOngoingTransaction(txId)).toBe(false);
|
|
240
211
|
expect(txnMgr.isOngoingTransactionForProjectID(projectId)).toBe(false);
|
|
241
212
|
expect(txnMgr.isAnyOngoingTransaction()).toBe(false);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
245
|
-
expect(msg.payload.status).toBe(keyMirrors.statusResponse.failure);
|
|
213
|
+
expect(successFn).toBeCalledTimes(0);
|
|
214
|
+
expect(errorFn).toBeCalledTimes(1);
|
|
246
215
|
});
|
|
247
216
|
|
|
248
217
|
test('Complete ongoing transaction', async () => {
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
keyMirrors
|
|
5
5
|
} from '@alwaysai/device-agent-schemas';
|
|
6
6
|
import { LiveUpdatesHandler } from './live-updates-handler';
|
|
7
|
-
import { Publisher } from './publisher';
|
|
8
7
|
import { logger } from '../util/logger';
|
|
9
8
|
import { keyMirror, stringifyError } from 'alwaysai/lib/util';
|
|
10
9
|
import { CodedError } from '@carnesen/coded-error';
|
|
@@ -30,7 +29,6 @@ export class TransactionManager {
|
|
|
30
29
|
private detailsByTx: Record<string, TransactionDetails> = {};
|
|
31
30
|
private detailsByProject: Record<string, TransactionDetails> = {};
|
|
32
31
|
private readonly liveUpdatesHandler: LiveUpdatesHandler;
|
|
33
|
-
private publisher: Publisher;
|
|
34
32
|
private async startTransaction(
|
|
35
33
|
txId: string,
|
|
36
34
|
projectId: string,
|
|
@@ -96,10 +94,9 @@ export class TransactionManager {
|
|
|
96
94
|
logger.info(`Updated transaction:\n${JSON.stringify(txDetails, null, 2)}`);
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
constructor(
|
|
97
|
+
constructor(liveUpdatesHandler: LiveUpdatesHandler) {
|
|
100
98
|
this.detailsByTx = {};
|
|
101
99
|
this.detailsByProject = {};
|
|
102
|
-
this.publisher = publisher;
|
|
103
100
|
this.liveUpdatesHandler = liveUpdatesHandler;
|
|
104
101
|
}
|
|
105
102
|
|
package/src/environment.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { TargetHardware } from 'alwaysai/lib/core/app';
|
|
1
2
|
import { platform } from 'os';
|
|
3
|
+
import { logger } from './util/logger';
|
|
2
4
|
|
|
3
5
|
export const ALWAYSAI_OS_PLATFORM = parseOsPlatform(
|
|
4
6
|
process.env.ALWAYSAI_OS_PLATFORM
|
|
@@ -22,6 +24,22 @@ export const ALWAYSAI_LOCAL_CONNECTION_PORT =
|
|
|
22
24
|
process.env.ALWAYSAI_LOCAL_CONNECTION_PORT;
|
|
23
25
|
export const ALWAYSAI_LOCAL_CONNECTION_ANALYTICS_ROUTING_KEY =
|
|
24
26
|
process.env.ALWAYSAI_LOCAL_CONNECTION_ANALYTICS_ROUTING_KEY;
|
|
27
|
+
export const ALWAYSAI_TARGET_HW_OVERRIDE =
|
|
28
|
+
process.env.ALWAYSAI_TARGET_HW_OVERRIDE;
|
|
29
|
+
|
|
30
|
+
export function parseTargetHW(
|
|
31
|
+
hardwareType?: string
|
|
32
|
+
): TargetHardware | undefined {
|
|
33
|
+
const target = hardwareType ? TargetHardware[hardwareType] : undefined;
|
|
34
|
+
if (!target && hardwareType) {
|
|
35
|
+
logger.error(
|
|
36
|
+
`Incorrect TargetHardware: ${hardwareType}. Ignoring the environment variable. Allowed TargetHardware types: ${Object.keys(
|
|
37
|
+
TargetHardware
|
|
38
|
+
)}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
25
43
|
|
|
26
44
|
function parseOsPlatform(str: string | undefined): NodeJS.Platform {
|
|
27
45
|
switch (str) {
|
package/src/jobs/job-handler.ts
CHANGED
|
@@ -36,7 +36,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
|
|
|
36
36
|
private jobId = '';
|
|
37
37
|
|
|
38
38
|
public async handle(message: any, topic: string): Promise<void> {
|
|
39
|
-
const TOPICS = this.
|
|
39
|
+
const TOPICS = this.getJobTopics();
|
|
40
40
|
|
|
41
41
|
try {
|
|
42
42
|
switch (topic) {
|
|
@@ -54,7 +54,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
getJobTopics() {
|
|
58
58
|
const TOPICS = {
|
|
59
59
|
NOTIFY_NEXT: `$aws/things/${this.clientId}/jobs/notify-next`,
|
|
60
60
|
START_NEXT: `$aws/things/${this.clientId}/jobs/start-next`,
|
|
@@ -67,7 +67,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
|
|
|
67
67
|
private async notifyNext(message: any): Promise<void> {
|
|
68
68
|
// Triggers when a job is completed and we need to notify the next job
|
|
69
69
|
logger.info('Invoking NOTIFY_NEXT handler');
|
|
70
|
-
const TOPICS = this.
|
|
70
|
+
const TOPICS = this.getJobTopics();
|
|
71
71
|
this.publisher.publish(TOPICS.START_NEXT, JSON.stringify({}));
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -121,7 +121,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
private updateJobStatus(status: string, message?: string): void {
|
|
124
|
-
const { UPDATE } = this.
|
|
124
|
+
const { UPDATE } = this.getJobTopics();
|
|
125
125
|
const payload = {
|
|
126
126
|
status,
|
|
127
127
|
statusDetails: {
|
|
@@ -80,6 +80,7 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
|
|
|
80
80
|
appConfig: JSON.stringify(appCfg) // Pack app config as string as dictated by schema
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
|
+
await deviceAgent.waitForConnection();
|
|
83
84
|
deviceAgent.publisher.publish(
|
|
84
85
|
getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
|
|
85
86
|
JSON.stringify(
|
|
@@ -92,9 +93,7 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
|
|
|
92
93
|
// Sleep for extra time to ensure time for shadow response
|
|
93
94
|
await sleep(10000);
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
await sleep(1000);
|
|
97
|
-
}
|
|
96
|
+
await deviceAgent.waitForCmd(project);
|
|
98
97
|
await deviceAgent.stop();
|
|
99
98
|
}
|
|
100
99
|
});
|
|
@@ -66,6 +66,7 @@ export const setEnvCliLeaf = CliLeaf({
|
|
|
66
66
|
envVars: JSON.stringify(envVars)
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
|
+
await deviceAgent.waitForConnection();
|
|
69
70
|
deviceAgent.publisher.publish(
|
|
70
71
|
getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
|
|
71
72
|
JSON.stringify(
|
|
@@ -78,9 +79,7 @@ export const setEnvCliLeaf = CliLeaf({
|
|
|
78
79
|
// Sleep for extra time to ensure time for shadow response
|
|
79
80
|
await sleep(10000);
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
await sleep(1000);
|
|
83
|
-
}
|
|
82
|
+
await deviceAgent.waitForCmd(projectId);
|
|
84
83
|
await deviceAgent.stop();
|
|
85
84
|
}
|
|
86
85
|
});
|
|
@@ -128,6 +127,7 @@ export const rmEnvCliLeaf = CliLeaf({
|
|
|
128
127
|
envVars: JSON.stringify(newEnvs)
|
|
129
128
|
}
|
|
130
129
|
};
|
|
130
|
+
await deviceAgent.waitForConnection();
|
|
131
131
|
deviceAgent.publisher.publish(
|
|
132
132
|
getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
|
|
133
133
|
JSON.stringify(
|
|
@@ -140,9 +140,7 @@ export const rmEnvCliLeaf = CliLeaf({
|
|
|
140
140
|
// Sleep for extra time to ensure time for shadow response
|
|
141
141
|
await sleep(10000);
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
await sleep(1000);
|
|
145
|
-
}
|
|
143
|
+
await deviceAgent.waitForCmd(projectId);
|
|
146
144
|
await deviceAgent.stop();
|
|
147
145
|
}
|
|
148
146
|
});
|
|
@@ -54,6 +54,7 @@ export const addModelCliLeaf = CliLeaf({
|
|
|
54
54
|
appConfig: JSON.stringify(newAppCfg)
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
+
await deviceAgent.waitForConnection();
|
|
57
58
|
deviceAgent.publisher.publish(
|
|
58
59
|
getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
|
|
59
60
|
JSON.stringify(
|
|
@@ -66,9 +67,7 @@ export const addModelCliLeaf = CliLeaf({
|
|
|
66
67
|
// Sleep for extra time to ensure time for shadow response
|
|
67
68
|
await sleep(10000);
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
await sleep(1000);
|
|
71
|
-
}
|
|
70
|
+
await deviceAgent.waitForCmd(projectId);
|
|
72
71
|
await deviceAgent.stop();
|
|
73
72
|
}
|
|
74
73
|
});
|
|
@@ -14,13 +14,12 @@ export const getShadowCliLeaf = CliLeaf({
|
|
|
14
14
|
async action(_, opts) {
|
|
15
15
|
const { project } = opts;
|
|
16
16
|
const deviceAgent = new DeviceAgentCloudConnection();
|
|
17
|
+
await deviceAgent.waitForConnection();
|
|
17
18
|
deviceAgent.shadowHandler.getProjectShadowUpdates();
|
|
18
19
|
|
|
19
20
|
// 5 seconds should cover the response wait time
|
|
20
21
|
await sleep(5000);
|
|
21
|
-
|
|
22
|
-
await sleep(1000);
|
|
23
|
-
}
|
|
22
|
+
await deviceAgent.waitForCmd(project);
|
|
24
23
|
await deviceAgent.stop();
|
|
25
24
|
}
|
|
26
25
|
});
|
|
@@ -37,13 +36,12 @@ export const updateShadowCliLeaf = CliLeaf({
|
|
|
37
36
|
async action(_, opts) {
|
|
38
37
|
const { project } = opts;
|
|
39
38
|
const deviceAgent = new DeviceAgentCloudConnection();
|
|
39
|
+
await deviceAgent.waitForConnection();
|
|
40
40
|
await deviceAgent.shadowHandler.updateProjectShadow(project);
|
|
41
41
|
|
|
42
42
|
// 5 seconds should cover the response wait time
|
|
43
43
|
await sleep(5000);
|
|
44
|
-
|
|
45
|
-
await sleep(1000);
|
|
46
|
-
}
|
|
44
|
+
await deviceAgent.waitForCmd(project);
|
|
47
45
|
await deviceAgent.stop();
|
|
48
46
|
}
|
|
49
47
|
});
|
|
@@ -10,6 +10,7 @@ import { DeviceAgentCloudConnection } from '../../cloud-connection/device-agent-
|
|
|
10
10
|
import { AgentConfigFile } from '../../infrastructure/agent-config';
|
|
11
11
|
import sleep from '../../util/sleep';
|
|
12
12
|
import { logger } from '../../util/logger';
|
|
13
|
+
import { device } from 'alwaysai/lib/components';
|
|
13
14
|
|
|
14
15
|
export const listAppsCliLeaf = CliLeaf({
|
|
15
16
|
name: 'list',
|
|
@@ -81,10 +82,9 @@ export const installAppCliLeaf = CliLeaf({
|
|
|
81
82
|
envVars
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
|
-
await deviceAgent.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
85
|
+
await deviceAgent.waitForConnection();
|
|
86
|
+
await deviceAgent.sendCliCmd(topic, message);
|
|
87
|
+
await deviceAgent.waitForCmd(project);
|
|
88
88
|
await deviceAgent.stop();
|
|
89
89
|
}
|
|
90
90
|
});
|
|
@@ -112,10 +112,9 @@ export const uninstallAppCliLeaf = CliLeaf({
|
|
|
112
112
|
projectId: project
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
|
-
await deviceAgent.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
115
|
+
await deviceAgent.waitForConnection();
|
|
116
|
+
await deviceAgent.sendCliCmd(topic, message);
|
|
117
|
+
await deviceAgent.waitForCmd(project);
|
|
119
118
|
await deviceAgent.stop();
|
|
120
119
|
}
|
|
121
120
|
});
|