@mojaloop/sdk-scheme-adapter 24.13.0 → 24.14.0-snapshot.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/.yarn/cache/{@mojaloop-central-services-shared-npm-18.34.0-98deaad7cb-660f407a57.zip → @mojaloop-central-services-shared-npm-18.34.1-fc3be8e73c-f7ad2f9394.zip} +0 -0
- package/.yarn/cache/{@mojaloop-inter-scheme-proxy-cache-lib-npm-2.7.0-84455815f8-7748014a4c.zip → @mojaloop-inter-scheme-proxy-cache-lib-npm-2.9.0-cb33cd6786-fd3f20e6a7.zip} +0 -0
- package/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.46.0-e6114965b4-415afd894a.zip +0 -0
- package/.yarn/cache/@typescript-eslint-parser-npm-8.46.0-c44629050a-6838fde776.zip +0 -0
- package/.yarn/cache/@typescript-eslint-project-service-npm-8.46.0-85a4b9bb9c-de11af23ae.zip +0 -0
- package/.yarn/cache/@typescript-eslint-scope-manager-npm-8.46.0-fd8edaba78-ed85abd08c.zip +0 -0
- package/.yarn/cache/@typescript-eslint-tsconfig-utils-npm-8.46.0-8919c1f746-e78a66a854.zip +0 -0
- package/.yarn/cache/@typescript-eslint-type-utils-npm-8.46.0-dbfff922bb-5405b71b91.zip +0 -0
- package/.yarn/cache/@typescript-eslint-types-npm-8.46.0-b013400d3e-0118b0dd59.zip +0 -0
- package/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.46.0-0b10d4388a-61053bd0c3.zip +0 -0
- package/.yarn/cache/@typescript-eslint-utils-npm-8.46.0-a7d3832f43-4e0da60de3.zip +0 -0
- package/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.46.0-7d793afea5-37e6145b6a.zip +0 -0
- package/.yarn/install-state.gz +0 -0
- package/.yarn/releases/{yarn-4.10.2.cjs → yarn-4.10.3.cjs} +126 -126
- package/.yarnrc.yml +1 -1
- package/CLAUDE.md +186 -0
- package/modules/api-svc/package.json +2 -2
- package/modules/api-svc/src/ControlAgent/index.js +42 -11
- package/modules/api-svc/src/OutboundServer/handlers.js +1 -1
- package/modules/api-svc/src/config.js +1 -0
- package/modules/api-svc/src/index.js +244 -188
- package/modules/api-svc/src/lib/cache.js +3 -1
- package/modules/api-svc/src/lib/logger.js +1 -2
- package/modules/api-svc/test/unit/index.configPolling.test.js +229 -0
- package/modules/api-svc/test/unit/lib/model/InboundPingModel.test.js +2 -2
- package/modules/outbound-command-event-handler/package.json +4 -4
- package/modules/outbound-domain-event-handler/package.json +3 -3
- package/modules/private-shared-lib/package.json +4 -4
- package/package.json +4 -4
- package/{sbom-v24.12.0.csv → sbom-v24.13.0.csv} +220 -231
package/.yarnrc.yml
CHANGED
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is the Mojaloop SDK Scheme Adapter - a monorepo that provides an adapter interface between Mojaloop API compliant switches and DFSP backend platforms.
|
|
8
|
+
The project consists of multiple modules organized using Nx workspace.
|
|
9
|
+
|
|
10
|
+
## Quick Reference (Start Here)
|
|
11
|
+
|
|
12
|
+
| Task | Command | Prerequisites |
|
|
13
|
+
|------|---------|---------------|
|
|
14
|
+
| Run all tests | `yarn test` | - |
|
|
15
|
+
| Run integration tests | `yarn test:integration` | Docker running, `yarn wait-4-docker` |
|
|
16
|
+
| Run specific module test | `yarn workspace @mojaloop/sdk-scheme-adapter-api-svc run test:unit` | - |
|
|
17
|
+
| Build everything | `yarn build` | Node 22.15.1 (`nvm use`) |
|
|
18
|
+
| Start services | `yarn start` | Docker running, modules built |
|
|
19
|
+
| Update OpenAPI | `yarn build:openapi && yarn validate:api` | - |
|
|
20
|
+
| Debug main service | `yarn workspace @mojaloop/sdk-scheme-adapter-api-svc run start:debug` | Port 9229 available |
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
**Critical File Locations:**
|
|
24
|
+
- Models: `modules/api-svc/src/lib/model/`
|
|
25
|
+
- Handlers: `modules/api-svc/src/{Inbound,Outbound}Server/handlers.js`
|
|
26
|
+
- Config: `modules/*/src/config/default.json`
|
|
27
|
+
- OpenAPI templates: `modules/*/src/*_template.yaml` (edit these, not `api.yaml`)
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
This service can be referenced as `Mojaloop Connector`, `ML Connector` or `Scheme Adapter`.
|
|
31
|
+
|
|
32
|
+
### Core Modules
|
|
33
|
+
|
|
34
|
+
- **api-svc**: Main service module (JavaScript/Node.js) handling inbound/outbound HTTP APIs and core business logic
|
|
35
|
+
- **outbound-command-event-handler**: TypeScript module handling outbound command events using domain-driven design
|
|
36
|
+
- **outbound-domain-event-handler**: TypeScript module processing domain events for outbound operations
|
|
37
|
+
- **private-shared-lib**: Shared TypeScript library containing domain entities, events, and infrastructure code
|
|
38
|
+
|
|
39
|
+
### Key Components
|
|
40
|
+
|
|
41
|
+
- **Event-Driven Architecture**: Uses Kafka for event streaming between modules
|
|
42
|
+
- **State Machines**: JavaScript State Machine library for managing transfer states
|
|
43
|
+
- **Cache Layer**: Redis for distributed caching and session management
|
|
44
|
+
- **Models**: Domain models for transfers, quotes, parties, bulk operations
|
|
45
|
+
- **Event Handlers**: FSPIOP and Backend event handling for Mojaloop protocol compliance
|
|
46
|
+
- **ControlAgent**: WebSocket client for PM4ML Management API with optional failsafe polling
|
|
47
|
+
|
|
48
|
+
## Code Structure Patterns
|
|
49
|
+
|
|
50
|
+
### API Service (modules/api-svc)
|
|
51
|
+
- **Handlers**: Route handlers in `src/InboundServer/handlers.js` and `src/OutboundServer/handlers.js`
|
|
52
|
+
- **Models**: Business logic in `src/lib/model/` with models like:
|
|
53
|
+
- `TransfersModel.js` - Transfer operations
|
|
54
|
+
- `QuotesModel.js` - Quote handling
|
|
55
|
+
- `AccountsModel.js` - Account management
|
|
56
|
+
- `InboundTransfersModel.js` - Inbound transfer processing
|
|
57
|
+
- `OutboundTransfersModel.js` - Outbound transfer processing
|
|
58
|
+
- `OutboundBulkQuotesModel.js` - Bulk quote operations
|
|
59
|
+
- `OutboundBulkTransfersModel.js` - Bulk transfer operations
|
|
60
|
+
- **State Machines**: Use `PersistentStateMachine` for managing complex state transitions
|
|
61
|
+
- **Middleware**: Validation and error handling middleware in `middlewares.js`
|
|
62
|
+
- **OpenAPI Templates**: API definitions in `api_template.yaml` files, compiled to `api.yaml`
|
|
63
|
+
|
|
64
|
+
### Event Handlers (TypeScript modules)
|
|
65
|
+
- **Domain Layer**: Aggregates and entities in `src/domain/`
|
|
66
|
+
- **Application Layer**: Event handlers in `src/application/handlers/`
|
|
67
|
+
- **Infrastructure**: Kafka producers/consumers in shared lib
|
|
68
|
+
- **API Server**: Express-based APIs with OpenAPI specs
|
|
69
|
+
- **Build Process**: TypeScript compilation + file copying (YAML files)
|
|
70
|
+
|
|
71
|
+
### Testing Patterns
|
|
72
|
+
- **Unit tests**: `test/unit/` directories using Jest
|
|
73
|
+
- **Integration tests**: `test/integration/` requiring Docker services
|
|
74
|
+
- **Functional tests**: Separate test suites in `test/func_bulk/` and `test/func_iso20022/`
|
|
75
|
+
- **Mocks**: Test mocks in `test/__mocks__/`
|
|
76
|
+
- **Setup**: Test setup files like `test/unit/setup.js`
|
|
77
|
+
- **Configuration**: Jest config in individual `jest.config.js` files
|
|
78
|
+
|
|
79
|
+
## Development Commands
|
|
80
|
+
Check **[development-commands.md](./_cc/docs/development-commands.md)** file to get details about some useful commands to
|
|
81
|
+
build and setup the project, start the services, run tests, linting, deps and audit checks, etc.
|
|
82
|
+
|
|
83
|
+
## Key Libraries & Dependencies
|
|
84
|
+
|
|
85
|
+
- **@mojaloop/sdk-standard-components**: Core Mojaloop SDK components
|
|
86
|
+
- **@mojaloop/central-services-***: Mojaloop platform services
|
|
87
|
+
- **@mojaloop/api-snippets**: API specification components
|
|
88
|
+
- **javascript-state-machine**: State management for transfers
|
|
89
|
+
- **redis**: Distributed caching (v5.x)
|
|
90
|
+
- **express/koa**: HTTP servers (Express for newer modules, Koa for some services)
|
|
91
|
+
- **ajv**: JSON schema validation
|
|
92
|
+
- **convict**: Configuration management in TypeScript modules
|
|
93
|
+
- **openapi-backend**: OpenAPI request validation and routing
|
|
94
|
+
- **Package Manager**: Yarn 4.10.2 (Berry)
|
|
95
|
+
|
|
96
|
+
## Docker Environment
|
|
97
|
+
|
|
98
|
+
See [development-commands.md](./_cc/docs/development-commands.md#docker-operations) for Docker commands.
|
|
99
|
+
|
|
100
|
+
**Services:** redis (6379), kafka (9092), ml-testing-toolkit (4040/5050), mojaloop-testing-toolkit-ui (6060)
|
|
101
|
+
**Debug profile adds:** redisinsight (9001), kafka-debug-ui (9080)
|
|
102
|
+
**Main service ports:** 4000-4004, 9229 (debugger)
|
|
103
|
+
|
|
104
|
+
## Development Patterns & Notes
|
|
105
|
+
|
|
106
|
+
### Module Architecture
|
|
107
|
+
- **api-svc**: JavaScript-based, legacy module with core functionality
|
|
108
|
+
- **Shared lib**: Private workspace package for cross-module code
|
|
109
|
+
|
|
110
|
+
### Event Sourcing
|
|
111
|
+
Commands → `outbound-command-event-handler` → Domain events → `outbound-domain-event-handler`
|
|
112
|
+
**Kafka topics:** `topic-sdk-outbound-command-events`, `topic-sdk-outbound-domain-events`
|
|
113
|
+
|
|
114
|
+
### State Management
|
|
115
|
+
**Redis:** State machine persistence, distributed cache, cross-module communication, bulk transaction tracking
|
|
116
|
+
**Pattern:** `PersistentStateMachine` class for complex state transitions
|
|
117
|
+
|
|
118
|
+
### OpenAPI Workflow
|
|
119
|
+
1. Edit `*_template.yaml` files (not generated `api.yaml`)
|
|
120
|
+
2. Run `yarn build:openapi` to compile templates
|
|
121
|
+
3. Validate with `yarn validate:api`
|
|
122
|
+
4. Uses `@redocly/openapi-cli` for bundling
|
|
123
|
+
|
|
124
|
+
### Testing Workflow
|
|
125
|
+
1. **Unit tests**: Run locally without dependencies
|
|
126
|
+
2. **Integration tests**: Require Docker services (Redis, Kafka)
|
|
127
|
+
3. **Functional tests**: Full end-to-end scenarios with TTK
|
|
128
|
+
4. Use `yarn wait-4-docker` to ensure services are ready
|
|
129
|
+
|
|
130
|
+
## Common Development Tasks
|
|
131
|
+
|
|
132
|
+
See [development-commands.md](./_cc/docs/development-commands.md) for all commands and [common-workflows.md](./_cc/docs/common-workflows.md) for step-by-step guides.
|
|
133
|
+
|
|
134
|
+
## For AI Assistants (Memory Management Hints)
|
|
135
|
+
|
|
136
|
+
**Always Re-read Before:**
|
|
137
|
+
- Modifying OpenAPI specs → Review OpenAPI Workflow section first
|
|
138
|
+
- Running integration tests → Verify Docker prerequisites and Testing Workflow
|
|
139
|
+
- Making state machine changes → Review api-svc-06-state-management.md
|
|
140
|
+
- Debugging test failures → Check development-commands.md for troubleshooting
|
|
141
|
+
|
|
142
|
+
**Cache (Low Change Frequency):**
|
|
143
|
+
- Architecture: 3 TypeScript modules (command-handler, domain-handler, shared-lib) + api-svc (JavaScript)
|
|
144
|
+
- Event flow: Command events → outbound-command-event-handler → Domain events → outbound-domain-event-handler
|
|
145
|
+
- Redis patterns: State machines, distributed cache, pub/sub, bulk transaction tracking
|
|
146
|
+
- Kafka topics: `topic-sdk-outbound-command-events`, `topic-sdk-outbound-domain-events`
|
|
147
|
+
- Package manager: Yarn 4.10.2 (Berry)
|
|
148
|
+
- Node version: 22.15.1
|
|
149
|
+
|
|
150
|
+
**Key Patterns to Remember:**
|
|
151
|
+
- Edit `*_template.yaml` files, NEVER edit generated `api.yaml` files
|
|
152
|
+
- State machines use `PersistentStateMachine` class backed by Redis
|
|
153
|
+
- Integration tests require Docker services - use `yarn wait-4-docker`
|
|
154
|
+
- Use workspace syntax: `yarn workspace @mojaloop/sdk-scheme-adapter-<module> run <command>`
|
|
155
|
+
- Nx caching enabled for builds/tests - use `--skip-nx-cache` to bypass
|
|
156
|
+
|
|
157
|
+
**When Uncertain:**
|
|
158
|
+
- Ask user ANY clarifying questions
|
|
159
|
+
- Check Quick Reference section at top of this file
|
|
160
|
+
- Consult api-svc-01-overview.md for 30-minute onboarding
|
|
161
|
+
- Use development-commands.md for command reference
|
|
162
|
+
- See common-workflows.md for step-by-step task guides
|
|
163
|
+
|
|
164
|
+
## Documentation
|
|
165
|
+
|
|
166
|
+
### API-SVC Module Documentation
|
|
167
|
+
|
|
168
|
+
Comprehensive documentation for the `api-svc` module (core service handling inbound/outbound APIs):
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
| Document | Description |
|
|
172
|
+
|----------|-------------|
|
|
173
|
+
| **[api-svc-01-overview.md](./_cc/docs/api-svc/api-svc-01-overview.md)** | Overview, quick start guide, 30-minute onboarding with core concepts and transfer flows |
|
|
174
|
+
| **[api-svc-02-architecture.md](./_cc/docs/api-svc/api-svc-02-architecture.md)** | System architecture, component design, configuration system, startup sequence |
|
|
175
|
+
| **[api-svc-03-inbound-server.md](./_cc/docs/api-svc/api-svc-03-inbound-server.md)** | Inbound server handling async FSPIOP callbacks from Mojaloop switch |
|
|
176
|
+
| **[api-svc-04-outbound-server.md](./_cc/docs/api-svc/api-svc-04-outbound-server.md)** | Outbound server providing synchronous REST API for DFSP backends |
|
|
177
|
+
| **[api-svc-05-models.md](./_cc/docs/api-svc/api-svc-05-models.md)** | Business logic models orchestrating party lookups, quotes, transfers, bulk operations |
|
|
178
|
+
| **[api-svc-06-state-management.md](./_cc/docs/api-svc/api-svc-06-state-management.md)** | Redis-backed state machines, pub/sub patterns, key patterns, recovery behavior |
|
|
179
|
+
| **[api-svc-07-control-agent.md](./_cc/docs/api-svc/api-svc-07-control-agent.md)** | WebSocket client for PM4ML Management API dynamic configuration |
|
|
180
|
+
| **[api-svc-08-error-handling.md](./_cc/docs/api-svc/api-svc-08-error-handling.md)** | Error taxonomy, Mojaloop error codes, handling patterns, logging strategies |
|
|
181
|
+
| **[api-svc-09-core-dependencies.md](./_cc/docs/api-svc/api-svc-09-core-dependencies.md)** | Core dependencies including @mojaloop/sdk-standard-components, JWS, ILP, OIDC |
|
|
182
|
+
| **[api-svc-10-service-lifecycle.md](./_cc/docs/api-svc/api-svc-10-service-lifecycle.md)** | Service startup/shutdown sequences, component bootstrap order, configuration sources, hot reload |
|
|
183
|
+
| **[api-svc-11-event-handlers.md](./_cc/docs/api-svc/api-svc-11-event-handlers.md)** | Kafka event handlers for domain/command events integration with TypeScript modules |
|
|
184
|
+
| **[api-svc-12-testing.md](./_cc/docs/api-svc/api-svc-12-testing.md)** | Testing strategy covering unit, integration, and functional tests |
|
|
185
|
+
| **[api-svc-13-deployment.md](./_cc/docs/api-svc/api-svc-13-deployment.md)** | Kubernetes deployment with Helm charts, production configuration, monitoring |
|
|
186
|
+
| **[api-svc-14-examples.md](./_cc/docs/api-svc/api-svc-14-examples.md)** | Practical examples: outbound/inbound transfers, error handling, bulk operations, auto-accept |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/sdk-scheme-adapter-api-svc",
|
|
3
|
-
"version": "21.0.0-snapshot.
|
|
3
|
+
"version": "21.0.0-snapshot.72",
|
|
4
4
|
"description": "An adapter for connecting to Mojaloop API enabled switches.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@mojaloop/central-services-error-handling": "13.1.3",
|
|
69
69
|
"@mojaloop/central-services-logger": "11.10.1",
|
|
70
70
|
"@mojaloop/central-services-metrics": "12.8.0",
|
|
71
|
-
"@mojaloop/central-services-shared": "18.34.
|
|
71
|
+
"@mojaloop/central-services-shared": "18.34.1",
|
|
72
72
|
"@mojaloop/event-sdk": "14.8.0",
|
|
73
73
|
"@mojaloop/logging-bc-client-lib": "0.5.8",
|
|
74
74
|
"@mojaloop/ml-schema-transformer-lib": "2.7.8",
|
|
@@ -40,12 +40,15 @@
|
|
|
40
40
|
// the current configuration to
|
|
41
41
|
|
|
42
42
|
const ws = require('ws');
|
|
43
|
+
const _ = require('lodash');
|
|
43
44
|
const jsonPatch = require('fast-json-patch');
|
|
45
|
+
const safeStringify = require('fast-safe-stringify');
|
|
44
46
|
const { generateSlug } = require('random-word-slugs');
|
|
45
|
-
const _ = require('lodash');
|
|
46
47
|
|
|
47
48
|
const FORCE_WS_CLOSE_TIMEOUT_MS = 5000;
|
|
48
49
|
|
|
50
|
+
const cloneJson = (obj) => JSON.parse(safeStringify(obj));
|
|
51
|
+
|
|
49
52
|
/**************************************************************************
|
|
50
53
|
* The message protocol messages, verbs, and errors
|
|
51
54
|
*************************************************************************/
|
|
@@ -77,7 +80,7 @@ const EVENT = {
|
|
|
77
80
|
/**************************************************************************
|
|
78
81
|
* Private convenience functions
|
|
79
82
|
*************************************************************************/
|
|
80
|
-
const serialise =
|
|
83
|
+
const serialise = safeStringify;
|
|
81
84
|
const deserialise = (msg) => {
|
|
82
85
|
//reviver function
|
|
83
86
|
return JSON.parse(msg.toString(), (k, v) => {
|
|
@@ -145,7 +148,7 @@ class Client extends ws {
|
|
|
145
148
|
*/
|
|
146
149
|
constructor({ address = 'localhost', port, logger, appConfig }) {
|
|
147
150
|
super(`ws://${address}:${port}`);
|
|
148
|
-
this._logger = logger.push({ component: '
|
|
151
|
+
this._logger = logger.push({ component: 'ControlClientWs' });
|
|
149
152
|
this._appConfig = appConfig;
|
|
150
153
|
}
|
|
151
154
|
|
|
@@ -173,28 +176,30 @@ class Client extends ws {
|
|
|
173
176
|
async receive() {
|
|
174
177
|
return new Promise((resolve) => this.once('message', (data) => {
|
|
175
178
|
const msg = deserialise(data);
|
|
176
|
-
this._logger.
|
|
179
|
+
this._logger.push({ msg }).debug('Received and deserialized ws message:');
|
|
177
180
|
resolve(msg);
|
|
178
181
|
}));
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
// Close connection
|
|
182
185
|
async stop() {
|
|
183
|
-
this._logger.
|
|
186
|
+
this._logger.verbose('Control client shutting down...');
|
|
184
187
|
return new Promise((resolve) => {
|
|
185
188
|
let timer = setTimeout(() => {
|
|
186
|
-
this._logger.
|
|
189
|
+
this._logger.warn(`Control client forced to close after ${FORCE_WS_CLOSE_TIMEOUT_MS}ms`);
|
|
190
|
+
this.terminate();
|
|
187
191
|
timer = null;
|
|
188
192
|
resolve(false);
|
|
189
193
|
}, FORCE_WS_CLOSE_TIMEOUT_MS);
|
|
190
194
|
|
|
191
195
|
this.once('close', () => {
|
|
192
|
-
this._logger.
|
|
196
|
+
this._logger.info('Control client is closed');
|
|
193
197
|
if (timer) clearTimeout(timer);
|
|
198
|
+
this.removeAllListeners();
|
|
194
199
|
resolve(true);
|
|
195
200
|
});
|
|
196
201
|
this.once('error', (error) => {
|
|
197
|
-
this._logger.
|
|
202
|
+
this._logger.warn('Control client failed to close:', error);
|
|
198
203
|
if (timer) clearTimeout(timer);
|
|
199
204
|
resolve(false);
|
|
200
205
|
});
|
|
@@ -203,6 +208,23 @@ class Client extends ws {
|
|
|
203
208
|
});
|
|
204
209
|
}
|
|
205
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Call the Connector Manager in Management API to get the updated config
|
|
213
|
+
*/
|
|
214
|
+
async getUpdatedConfig() { // clarify naming - why config is updated?
|
|
215
|
+
this._logger.info(`Getting updated config from Management API at ${this.url}...`);
|
|
216
|
+
const wsSendResponse = await this.send(build.CONFIGURATION.READ());
|
|
217
|
+
this._logger.debug('wsSendResponse: ', { wsSendResponse });
|
|
218
|
+
|
|
219
|
+
const wsReceivedData = (await this.receive())?.data;
|
|
220
|
+
this._logger.debug('wsReceivedData: ', { wsReceivedData });
|
|
221
|
+
|
|
222
|
+
if (!wsReceivedData) this._logger.warn('no updatedConfigFromMgmtAPI');
|
|
223
|
+
else this._logger.info('updatedConfigFromMgmtAPI keys:', { updatedConfigFromMgmtAPIKeys: Object.keys(wsReceivedData) });
|
|
224
|
+
|
|
225
|
+
return wsReceivedData;
|
|
226
|
+
}
|
|
227
|
+
|
|
206
228
|
// Handle incoming message from the server.
|
|
207
229
|
_handle(data) {
|
|
208
230
|
// TODO: json-schema validation of received message- should be pretty straight-forward
|
|
@@ -211,7 +233,7 @@ class Client extends ws {
|
|
|
211
233
|
try {
|
|
212
234
|
msg = deserialise(data);
|
|
213
235
|
} catch {
|
|
214
|
-
this._logger.
|
|
236
|
+
this._logger.warn('failed to parse received message: ', { data });
|
|
215
237
|
this.send(build.ERROR.NOTIFY.JSON_PARSE_ERROR());
|
|
216
238
|
}
|
|
217
239
|
this._logger.isDebugEnabled && this._logger.push({ msg }).debug('Handling received message');
|
|
@@ -219,14 +241,14 @@ class Client extends ws {
|
|
|
219
241
|
case MESSAGE.CONFIGURATION:
|
|
220
242
|
switch (msg.verb) {
|
|
221
243
|
case VERB.NOTIFY: {
|
|
222
|
-
const dup =
|
|
244
|
+
const dup = cloneJson(this._appConfig); // fast-json-patch explicitly mutates
|
|
223
245
|
_.merge(dup, msg.data);
|
|
224
246
|
this._logger.isDebugEnabled && this._logger.push({ oldConf: this._appConfig, newConf: dup }).debug(`Emitting new agent configuration [${VERB.NOTIFY}]`);
|
|
225
247
|
this.emit(EVENT.RECONFIGURE, dup);
|
|
226
248
|
break;
|
|
227
249
|
}
|
|
228
250
|
case VERB.PATCH: {
|
|
229
|
-
const dup =
|
|
251
|
+
const dup = cloneJson(this._appConfig); // fast-json-patch explicitly mutates
|
|
230
252
|
jsonPatch.applyPatch(dup, msg.data);
|
|
231
253
|
this._logger.isDebugEnabled && this._logger.push({ oldConf: this._appConfig, newConf: dup }).debug(`Emitting new agent configuration [${VERB.PATCH}]`);
|
|
232
254
|
this.emit(EVENT.RECONFIGURE, dup);
|
|
@@ -255,9 +277,18 @@ class Client extends ws {
|
|
|
255
277
|
}
|
|
256
278
|
}
|
|
257
279
|
|
|
280
|
+
const createConnectedControlAgentWs = async (conf, log) => {
|
|
281
|
+
return await Client.Create({
|
|
282
|
+
address: conf.control.mgmtAPIWsUrl,
|
|
283
|
+
port: conf.control.mgmtAPIWsPort,
|
|
284
|
+
appConfig: conf,
|
|
285
|
+
logger: log,
|
|
286
|
+
});
|
|
287
|
+
};
|
|
258
288
|
|
|
259
289
|
|
|
260
290
|
module.exports = {
|
|
291
|
+
createConnectedControlAgentWs,
|
|
261
292
|
Client,
|
|
262
293
|
build,
|
|
263
294
|
MESSAGE,
|
|
@@ -53,7 +53,7 @@ const { ReturnCodes } = Enum.Http;
|
|
|
53
53
|
* Error handling logic shared by outbound API handlers
|
|
54
54
|
*/
|
|
55
55
|
const handleError = (method, err, ctx, stateField) => {
|
|
56
|
-
ctx.state.logger.push({
|
|
56
|
+
ctx.state.logger.push({ stateField }).error(`Error handling ${method}: `, err);
|
|
57
57
|
ctx.response.status = err.httpStatusCode || ReturnCodes.INTERNALSERVERERRROR.CODE;
|
|
58
58
|
ctx.response.body = {
|
|
59
59
|
message: err.message || 'Unspecified error',
|
|
@@ -88,6 +88,7 @@ module.exports = {
|
|
|
88
88
|
mgmtAPIWsUrl: env.get('MGMT_API_WS_URL').default('127.0.0.1').asString(),
|
|
89
89
|
mgmtAPIWsPort: env.get('MGMT_API_WS_PORT').default('4005').asPortNumber(),
|
|
90
90
|
mgmtAPILatencyAssumption: env.get('MGMT_API_LATENCY_ASSUMPTION').default('2000').asIntPositive(),
|
|
91
|
+
mgmtAPIPollIntervalMs: env.get('MANAGEMENT_API_POLL_INTERVAL_MS').asIntPositive(), // undefined if not set (feature disabled)
|
|
91
92
|
},
|
|
92
93
|
idGenerator: env.get('ID_GENERATOR').default('{"type":"ulid"}').asJsonObject(),
|
|
93
94
|
logLevel: env.get('LOG_LEVEL').default('info').asEnum(LOG_LEVELS),
|