dt-common-device 3.0.10 → 3.0.12
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/dist/audit/AuditProperties.d.ts +16 -0
- package/dist/audit/AuditUtils.d.ts +2 -0
- package/dist/audit/AuditUtils.js +36 -0
- package/dist/config/config.d.ts +1 -2
- package/dist/config/config.js +4 -5
- package/dist/constants/Service.d.ts +1 -0
- package/dist/device/local/events/EventHandler.js +6 -6
- package/dist/device/local/events/Events.d.ts +33 -12
- package/dist/device/local/events/Events.js +33 -12
- package/dist/device/local/repository/Schedule.repository.d.ts +0 -1
- package/dist/device/local/repository/Schedule.repository.js +6 -6
- package/dist/queue/entities/HybridHttpQueue.d.ts +4 -14
- package/dist/queue/entities/HybridHttpQueue.js +31 -119
- package/dist/queue/interfaces/IHybridHttpQueue.d.ts +2 -12
- package/dist/queue/interfaces/IJobResult.d.ts +1 -8
- package/dist/queue/interfaces/index.d.ts +0 -1
- package/dist/queue/interfaces/index.js +0 -1
- package/dist/queue/services/QueueService.d.ts +2 -12
- package/dist/queue/types/http.types.d.ts +6 -4
- package/dist/queue/types/queue.types.d.ts +12 -29
- package/dist/queue/utils/jobUtils.d.ts +2 -4
- package/dist/queue/utils/jobUtils.js +0 -48
- package/dist/queue/utils/queueUtils.d.ts +7 -0
- package/dist/queue/utils/queueUtils.js +114 -4
- package/dist/queue/utils/rateLimit.utils.d.ts +1 -1
- package/dist/queue/utils/rateLimit.utils.js +38 -2
- package/package.json +6 -1
- package/.eslintrc.js +0 -44
- package/dist/device/cloud/interface.d.ts +0 -101
- package/dist/device/cloud/interface.js +0 -3
- package/dist/device/cloud/interfaces/IDeviceConnectionService.d.ts +0 -7
- package/dist/device/cloud/interfaces/IDeviceConnectionService.js +0 -3
- package/dist/device/cloud/interfaces/IDevicesService.d.ts +0 -9
- package/dist/device/cloud/services/Device.service.d.ts +0 -39
- package/dist/device/cloud/services/Device.service.js +0 -9
- package/dist/device/cloud/services/DeviceCloudService.d.ts +0 -42
- package/dist/device/cloud/services/DeviceCloudService.js +0 -59
- package/dist/device/cloud/services/DeviceHub.service.d.ts +0 -3
- package/dist/device/cloud/services/DeviceHub.service.js +0 -6
- package/dist/device/cloud/services/Hub.service.d.ts +0 -25
- package/dist/device/cloud/services/Hub.service.js +0 -9
- package/dist/device/cloud/services/SmartThingsDeviceService.d.ts +0 -38
- package/dist/device/cloud/services/SmartThingsDeviceService.js +0 -52
- package/dist/device/index.d.ts +0 -4
- package/dist/device/index.js +0 -20
- package/dist/device/local/interface.d.ts +0 -0
- package/dist/device/local/interface.js +0 -1
- package/dist/device/local/services/DeviceHub.service.d.ts +0 -11
- package/dist/device/local/services/DeviceHub.service.js +0 -40
- package/src/alerts/Alert.model.ts +0 -289
- package/src/alerts/Alert.repository.ts +0 -487
- package/src/alerts/Alert.service.ts +0 -711
- package/src/alerts/AlertBuilder.example.ts +0 -126
- package/src/alerts/AlertBuilder.ts +0 -208
- package/src/alerts/AlertService.example.ts +0 -232
- package/src/alerts/alert.types.ts +0 -64
- package/src/alerts/index.ts +0 -3
- package/src/config/config.ts +0 -202
- package/src/config/config.types.ts +0 -21
- package/src/connection/Connection.repository.ts +0 -52
- package/src/connection/Connection.service.ts +0 -39
- package/src/connection/IConnection.ts +0 -27
- package/src/connection/index.ts +0 -3
- package/src/constants/ConnectionProviders.ts +0 -11
- package/src/constants/Event.ts +0 -89
- package/src/constants/Service.ts +0 -17
- package/src/constants/index.ts +0 -3
- package/src/db/db.ts +0 -24
- package/src/db/index.ts +0 -2
- package/src/db/redis.ts +0 -20
- package/src/device/cloud/entities/CloudDevice.ts +0 -40
- package/src/device/cloud/entities/CloudDeviceService.ts +0 -8
- package/src/device/cloud/entities/DeviceFactory.ts +0 -27
- package/src/device/cloud/entities/index.ts +0 -3
- package/src/device/cloud/interfaces/ICloudDevice.ts +0 -14
- package/src/device/cloud/interfaces/ICloudDeviceService.ts +0 -6
- package/src/device/cloud/interfaces/IDeviceFactory.ts +0 -5
- package/src/device/cloud/interfaces/IRawDataTransformer.ts +0 -5
- package/src/device/cloud/interfaces/IRawDevice.ts +0 -19
- package/src/device/cloud/interfaces/index.ts +0 -5
- package/src/device/local/interfaces/IDevice.ts +0 -62
- package/src/device/local/interfaces/IDtDevice.ts +0 -16
- package/src/device/local/interfaces/ISchedule.ts +0 -40
- package/src/device/local/interfaces/index.ts +0 -3
- package/src/device/local/repository/Device.repository.ts +0 -368
- package/src/device/local/repository/Hub.repository.ts +0 -107
- package/src/device/local/repository/Schedule.repository.ts +0 -72
- package/src/device/local/services/Device.service.ts +0 -436
- package/src/device/local/services/Hub.service.ts +0 -57
- package/src/device/local/services/Schedule.service.ts +0 -26
- package/src/device/local/services/index.ts +0 -3
- package/src/docs/Alert.model.md +0 -319
- package/src/docs/Alerts&IssuesModel.md +0 -312
- package/src/docs/Issue.model.md +0 -386
- package/src/docs/SECURITY.md +0 -67
- package/src/docs/TROUBLESHOOTING.md +0 -184
- package/src/events/BaseEventHandler.ts +0 -145
- package/src/events/BaseEventTransformer.ts +0 -97
- package/src/events/DeviceEventHandler.ts +0 -213
- package/src/events/DeviceEventTransformerFactory.ts +0 -77
- package/src/events/EventHandler.ts +0 -124
- package/src/events/EventHandlerOrchestrator.ts +0 -119
- package/src/events/EventProcessingService.ts +0 -248
- package/src/events/InternalEventSubscription.ts +0 -194
- package/src/events/index.ts +0 -9
- package/src/events/interfaces/DeviceEvent.ts +0 -56
- package/src/events/interfaces/IEventHandler.ts +0 -28
- package/src/events/interfaces/IEventTransformer.ts +0 -8
- package/src/events/interfaces/IInternalEvent.ts +0 -33
- package/src/events/interfaces/index.ts +0 -4
- package/src/index.ts +0 -43
- package/src/issues/Issue.model.ts +0 -350
- package/src/issues/Issue.repository.ts +0 -517
- package/src/issues/Issue.service.ts +0 -932
- package/src/issues/IssueBuilder.example.ts +0 -210
- package/src/issues/IssueBuilder.ts +0 -263
- package/src/issues/IssueService.example.ts +0 -310
- package/src/issues/index.ts +0 -2
- package/src/issues/issue.types.ts +0 -98
- package/src/property/IProperty.ts +0 -30
- package/src/property/Property.repository.ts +0 -53
- package/src/property/Property.service.ts +0 -38
- package/src/property/index.ts +0 -2
- package/src/queue/entities/HybridHttpQueue.ts +0 -274
- package/src/queue/entities/index.ts +0 -1
- package/src/queue/index.ts +0 -6
- package/src/queue/interfaces/IHttpRequestJob.ts +0 -10
- package/src/queue/interfaces/IHybridHttpQueue.ts +0 -25
- package/src/queue/interfaces/IJobResult.ts +0 -15
- package/src/queue/interfaces/IRateLimitConfig.ts +0 -5
- package/src/queue/interfaces/index.ts +0 -4
- package/src/queue/services/QueueService.ts +0 -40
- package/src/queue/services/index.ts +0 -1
- package/src/queue/types/http.types.ts +0 -23
- package/src/queue/types/index.ts +0 -2
- package/src/queue/types/queue.types.ts +0 -21
- package/src/queue/utils/index.ts +0 -3
- package/src/queue/utils/jobUtils.ts +0 -79
- package/src/queue/utils/queueUtils.ts +0 -84
- package/src/queue/utils/rateLimit.utils.ts +0 -131
- package/src/utils/http.utils.ts +0 -143
- package/src/utils/index.ts +0 -2
- package/src/utils/redis.utils.ts +0 -74
- package/tsconfig.json +0 -20
- /package/dist/{device/cloud/interfaces/IDevicesService.js → audit/AuditProperties.js} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AuditProperties {
|
|
2
|
+
resource: string;
|
|
3
|
+
propertyId: string;
|
|
4
|
+
propertyName?: string;
|
|
5
|
+
userId?: string;
|
|
6
|
+
userName?: string;
|
|
7
|
+
deviceId: string;
|
|
8
|
+
deviceName: string;
|
|
9
|
+
zoneId?: string;
|
|
10
|
+
zoneName?: string;
|
|
11
|
+
accessGroupId?: string;
|
|
12
|
+
accessGroupName?: string;
|
|
13
|
+
scheduleId?: string;
|
|
14
|
+
scheduleName?: string;
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildAuditProperties = buildAuditProperties;
|
|
4
|
+
const AUDIT_FIELDS = [
|
|
5
|
+
"resource",
|
|
6
|
+
"propertyId",
|
|
7
|
+
"propertyName",
|
|
8
|
+
"userId",
|
|
9
|
+
"userName",
|
|
10
|
+
"deviceId",
|
|
11
|
+
"deviceName",
|
|
12
|
+
"zoneId",
|
|
13
|
+
"zoneName",
|
|
14
|
+
"accessGroupId",
|
|
15
|
+
"accessGroupName",
|
|
16
|
+
"scheduleId",
|
|
17
|
+
"scheduleName",
|
|
18
|
+
];
|
|
19
|
+
function buildAuditProperties(input) {
|
|
20
|
+
// Normalize keys to camelCase for matching
|
|
21
|
+
const normalized = { ...input };
|
|
22
|
+
// Build the audit object with all standard fields
|
|
23
|
+
const audit = {};
|
|
24
|
+
for (const field of AUDIT_FIELDS) {
|
|
25
|
+
// Try to find a matching key in input (case-insensitive)
|
|
26
|
+
const foundKey = Object.keys(normalized).find((k) => k.toLowerCase() === field.toLowerCase());
|
|
27
|
+
audit[field] = foundKey ? normalized[foundKey] : undefined;
|
|
28
|
+
}
|
|
29
|
+
// Merge in all other event-specific data (but don't overwrite audit fields)
|
|
30
|
+
for (const key of Object.keys(normalized)) {
|
|
31
|
+
if (!audit.hasOwnProperty(key)) {
|
|
32
|
+
audit[key] = normalized[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return audit;
|
|
36
|
+
}
|
package/dist/config/config.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { InternalEventSubscription } from "../events";
|
|
2
|
-
import { IConfig
|
|
2
|
+
import { IConfig } from "./config.types";
|
|
3
3
|
export declare function initialize(cfg: IConfig): Promise<void>;
|
|
4
4
|
export declare function getConfig(): IConfig;
|
|
5
|
-
export declare function getLogger(): ILogger;
|
|
6
5
|
export declare function getEventSubscription(): InternalEventSubscription | null;
|
|
7
6
|
export declare function checkRequiredEnv(): void;
|
|
8
7
|
export declare function ensureAuditInitialized(): void;
|
package/dist/config/config.js
CHANGED
|
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.initialize = initialize;
|
|
7
7
|
exports.getConfig = getConfig;
|
|
8
|
-
exports.getLogger = getLogger;
|
|
9
8
|
exports.getEventSubscription = getEventSubscription;
|
|
10
9
|
exports.checkRequiredEnv = checkRequiredEnv;
|
|
11
10
|
exports.ensureAuditInitialized = ensureAuditInitialized;
|
|
@@ -83,10 +82,6 @@ function getConfig() {
|
|
|
83
82
|
}
|
|
84
83
|
return config;
|
|
85
84
|
}
|
|
86
|
-
// Direct logger export for easier usage
|
|
87
|
-
function getLogger() {
|
|
88
|
-
return getConfig().LOGGER;
|
|
89
|
-
}
|
|
90
85
|
function getEventSubscription() {
|
|
91
86
|
return eventSubscription;
|
|
92
87
|
}
|
|
@@ -120,6 +115,10 @@ function ensureAuditInitialized() {
|
|
|
120
115
|
(0, dt_audit_library_1.initializeAudit)(apiKey, host);
|
|
121
116
|
auditInitialized = true;
|
|
122
117
|
}
|
|
118
|
+
// // Direct logger export for easier usage
|
|
119
|
+
// export function getLogger(): ILogger {
|
|
120
|
+
// return getConfig().LOGGER;
|
|
121
|
+
// }
|
|
123
122
|
/**
|
|
124
123
|
* Returns the PostgreSQL DB URI from environment variables.
|
|
125
124
|
* Throws an error if not set.
|
|
@@ -5,6 +5,7 @@ export declare const SERVICE_NAMES: {
|
|
|
5
5
|
readonly SCHEDULE: "smart-schedule";
|
|
6
6
|
readonly DEVICE: "smart-device";
|
|
7
7
|
};
|
|
8
|
+
export type SERVICE_NAME = typeof SERVICE_NAMES[keyof typeof SERVICE_NAMES];
|
|
8
9
|
export declare enum Source {
|
|
9
10
|
USER = "user",
|
|
10
11
|
CLOUD_EVENT = "cloud-event",
|
|
@@ -9,9 +9,9 @@ class EventHandler {
|
|
|
9
9
|
this.source = "dt-common-device";
|
|
10
10
|
}
|
|
11
11
|
async onDeviceCreate(body) {
|
|
12
|
-
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.
|
|
12
|
+
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.CREATE.SUCCESS, body, this.source);
|
|
13
13
|
const payload = {
|
|
14
|
-
eventType: Events_1.DT_EVENT_TYPES.DEVICE.
|
|
14
|
+
eventType: Events_1.DT_EVENT_TYPES.DEVICE.CREATE.SUCCESS,
|
|
15
15
|
properties: {
|
|
16
16
|
...body,
|
|
17
17
|
},
|
|
@@ -19,9 +19,9 @@ class EventHandler {
|
|
|
19
19
|
await (0, dt_audit_library_1.publishAudit)(payload);
|
|
20
20
|
}
|
|
21
21
|
async onDeviceUpdate(deviceId, body) {
|
|
22
|
-
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.
|
|
22
|
+
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.UPDATE.SUCCESS, { deviceId, body }, this.source);
|
|
23
23
|
const payload = {
|
|
24
|
-
eventType: Events_1.DT_EVENT_TYPES.DEVICE.
|
|
24
|
+
eventType: Events_1.DT_EVENT_TYPES.DEVICE.UPDATE.SUCCESS,
|
|
25
25
|
properties: {
|
|
26
26
|
...body,
|
|
27
27
|
},
|
|
@@ -29,9 +29,9 @@ class EventHandler {
|
|
|
29
29
|
await (0, dt_audit_library_1.publishAudit)(payload);
|
|
30
30
|
}
|
|
31
31
|
async onDeviceDelete(deviceId) {
|
|
32
|
-
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.
|
|
32
|
+
await dt_pub_sub_1.eventDispatcher.publishEvent(Events_1.DT_EVENT_TYPES.DEVICE.DELETE.SUCCESS, { deviceId }, this.source);
|
|
33
33
|
const payload = {
|
|
34
|
-
eventType: Events_1.DT_EVENT_TYPES.DEVICE.
|
|
34
|
+
eventType: Events_1.DT_EVENT_TYPES.DEVICE.DELETE.SUCCESS,
|
|
35
35
|
properties: {
|
|
36
36
|
deviceId,
|
|
37
37
|
},
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
export declare const DT_EVENT_TYPES: {
|
|
2
2
|
DEVICE: {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
CREATE: {
|
|
4
|
+
SUCCESS: string;
|
|
5
|
+
FAILED: string;
|
|
6
|
+
};
|
|
7
|
+
UPDATE: {
|
|
8
|
+
SUCCESS: string;
|
|
9
|
+
FAILED: string;
|
|
10
|
+
};
|
|
11
|
+
DELETE: {
|
|
12
|
+
SUCCESS: string;
|
|
13
|
+
FAILED: string;
|
|
7
14
|
};
|
|
8
15
|
STATE: {
|
|
9
16
|
SET: string;
|
|
@@ -34,17 +41,31 @@ export declare const DT_EVENT_TYPES: {
|
|
|
34
41
|
};
|
|
35
42
|
};
|
|
36
43
|
CONNECTION: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
CREATE: {
|
|
45
|
+
SUCCESS: string;
|
|
46
|
+
FAILED: string;
|
|
47
|
+
};
|
|
48
|
+
UPDATE: {
|
|
49
|
+
SUCCESS: string;
|
|
50
|
+
FAILED: string;
|
|
51
|
+
};
|
|
52
|
+
DELETE: {
|
|
53
|
+
SUCCESS: string;
|
|
54
|
+
FAILED: string;
|
|
41
55
|
};
|
|
42
56
|
};
|
|
43
57
|
PROPERTY: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
CREATE: {
|
|
59
|
+
SUCCESS: string;
|
|
60
|
+
FAILED: string;
|
|
61
|
+
};
|
|
62
|
+
UPDATE: {
|
|
63
|
+
SUCCESS: string;
|
|
64
|
+
FAILED: string;
|
|
65
|
+
};
|
|
66
|
+
DELETE: {
|
|
67
|
+
SUCCESS: string;
|
|
68
|
+
FAILED: string;
|
|
48
69
|
};
|
|
49
70
|
PREFERENCES: {
|
|
50
71
|
UPDATED: string;
|
|
@@ -3,10 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DT_EVENT_TYPES = void 0;
|
|
4
4
|
exports.DT_EVENT_TYPES = {
|
|
5
5
|
DEVICE: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
CREATE: {
|
|
7
|
+
SUCCESS: "device.create.success",
|
|
8
|
+
FAILED: "device.create.failed",
|
|
9
|
+
},
|
|
10
|
+
UPDATE: {
|
|
11
|
+
SUCCESS: "device.update.success",
|
|
12
|
+
FAILED: "device.update.failed",
|
|
13
|
+
},
|
|
14
|
+
DELETE: {
|
|
15
|
+
SUCCESS: "device.delete.success",
|
|
16
|
+
FAILED: "device.delete.failed",
|
|
10
17
|
},
|
|
11
18
|
STATE: {
|
|
12
19
|
SET: "device.state.set",
|
|
@@ -37,17 +44,31 @@ exports.DT_EVENT_TYPES = {
|
|
|
37
44
|
},
|
|
38
45
|
},
|
|
39
46
|
CONNECTION: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
CREATE: {
|
|
48
|
+
SUCCESS: "connection.create.success",
|
|
49
|
+
FAILED: "connection.create.failed",
|
|
50
|
+
},
|
|
51
|
+
UPDATE: {
|
|
52
|
+
SUCCESS: "connection.update.success",
|
|
53
|
+
FAILED: "connection.update.failed",
|
|
54
|
+
},
|
|
55
|
+
DELETE: {
|
|
56
|
+
SUCCESS: "connection.delete.success",
|
|
57
|
+
FAILED: "connection.delete.failed",
|
|
44
58
|
},
|
|
45
59
|
},
|
|
46
60
|
PROPERTY: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
CREATE: {
|
|
62
|
+
SUCCESS: "property.create.success",
|
|
63
|
+
FAILED: "property.create.failed",
|
|
64
|
+
},
|
|
65
|
+
UPDATE: {
|
|
66
|
+
SUCCESS: "property.update.success",
|
|
67
|
+
FAILED: "property.update.failed",
|
|
68
|
+
},
|
|
69
|
+
DELETE: {
|
|
70
|
+
SUCCESS: "property.delete.success",
|
|
71
|
+
FAILED: "property.delete.failed",
|
|
51
72
|
},
|
|
52
73
|
PREFERENCES: {
|
|
53
74
|
UPDATED: "property.preferences.updated",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ISchedule } from "../interfaces/ISchedule";
|
|
2
2
|
export declare class ScheduleRepository {
|
|
3
3
|
private readonly axiosInstance;
|
|
4
|
-
private readonly logger;
|
|
5
4
|
constructor();
|
|
6
5
|
getSchedule(scheduleId: string): Promise<any>;
|
|
7
6
|
getScheduleByZone(zoneId: string): Promise<any>;
|
|
@@ -40,16 +40,16 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
41
|
exports.ScheduleRepository = void 0;
|
|
42
42
|
const typedi_1 = require("typedi");
|
|
43
|
-
const config_1 = require("../../../config/config");
|
|
44
43
|
const http_utils_1 = require("../../../utils/http.utils");
|
|
44
|
+
const config_1 = require("../../../config/config");
|
|
45
45
|
let ScheduleRepository = (() => {
|
|
46
46
|
let _classDecorators = [(0, typedi_1.Service)()];
|
|
47
47
|
let _classDescriptor;
|
|
48
48
|
let _classExtraInitializers = [];
|
|
49
49
|
let _classThis;
|
|
50
50
|
var ScheduleRepository = _classThis = class {
|
|
51
|
+
// private readonly logger = getLogger();
|
|
51
52
|
constructor() {
|
|
52
|
-
this.logger = (0, config_1.getLogger)();
|
|
53
53
|
this.axiosInstance = (0, http_utils_1.getDeviceServiceAxiosInstance)();
|
|
54
54
|
}
|
|
55
55
|
async getSchedule(scheduleId) {
|
|
@@ -58,7 +58,7 @@ let ScheduleRepository = (() => {
|
|
|
58
58
|
return response.data;
|
|
59
59
|
}
|
|
60
60
|
catch (error) {
|
|
61
|
-
|
|
61
|
+
(0, config_1.getConfig)().LOGGER.error(`Failed to get schedule ${scheduleId}:`, error);
|
|
62
62
|
const errorMessage = error.response?.data?.message || error.message || "Unknown error";
|
|
63
63
|
throw new Error(`Failed to get schedule: ${errorMessage}`);
|
|
64
64
|
}
|
|
@@ -69,7 +69,7 @@ let ScheduleRepository = (() => {
|
|
|
69
69
|
return response.data;
|
|
70
70
|
}
|
|
71
71
|
catch (error) {
|
|
72
|
-
|
|
72
|
+
(0, config_1.getConfig)().LOGGER.error(`Failed to get schedule by zone ${zoneId}:`, error);
|
|
73
73
|
const errorMessage = error.response?.data?.message || error.message || "Unknown error";
|
|
74
74
|
throw new Error(`Failed to get schedule: ${errorMessage}`);
|
|
75
75
|
}
|
|
@@ -80,7 +80,7 @@ let ScheduleRepository = (() => {
|
|
|
80
80
|
return response.data;
|
|
81
81
|
}
|
|
82
82
|
catch (error) {
|
|
83
|
-
|
|
83
|
+
(0, config_1.getConfig)().LOGGER.error(`Failed to update schedule ${scheduleId}:`, error);
|
|
84
84
|
const errorMessage = error.response?.data?.message || error.message || "Unknown error";
|
|
85
85
|
throw new Error(`Failed to update schedule: ${errorMessage}`);
|
|
86
86
|
}
|
|
@@ -91,7 +91,7 @@ let ScheduleRepository = (() => {
|
|
|
91
91
|
return response.data;
|
|
92
92
|
}
|
|
93
93
|
catch (error) {
|
|
94
|
-
|
|
94
|
+
(0, config_1.getConfig)().LOGGER.error(`Failed to delete schedule from DB ${scheduleId}:`, error);
|
|
95
95
|
throw new Error(`Failed to delete schedule from DB: ${error.message}`);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
import { HttpCallOption } from "../types/http.types";
|
|
2
2
|
import { IQueueResponse } from "../interfaces";
|
|
3
|
+
import { RequestQueueOptions } from "../types/queue.types";
|
|
3
4
|
export declare class HybridHttpQueue {
|
|
5
|
+
private readonly rateLimitConfigs;
|
|
4
6
|
private readonly queues;
|
|
5
7
|
private readonly workers;
|
|
6
|
-
private readonly rateLimitConfigs;
|
|
7
8
|
private readonly jobResults;
|
|
8
9
|
constructor();
|
|
9
|
-
private
|
|
10
|
+
private addToQueue;
|
|
10
11
|
private processHttpRequest;
|
|
11
|
-
request(options:
|
|
12
|
-
method: string;
|
|
13
|
-
url: string;
|
|
14
|
-
body?: any;
|
|
15
|
-
params?: Record<string, any>;
|
|
16
|
-
headers?: Record<string, string>;
|
|
17
|
-
queueOptions?: {
|
|
18
|
-
connectionId: string;
|
|
19
|
-
connectionProvider: string;
|
|
20
|
-
microservice: string;
|
|
21
|
-
};
|
|
22
|
-
}): Promise<IQueueResponse>;
|
|
12
|
+
request(options: RequestQueueOptions): Promise<any>;
|
|
23
13
|
handleRequest(url: string, method: string, options: HttpCallOption): Promise<IQueueResponse>;
|
|
24
14
|
shutdown(): Promise<void>;
|
|
25
15
|
}
|
|
@@ -37,18 +37,13 @@ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, p
|
|
|
37
37
|
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
38
38
|
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
39
39
|
};
|
|
40
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
-
};
|
|
43
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
41
|
exports.HybridHttpQueue = void 0;
|
|
45
|
-
const config_1 = require("../../config/config");
|
|
46
|
-
const axios_1 = __importDefault(require("axios"));
|
|
47
|
-
const dt_audit_library_1 = require("dt-audit-library");
|
|
48
42
|
const typedi_1 = require("typedi");
|
|
49
43
|
const rateLimit_utils_1 = require("../utils/rateLimit.utils");
|
|
50
44
|
const jobUtils_1 = require("../utils/jobUtils");
|
|
51
45
|
const queueUtils_1 = require("../utils/queueUtils");
|
|
46
|
+
const config_1 = require("../../config/config");
|
|
52
47
|
let HybridHttpQueue = (() => {
|
|
53
48
|
let _classDecorators = [(0, typedi_1.Service)()];
|
|
54
49
|
let _classDescriptor;
|
|
@@ -56,13 +51,15 @@ let HybridHttpQueue = (() => {
|
|
|
56
51
|
let _classThis;
|
|
57
52
|
var HybridHttpQueue = _classThis = class {
|
|
58
53
|
constructor() {
|
|
54
|
+
// BullMQ queues and workers for persistent storage
|
|
59
55
|
this.queues = new Map();
|
|
60
56
|
this.workers = new Map();
|
|
61
57
|
this.jobResults = new Map();
|
|
62
58
|
this.rateLimitConfigs = rateLimit_utils_1.RateLimitUtils.initializeRateLimitConfigs();
|
|
63
59
|
}
|
|
64
|
-
async
|
|
65
|
-
const
|
|
60
|
+
async addToQueue(connectionId, provider, url, method, options) {
|
|
61
|
+
const queueKey = queueUtils_1.QueueUtils.getQueueKey(options.queueOptions?.microservice, connectionId, provider);
|
|
62
|
+
// Calculate delay based on rate limit window
|
|
66
63
|
const key = `rate_limit:${provider}:${connectionId}`;
|
|
67
64
|
const config = this.rateLimitConfigs.get(provider);
|
|
68
65
|
const windowMs = config?.windowMs ?? 60000;
|
|
@@ -70,11 +67,14 @@ let HybridHttpQueue = (() => {
|
|
|
70
67
|
const now = Date.now();
|
|
71
68
|
const windowStart = now - windowMs;
|
|
72
69
|
const recentRequests = timestamps.filter((t) => t > windowStart);
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
let delay = 0;
|
|
71
|
+
if (recentRequests.length >= (config?.maxRequests ?? 5)) {
|
|
72
|
+
const earliestRequest = recentRequests[0];
|
|
73
|
+
const nextAvailableTime = earliestRequest + windowMs;
|
|
74
|
+
delay = Math.max(nextAvailableTime - now, 1000); // At least 1s delay
|
|
75
|
+
}
|
|
75
76
|
// Create job data
|
|
76
77
|
const jobData = {
|
|
77
|
-
microservice,
|
|
78
78
|
connectionId,
|
|
79
79
|
provider,
|
|
80
80
|
url,
|
|
@@ -82,78 +82,25 @@ let HybridHttpQueue = (() => {
|
|
|
82
82
|
options,
|
|
83
83
|
timestamp: Date.now(),
|
|
84
84
|
};
|
|
85
|
-
// Add job to queue with delay
|
|
86
|
-
const
|
|
87
|
-
|
|
85
|
+
// Add job to BullMQ queue with delay
|
|
86
|
+
const jobId = await queueUtils_1.QueueUtils.addJobToQueue(queueKey, jobData, delay, this.queues);
|
|
87
|
+
// Initialize worker if not exists
|
|
88
88
|
queueUtils_1.QueueUtils.getOrCreateWorker(queueKey, this.workers, this.processHttpRequest.bind(this), this.jobResults);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
removeOnComplete: { age: 300, count: 1 },
|
|
93
|
-
removeOnFail: { age: 300, count: 1 },
|
|
94
|
-
});
|
|
95
|
-
await (0, dt_audit_library_1.publishAudit)({
|
|
96
|
-
eventType: "http.request.rateLimitQueued",
|
|
97
|
-
properties: {
|
|
98
|
-
resource: microservice,
|
|
99
|
-
connectionId,
|
|
100
|
-
provider,
|
|
101
|
-
endpoint: url,
|
|
102
|
-
method,
|
|
103
|
-
timestamp: Date.now(),
|
|
104
|
-
queueId: job.id,
|
|
105
|
-
reason: "rate_limit_exceeded_queued",
|
|
106
|
-
delay,
|
|
107
|
-
estimatedProcessingTime: now + delay,
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
// Return immediate response to controller
|
|
111
|
-
return {
|
|
112
|
-
success: true,
|
|
113
|
-
queued: true,
|
|
114
|
-
estimatedProcessingTime: now + delay,
|
|
115
|
-
jobId: job.id,
|
|
116
|
-
};
|
|
89
|
+
(0, config_1.getConfig)().LOGGER.info(`Request queued: ${method} ${url} -> ${provider} [${connectionId}]. Job ID: ${jobId}, Delay: ${delay}ms`);
|
|
90
|
+
// Wait for job completion and return result
|
|
91
|
+
return queueUtils_1.QueueUtils.waitForJobCompletion(jobId, queueKey, this.jobResults);
|
|
117
92
|
}
|
|
118
93
|
async processHttpRequest(job) {
|
|
119
94
|
const { connectionId, provider, url, method, options } = job.data;
|
|
95
|
+
// Check rate limit before processing
|
|
120
96
|
const allowed = await rateLimit_utils_1.RateLimitUtils.isRateLimitAllowed(connectionId, provider, this.rateLimitConfigs);
|
|
121
97
|
if (!allowed) {
|
|
122
|
-
// This shouldn't happen since we
|
|
123
|
-
(0, config_1.getConfig)().LOGGER.warn(`Job ${job.id} still rate limited after delay,
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
await rateLimit_utils_1.RateLimitUtils.recordRequest(connectionId, provider);
|
|
127
|
-
try {
|
|
128
|
-
(0, config_1.getConfig)().LOGGER.info(`Executing HTTP request: ${method} ${url} for ${provider}`);
|
|
129
|
-
const response = await (0, axios_1.default)({
|
|
130
|
-
method: method.toLowerCase(),
|
|
131
|
-
url: url,
|
|
132
|
-
headers: options.headers || {},
|
|
133
|
-
timeout: 30000,
|
|
134
|
-
...(options.body && { data: options.body }),
|
|
135
|
-
...(options.params && { params: options.params }),
|
|
136
|
-
});
|
|
137
|
-
(0, config_1.getConfig)().LOGGER.info(`HTTP request successful: ${method} ${url} for ${provider}`);
|
|
138
|
-
return response.data;
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
(0, config_1.getConfig)().LOGGER.error(`HTTP request failed ${job.id}: ${error.message}`);
|
|
142
|
-
await (0, dt_audit_library_1.publishAudit)({
|
|
143
|
-
eventType: "http.request.error",
|
|
144
|
-
properties: {
|
|
145
|
-
connectionId,
|
|
146
|
-
provider,
|
|
147
|
-
endpoint: url,
|
|
148
|
-
method,
|
|
149
|
-
timestamp: Date.now(),
|
|
150
|
-
queueId: job.id,
|
|
151
|
-
reason: "execution_error",
|
|
152
|
-
errorMessage: error.message,
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
throw new Error(`HTTP request failed: ${error.message}`);
|
|
98
|
+
// This shouldn't happen since we calculate delay, but handle it gracefully
|
|
99
|
+
(0, config_1.getConfig)().LOGGER.warn(`Job ${job.id} still rate limited after delay, waiting for window to expire...`);
|
|
100
|
+
await queueUtils_1.QueueUtils.waitForRateLimitExpiry(connectionId, provider, this.rateLimitConfigs);
|
|
156
101
|
}
|
|
102
|
+
// Execute the HTTP request
|
|
103
|
+
return queueUtils_1.QueueUtils.executeHttpRequest(url, method, options, connectionId, provider);
|
|
157
104
|
}
|
|
158
105
|
async request(options) {
|
|
159
106
|
const { method, url, body, params, headers, queueOptions } = options;
|
|
@@ -171,50 +118,15 @@ let HybridHttpQueue = (() => {
|
|
|
171
118
|
const { connectionId, provider, microservice } = jobUtils_1.JobUtils.extractConnectionDetails(options);
|
|
172
119
|
// Check rate limit first
|
|
173
120
|
const allowed = await rateLimit_utils_1.RateLimitUtils.isRateLimitAllowed(connectionId, provider, this.rateLimitConfigs);
|
|
174
|
-
if (
|
|
175
|
-
// Rate
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Not rate limited - process immediately
|
|
179
|
-
(0, config_1.getConfig)().LOGGER.info(`Processing immediately: ${method} ${url} -> ${provider} [${connectionId}]`);
|
|
180
|
-
try {
|
|
181
|
-
// Record the request first
|
|
182
|
-
await rateLimit_utils_1.RateLimitUtils.recordRequest(connectionId, provider);
|
|
183
|
-
// Execute the HTTP request
|
|
184
|
-
const response = await (0, axios_1.default)({
|
|
185
|
-
method: method.toLowerCase(),
|
|
186
|
-
url: url,
|
|
187
|
-
headers: options.headers || {},
|
|
188
|
-
timeout: 30000,
|
|
189
|
-
...(options.body && { data: options.body }),
|
|
190
|
-
...(options.params && { params: options.params }),
|
|
191
|
-
});
|
|
192
|
-
(0, config_1.getConfig)().LOGGER.info(`HTTP request successful: ${method} ${url} for ${provider}`);
|
|
193
|
-
return {
|
|
194
|
-
success: true,
|
|
195
|
-
data: response.data,
|
|
196
|
-
queued: false,
|
|
197
|
-
};
|
|
121
|
+
if (allowed) {
|
|
122
|
+
// Rate limit not exceeded - execute immediately
|
|
123
|
+
(0, config_1.getConfig)().LOGGER.info(`Rate limit not exceeded: ${method} ${url} -> ${provider} [${connectionId}], executing immediately`);
|
|
124
|
+
return queueUtils_1.QueueUtils.executeHttpRequest(url, method, options, connectionId, provider);
|
|
198
125
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
properties: {
|
|
204
|
-
connectionId,
|
|
205
|
-
provider,
|
|
206
|
-
endpoint: url,
|
|
207
|
-
method,
|
|
208
|
-
timestamp: Date.now(),
|
|
209
|
-
reason: "execution_error",
|
|
210
|
-
errorMessage: error.message,
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
return {
|
|
214
|
-
success: false,
|
|
215
|
-
error: `HTTP request failed: ${error.message}`,
|
|
216
|
-
queued: false,
|
|
217
|
-
};
|
|
126
|
+
else {
|
|
127
|
+
// Rate limit exceeded - add to BullMQ queue
|
|
128
|
+
(0, config_1.getConfig)().LOGGER.info(`Rate limit exceeded: ${method} ${url} -> ${provider} [${connectionId}], adding to BullMQ queue`);
|
|
129
|
+
return this.addToQueue(connectionId, provider, url, method, options);
|
|
218
130
|
}
|
|
219
131
|
}
|
|
220
132
|
async shutdown() {
|
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
import { HttpCallOption } from "../types/http.types";
|
|
2
2
|
import { IQueueResponse } from "./IJobResult";
|
|
3
|
+
import { RequestQueueOptions } from "../types/queue.types";
|
|
3
4
|
export interface IHybridHttpQueue {
|
|
4
|
-
request(options:
|
|
5
|
-
method: string;
|
|
6
|
-
url: string;
|
|
7
|
-
body?: any;
|
|
8
|
-
params?: Record<string, any>;
|
|
9
|
-
headers?: Record<string, string>;
|
|
10
|
-
queueOptions?: {
|
|
11
|
-
connectionId: string;
|
|
12
|
-
connectionProvider: string;
|
|
13
|
-
microservice: string;
|
|
14
|
-
};
|
|
15
|
-
}): Promise<IQueueResponse>;
|
|
5
|
+
request(options: RequestQueueOptions): Promise<IQueueResponse>;
|
|
16
6
|
handleRequest(url: string, method: string, options: HttpCallOption): Promise<IQueueResponse>;
|
|
17
7
|
shutdown(): Promise<void>;
|
|
18
8
|
}
|
|
@@ -4,11 +4,4 @@ export interface IJobResult {
|
|
|
4
4
|
resolved: boolean;
|
|
5
5
|
timestamp: number;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
8
|
-
success: boolean;
|
|
9
|
-
data?: any;
|
|
10
|
-
error?: string;
|
|
11
|
-
queued?: boolean;
|
|
12
|
-
estimatedProcessingTime?: number;
|
|
13
|
-
jobId?: string;
|
|
14
|
-
}
|
|
7
|
+
export type IQueueResponse = any;
|
|
@@ -15,6 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./IHybridHttpQueue"), exports);
|
|
18
|
-
__exportStar(require("./IHttpRequestJob"), exports);
|
|
19
18
|
__exportStar(require("./IJobResult"), exports);
|
|
20
19
|
__exportStar(require("./IRateLimitConfig"), exports);
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { IHybridHttpQueue, IQueueResponse } from "../interfaces";
|
|
2
2
|
import { HttpCallOption } from "../types/http.types";
|
|
3
|
+
import { RequestQueueOptions } from "../types/queue.types";
|
|
3
4
|
export declare class QueueService implements IHybridHttpQueue {
|
|
4
5
|
private readonly hybridQueue;
|
|
5
6
|
constructor();
|
|
6
|
-
request(options:
|
|
7
|
-
method: string;
|
|
8
|
-
url: string;
|
|
9
|
-
body?: any;
|
|
10
|
-
params?: Record<string, any>;
|
|
11
|
-
headers?: Record<string, string>;
|
|
12
|
-
queueOptions?: {
|
|
13
|
-
connectionId: string;
|
|
14
|
-
connectionProvider: string;
|
|
15
|
-
microservice: string;
|
|
16
|
-
};
|
|
17
|
-
}): Promise<IQueueResponse>;
|
|
7
|
+
request(options: RequestQueueOptions): Promise<IQueueResponse>;
|
|
18
8
|
handleRequest(url: string, method: string, options: HttpCallOption): Promise<IQueueResponse>;
|
|
19
9
|
shutdown(): Promise<void>;
|
|
20
10
|
}
|