keeyu-azure-service-bus 1.0.33 → 1.0.34
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/enums/message.d.ts +6 -0
- package/dist/enums/message.js +10 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/interfaces/message.d.ts +53 -0
- package/dist/interfaces/message.js +2 -0
- package/dist/logger/logger.d.ts +3 -0
- package/dist/logger/logger.js +33 -0
- package/dist/models/job-info.model.d.ts +5 -1
- package/dist/models/job-info.model.js +8 -4
- package/dist/models/persist-data.model.d.ts +0 -9
- package/dist/models/persist-data.model.js +16 -12
- package/dist/models/query-metric-data-all.d.ts +3 -1
- package/dist/models/query-metric-data-all.js +5 -3
- package/dist/models/query-metric-data-chunked.d.ts +9 -9
- package/dist/models/query-metric-data-chunked.js +6 -28
- package/dist/models/query-metric-data-onboarding.d.ts +3 -1
- package/dist/models/query-metric-data-onboarding.js +5 -3
- package/dist/models/request-body.model.d.ts +3 -3
- package/dist/models/request-body.model.js +5 -5
- package/dist/models/request-info.model.d.ts +3 -2
- package/dist/models/request-info.model.js +3 -3
- package/dist/models/request-params.model.d.ts +2 -1
- package/dist/models/request-params.model.js +3 -1
- package/dist/services/persistence/api-request-service.d.ts +16 -0
- package/dist/services/persistence/api-request-service.js +68 -0
- package/dist/services/persistence/persistence-client.d.ts +13 -0
- package/dist/services/persistence/persistence-client.js +41 -0
- package/dist/services/service-bus/service-bus-client.d.ts +2 -5
- package/package.json +6 -2
- package/src/enums/message.ts +6 -0
- package/src/index.ts +3 -4
- package/src/interfaces/message.ts +59 -0
- package/src/logger/logger.ts +37 -0
- package/src/models/job-info.model.ts +12 -5
- package/src/models/persist-data.model.ts +16 -16
- package/src/models/query-metric-data-all.ts +8 -4
- package/src/models/query-metric-data-chunked.ts +15 -37
- package/src/models/query-metric-data-onboarding.ts +8 -4
- package/src/models/request-body.model.ts +5 -5
- package/src/models/request-info.model.ts +6 -4
- package/src/models/request-params.model.ts +4 -1
- package/src/services/persistence/api-request-service.ts +63 -0
- package/src/services/persistence/persistence-client.ts +37 -0
- package/src/services/service-bus/service-bus-client.ts +4 -7
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keeyu-azure-service-bus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@typescript-eslint/eslint-plugin": "^6.19.1",
|
|
15
15
|
"@typescript-eslint/parser": "^6.19.1",
|
|
16
|
+
"@types/winston": "^2.4.4",
|
|
16
17
|
"eslint": "^8.56.0",
|
|
17
18
|
"nodemon": "^3.0.2",
|
|
18
19
|
"ts-node": "^10.9.2",
|
|
@@ -22,6 +23,9 @@
|
|
|
22
23
|
"@azure/identity": "^4.2.0",
|
|
23
24
|
"@azure/service-bus": "^7.9.4",
|
|
24
25
|
"@types/node": "^20.10.6",
|
|
25
|
-
"
|
|
26
|
+
"axios": "^1.7.2",
|
|
27
|
+
"joi": "^17.13.1",
|
|
28
|
+
"winston": "^3.11.0",
|
|
29
|
+
"winston-daily-rotate-file": "^4.7.1"
|
|
26
30
|
}
|
|
27
31
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import QueryMetricDataAll from "./models/query-metric-data-all";
|
|
2
2
|
import QueryMetricDataOnboarding from "./models/query-metric-data-onboarding";
|
|
3
3
|
import QueryMetricDataChunked from "./models/query-metric-data-chunked";
|
|
4
|
-
import PersistData from "./models/persist-data.model";
|
|
5
4
|
import ServiceBus from "./services/service-bus/service-bus-client";
|
|
6
5
|
import ServiceBusAdminClient from "./services/service-bus/service-bus-admin-client";
|
|
7
6
|
import { ServiceBusReceivedMessage, ProcessErrorArgs } from "@azure/service-bus";
|
|
8
|
-
|
|
7
|
+
import PersistenceClient from "./services/persistence/persistence-client";
|
|
9
8
|
|
|
10
9
|
export {
|
|
11
10
|
ServiceBus,
|
|
12
11
|
ServiceBusAdminClient,
|
|
13
12
|
QueryMetricDataAll,
|
|
14
13
|
QueryMetricDataOnboarding,
|
|
15
|
-
PersistData,
|
|
16
14
|
ServiceBusReceivedMessage,
|
|
17
15
|
ProcessErrorArgs,
|
|
18
|
-
QueryMetricDataChunked
|
|
16
|
+
QueryMetricDataChunked,
|
|
17
|
+
PersistenceClient
|
|
19
18
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import JobInfo from "../models/job-info.model";
|
|
2
|
+
import RequestBody from "../models/request-body.model";
|
|
3
|
+
import RequestsInfo from "../models/request-info.model";
|
|
4
|
+
import RequestParams from "../models/request-params.model";
|
|
5
|
+
|
|
6
|
+
export interface MessageDto {
|
|
7
|
+
tenantId: string;
|
|
8
|
+
channelId: string;
|
|
9
|
+
componentId: string;
|
|
10
|
+
componentName: string;
|
|
11
|
+
url: string;
|
|
12
|
+
connectorUrl: string;
|
|
13
|
+
headers: HeadersInfo[];
|
|
14
|
+
connectorId: string;
|
|
15
|
+
connectorInfo: ConnectorInfo;
|
|
16
|
+
scheduleFields: ScheduleFields;
|
|
17
|
+
metricDetailedConfiguration?: any;
|
|
18
|
+
componentOptions?: Record<string, string>;
|
|
19
|
+
params?: any;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ChunkedMessageDto {
|
|
23
|
+
jobInfo: JobInfo;
|
|
24
|
+
requestInfo: RequestsInfo;
|
|
25
|
+
requestParams: RequestParams;
|
|
26
|
+
requestBody: RequestBody;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface HeadersInfo {
|
|
30
|
+
key: string;
|
|
31
|
+
value: string | boolean | number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ConnectorInfo {
|
|
35
|
+
_id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
queueName: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ScheduleFields {
|
|
41
|
+
componentId: string;
|
|
42
|
+
channelId?: string;
|
|
43
|
+
tenantId?: string;
|
|
44
|
+
normalPullSchedule: string;
|
|
45
|
+
widerPullSchedule: string;
|
|
46
|
+
normalTimeRange: number;
|
|
47
|
+
widerTimeRange: number;
|
|
48
|
+
persistenceCollection: string;
|
|
49
|
+
isProcessing: boolean;
|
|
50
|
+
lastRunTime: string | null;
|
|
51
|
+
requireOnboarding: boolean;
|
|
52
|
+
scheduleActive: boolean;
|
|
53
|
+
lastSuccessfulCompletionDate?: string | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface PostRequestAttributes {
|
|
57
|
+
params: Record<string, string>
|
|
58
|
+
data: unknown
|
|
59
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
const logFolder = 'logs';
|
|
6
|
+
|
|
7
|
+
// Ensure the logs directory exists
|
|
8
|
+
if (!fs.existsSync(logFolder)) {
|
|
9
|
+
fs.mkdirSync(logFolder);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Define log formats
|
|
13
|
+
const logFormat = winston.format.printf(({ level, message, timestamp }) => {
|
|
14
|
+
return `${timestamp} ${level}: ${message}`;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Define transports
|
|
18
|
+
const consoleTransport = new winston.transports.Console();
|
|
19
|
+
const fileTransport = new DailyRotateFile({
|
|
20
|
+
dirname: logFolder,
|
|
21
|
+
filename: 'app-%DATE%.log',
|
|
22
|
+
datePattern: 'YYYY-MM-DD',
|
|
23
|
+
zippedArchive: true,
|
|
24
|
+
maxSize: '20m', // Set the maximum size for a log file
|
|
25
|
+
maxFiles: '1d', // Retain logs for 1 day
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Create the logger
|
|
29
|
+
const logger = winston.createLogger({
|
|
30
|
+
format: winston.format.combine(
|
|
31
|
+
winston.format.timestamp(),
|
|
32
|
+
logFormat
|
|
33
|
+
),
|
|
34
|
+
transports: [consoleTransport, fileTransport],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default logger;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Joi from "joi";
|
|
2
|
+
import { MessageDto } from "../interfaces/message";
|
|
2
3
|
|
|
3
4
|
export default class JobInfo {
|
|
4
5
|
daysToPull: string;
|
|
@@ -9,14 +10,19 @@ export default class JobInfo {
|
|
|
9
10
|
startDate: string;
|
|
10
11
|
endDate: string;
|
|
11
12
|
persistenceCollection: string;
|
|
13
|
+
lastRunTime: string | null;
|
|
14
|
+
isProcessing: boolean;
|
|
15
|
+
queueName: string;
|
|
12
16
|
|
|
13
|
-
constructor(data:
|
|
17
|
+
constructor(data: MessageDto) {
|
|
14
18
|
const schema = Joi.object({
|
|
15
19
|
scheduleFields: Joi.object({
|
|
16
20
|
normalTimeRange: Joi.number().positive().required(),
|
|
17
21
|
widerTimeRange: Joi.number().positive().required(),
|
|
18
22
|
requireOnboarding: Joi.boolean().required(),
|
|
19
23
|
persistenceCollection: Joi.required(),
|
|
24
|
+
lastRunTime: Joi.optional(),
|
|
25
|
+
isProcessing: Joi.required()
|
|
20
26
|
}).unknown(true),
|
|
21
27
|
tenantId: Joi.required(),
|
|
22
28
|
channelId: Joi.required(),
|
|
@@ -28,19 +34,20 @@ export default class JobInfo {
|
|
|
28
34
|
|
|
29
35
|
if (error) throw new Error(error.message);
|
|
30
36
|
|
|
31
|
-
const { scheduleFields: { normalTimeRange, widerTimeRange, requireOnboarding, persistenceCollection }, tenantId, channelId, componentId, connectorId } = value;
|
|
37
|
+
const { scheduleFields: { normalTimeRange, widerTimeRange, requireOnboarding, persistenceCollection, isProcessing, lastRunTime }, tenantId, channelId, componentId, connectorId } = value;
|
|
32
38
|
|
|
39
|
+
this.queueName = data?.connectorInfo?.queueName;
|
|
33
40
|
const today = new Date();
|
|
34
|
-
const startDate = new Date();
|
|
35
|
-
startDate.setUTCHours(0,0,0,0);
|
|
36
41
|
this.daysToPull = requireOnboarding ? widerTimeRange : normalTimeRange;
|
|
37
42
|
this.tenantId = tenantId;
|
|
38
43
|
this.channelId = channelId;
|
|
39
44
|
this.connectorId = connectorId;
|
|
40
45
|
this.componentId = componentId;
|
|
41
46
|
this.persistenceCollection = persistenceCollection;
|
|
42
|
-
this.startDate = this.getFormatedDate(new Date(
|
|
47
|
+
this.startDate = this.getFormatedDate(new Date(today.getTime() - (requireOnboarding ? widerTimeRange : normalTimeRange) * 24 * 60 * 60 * 1000));
|
|
43
48
|
this.endDate = this.getFormatedDate(today);
|
|
49
|
+
this.isProcessing = isProcessing;
|
|
50
|
+
this.lastRunTime = lastRunTime;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
private getFormatedDate(date: Date) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export default class PersistData {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// export default class PersistData {
|
|
2
|
+
// connectorId: string;
|
|
3
|
+
// channelId: string;
|
|
4
|
+
// tenantId: string;
|
|
5
|
+
// componentId: string;
|
|
6
|
+
// idKey: string;
|
|
7
|
+
// data: any[];
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
9
|
+
// constructor(data: any) {
|
|
10
|
+
// this.connectorId = data.connectorId;
|
|
11
|
+
// this.componentId = data.componentId;
|
|
12
|
+
// this.channelId = data.channelId;
|
|
13
|
+
// this.tenantId = data.tenantId;
|
|
14
|
+
// this.idKey = data.idKey;
|
|
15
|
+
// this.data = data.record_list;
|
|
16
|
+
// }
|
|
17
|
+
// }
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import { MessageEnum } from "../enums/message";
|
|
2
|
+
import { MessageDto } from "../interfaces/message";
|
|
1
3
|
import JobInfo from "./job-info.model";
|
|
2
4
|
import RequestBody from "./request-body.model";
|
|
3
5
|
import RequestsInfo from "./request-info.model";
|
|
4
6
|
import RequestParams from "./request-params.model";
|
|
5
7
|
|
|
6
8
|
export default class QueryMetricDataAll {
|
|
9
|
+
type: string;
|
|
7
10
|
jobInfo: JobInfo;
|
|
8
11
|
requestInfo: RequestsInfo;
|
|
9
12
|
requestParams: RequestParams;
|
|
10
13
|
requestBody: RequestBody;
|
|
11
14
|
|
|
12
|
-
constructor(data:
|
|
15
|
+
constructor(data: MessageDto) {
|
|
16
|
+
this.type = MessageEnum.normal;
|
|
13
17
|
this.jobInfo = new JobInfo(data);
|
|
14
|
-
this.requestInfo = new RequestsInfo(data);
|
|
15
|
-
this.requestParams = new RequestParams(data);
|
|
16
|
-
this.requestBody = new RequestBody(data);
|
|
18
|
+
this.requestInfo = new RequestsInfo(data.headers, data.url);
|
|
19
|
+
this.requestParams = new RequestParams(data?.params);
|
|
20
|
+
this.requestBody = new RequestBody(data?.metricDetailedConfiguration, data?.componentOptions);
|
|
17
21
|
}
|
|
18
22
|
}
|
|
@@ -1,44 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { MessageEnum } from "../enums/message";
|
|
2
|
+
import { ChunkedMessageDto } from "../interfaces/message";
|
|
3
|
+
import JobInfo from "./job-info.model";
|
|
2
4
|
import RequestBody from "./request-body.model";
|
|
5
|
+
import RequestsInfo from "./request-info.model";
|
|
6
|
+
import RequestParams from "./request-params.model";
|
|
3
7
|
|
|
4
8
|
export default class QueryMetricDataChunked {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
persistenceCollection: string;
|
|
10
|
-
startDate: string;
|
|
11
|
-
endDate: string;
|
|
12
|
-
pageNo: number;
|
|
9
|
+
type: string;
|
|
10
|
+
jobInfo: JobInfo;
|
|
11
|
+
requestInfo: RequestsInfo;
|
|
12
|
+
requestParams: RequestParams;
|
|
13
13
|
requestBody: RequestBody;
|
|
14
14
|
|
|
15
|
-
constructor(data:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
persistenceCollection: Joi.required(),
|
|
22
|
-
startDate: Joi.required(),
|
|
23
|
-
endDate: Joi.required(),
|
|
24
|
-
pageNo: Joi.required(),
|
|
25
|
-
}).unknown(true);
|
|
26
|
-
|
|
27
|
-
const { error, value } = schema.validate(data);
|
|
28
|
-
|
|
29
|
-
if (error) throw new Error(error.message);
|
|
30
|
-
|
|
31
|
-
const { tenantId, channelId, componentId, connectorId, persistenceCollection, startDate, endDate, pageNo } = value;
|
|
32
|
-
|
|
33
|
-
this.tenantId = tenantId;
|
|
34
|
-
this.channelId = channelId;
|
|
35
|
-
this.connectorId = connectorId;
|
|
36
|
-
this.componentId = componentId;
|
|
37
|
-
this.connectorId = connectorId;
|
|
38
|
-
this.persistenceCollection = persistenceCollection;
|
|
39
|
-
this.startDate = startDate;
|
|
40
|
-
this.endDate = endDate;
|
|
41
|
-
this.pageNo = Number(pageNo);
|
|
42
|
-
this.requestBody = data.headers;
|
|
15
|
+
constructor(data: ChunkedMessageDto) {
|
|
16
|
+
this.type = MessageEnum.chunked;
|
|
17
|
+
this.jobInfo = data.jobInfo;
|
|
18
|
+
this.requestInfo = data.requestInfo;
|
|
19
|
+
this.requestParams = data.requestParams;
|
|
20
|
+
this.requestBody = data.requestBody;
|
|
43
21
|
}
|
|
44
22
|
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import { MessageEnum } from "../enums/message";
|
|
2
|
+
import { MessageDto } from "../interfaces/message";
|
|
1
3
|
import JobInfo from "./job-info.model";
|
|
2
4
|
import RequestBody from "./request-body.model";
|
|
3
5
|
import RequestsInfo from "./request-info.model";
|
|
4
6
|
import RequestParams from "./request-params.model";
|
|
5
7
|
|
|
6
8
|
export default class QueryMetricDataOnboarding {
|
|
9
|
+
type: string;
|
|
7
10
|
jobInfo: JobInfo;
|
|
8
11
|
requestInfo: RequestsInfo;
|
|
9
12
|
requestParams: RequestParams;
|
|
10
13
|
requestBody: RequestBody;
|
|
11
14
|
|
|
12
|
-
constructor(data:
|
|
15
|
+
constructor(data: MessageDto) {
|
|
16
|
+
this.type = MessageEnum.on_boarding;
|
|
13
17
|
this.jobInfo = new JobInfo(data);
|
|
14
|
-
this.requestInfo = new RequestsInfo(data);
|
|
15
|
-
this.requestParams = new RequestParams(data);
|
|
16
|
-
this.requestBody = new RequestBody(data);
|
|
18
|
+
this.requestInfo = new RequestsInfo(data.headers, data.url);
|
|
19
|
+
this.requestParams = new RequestParams(data.params);
|
|
20
|
+
this.requestBody = new RequestBody(data?.metricDetailedConfiguration, data?.componentOptions);
|
|
17
21
|
}
|
|
18
22
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export default class
|
|
1
|
+
export default class RequestBody {
|
|
2
2
|
metricDetailedConfiguration: any;
|
|
3
|
-
componentOptions: Record<string, string
|
|
3
|
+
componentOptions: Record<string, string> | null | undefined;
|
|
4
4
|
|
|
5
|
-
constructor(
|
|
6
|
-
this.metricDetailedConfiguration =
|
|
7
|
-
this.componentOptions =
|
|
5
|
+
constructor(metricDetailedConfiguration: any, componentOptions: Record<string, string> | null | undefined) {
|
|
6
|
+
this.metricDetailedConfiguration = metricDetailedConfiguration;
|
|
7
|
+
this.componentOptions = componentOptions;
|
|
8
8
|
}
|
|
9
9
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { HeadersInfo } from "../interfaces/message";
|
|
2
|
+
|
|
1
3
|
export default class RequestsInfo {
|
|
2
|
-
kcHeaders:
|
|
4
|
+
kcHeaders: HeadersInfo[];
|
|
3
5
|
url: string;
|
|
4
6
|
|
|
5
|
-
constructor(
|
|
6
|
-
this.kcHeaders =
|
|
7
|
-
this.url =
|
|
7
|
+
constructor(headers: HeadersInfo[], url: string) {
|
|
8
|
+
this.kcHeaders = headers;
|
|
9
|
+
this.url = url;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import axios, { AxiosError, AxiosInstance, AxiosResponse } from "axios";
|
|
2
|
+
import { PostRequestAttributes } from "../../interfaces/message";
|
|
3
|
+
import QueryMetricDataAll from "../../models/query-metric-data-all";
|
|
4
|
+
import QueryMetricDataChunked from "../../models/query-metric-data-chunked";
|
|
5
|
+
import QueryMetricDataOnboarding from "../../models/query-metric-data-onboarding";
|
|
6
|
+
import logger from "../../logger/logger";
|
|
7
|
+
import ServiceBus from "../service-bus/service-bus-client";
|
|
8
|
+
|
|
9
|
+
export class ApiRequestService {
|
|
10
|
+
MaxRetryAttempts = 3;
|
|
11
|
+
|
|
12
|
+
protected readonly axiosInstance: AxiosInstance;
|
|
13
|
+
protected sbClient: ServiceBus;
|
|
14
|
+
protected message: QueryMetricDataAll | QueryMetricDataChunked | QueryMetricDataOnboarding;
|
|
15
|
+
|
|
16
|
+
constructor(baseUrl: string, message: QueryMetricDataAll | QueryMetricDataChunked | QueryMetricDataOnboarding, sbClient: ServiceBus) {
|
|
17
|
+
this.message = message;
|
|
18
|
+
this.sbClient = sbClient;
|
|
19
|
+
this.axiosInstance = axios.create({
|
|
20
|
+
baseURL: baseUrl,
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
maxContentLength: 100000000,
|
|
24
|
+
maxBodyLength: 1000000000
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
this.axiosInstance.interceptors.response.use(this.handleResponse, this.handleError);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async post<T>(url: string, requestAttributes: PostRequestAttributes): Promise<T> {
|
|
32
|
+
const response: AxiosResponse<T> = await this.axiosInstance.post(url, requestAttributes);
|
|
33
|
+
return response?.data;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private async handleResponse(response: AxiosResponse) {
|
|
37
|
+
return response;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private async handleError(error: AxiosError) {
|
|
41
|
+
if (error.response) {
|
|
42
|
+
// Rate limit exceeded, retry after the specified delay
|
|
43
|
+
const resetTimeInSeconds = parseInt(
|
|
44
|
+
error.response.headers['x-rate-limit-reset']
|
|
45
|
+
);
|
|
46
|
+
const delayInSeconds = resetTimeInSeconds + 1;
|
|
47
|
+
|
|
48
|
+
logger.error(`got error, wait time is ${delayInSeconds}, header value is: ${error.response.headers['x-rate-limit-reset']}`)
|
|
49
|
+
|
|
50
|
+
if (delayInSeconds > 0 && this.MaxRetryAttempts > 0) {
|
|
51
|
+
await new Promise((resolve) => setTimeout(resolve, delayInSeconds * 1000));
|
|
52
|
+
this.MaxRetryAttempts--;
|
|
53
|
+
return this.axiosInstance.post(error.request.config.url, { params: error.request.config.params, data: error.request.config.body } )
|
|
54
|
+
}else{
|
|
55
|
+
const message: QueryMetricDataChunked = new QueryMetricDataChunked(this.message);
|
|
56
|
+
const result = await this.sbClient.scheduleMessage(this.message.jobInfo.queueName, 2, message)
|
|
57
|
+
logger.info(`Message is reschedule ${JSON.stringify(message)}`);
|
|
58
|
+
logger.info(`Response of schdule message method ${result}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import logger from "../../logger/logger";
|
|
2
|
+
import QueryMetricDataAll from "../../models/query-metric-data-all";
|
|
3
|
+
import QueryMetricDataChunked from "../../models/query-metric-data-chunked";
|
|
4
|
+
import QueryMetricDataOnboarding from "../../models/query-metric-data-onboarding";
|
|
5
|
+
import ServiceBus from "../service-bus/service-bus-client";
|
|
6
|
+
import { ApiRequestService } from "./api-request-service";
|
|
7
|
+
|
|
8
|
+
class PersistenceClient {
|
|
9
|
+
protected axiosClient: ApiRequestService;
|
|
10
|
+
protected uniqueKey: string;
|
|
11
|
+
protected message: QueryMetricDataAll | QueryMetricDataChunked | QueryMetricDataOnboarding;
|
|
12
|
+
|
|
13
|
+
constructor(baseUrl: string, uniqueKey: string, message: QueryMetricDataAll | QueryMetricDataChunked | QueryMetricDataOnboarding, sbClient: ServiceBus) {
|
|
14
|
+
this.uniqueKey = uniqueKey;
|
|
15
|
+
this.message = message;
|
|
16
|
+
this.axiosClient = new ApiRequestService(baseUrl, message, sbClient);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected async persistData (data: unknown) {
|
|
20
|
+
const queryParams: Record<string, string> = {
|
|
21
|
+
startDate: this.message.jobInfo.startDate,
|
|
22
|
+
endDate: this.message.jobInfo.endDate,
|
|
23
|
+
tenantId: this.message.jobInfo.tenantId,
|
|
24
|
+
componentId: this.message.jobInfo.componentId,
|
|
25
|
+
connectorId: this.message.jobInfo.connectorId,
|
|
26
|
+
channelId: this.message.jobInfo.channelId,
|
|
27
|
+
persistenceCollection: this.message.jobInfo.persistenceCollection,
|
|
28
|
+
idKey: this.uniqueKey,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
logger.info("API call to persistence service to save data");
|
|
32
|
+
const response = await this.axiosClient.post("/save-data", { params: queryParams, data })
|
|
33
|
+
logger.info(`Response of persistence service after API call ${JSON.stringify(response)}`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
export default PersistenceClient;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { ProcessErrorArgs, ServiceBusClient, ServiceBusReceivedMessage } from "@azure/service-bus";
|
|
2
2
|
import QueryMetricDataAll from "../../models/query-metric-data-all";
|
|
3
|
-
import QueryMetricDataOnboarding from "../../models/query-metric-data-onboarding";
|
|
4
|
-
import PersistData from "../../models/persist-data.model";
|
|
5
|
-
import QueryMetricDataChunked from "../../models/query-metric-data-chunked";
|
|
6
3
|
|
|
7
4
|
type MessageHandler = (message: ServiceBusReceivedMessage) => void;
|
|
8
5
|
type ErrorHandler = (message: ProcessErrorArgs) => void;
|
|
@@ -13,7 +10,7 @@ class ServiceBus {
|
|
|
13
10
|
this.client = new ServiceBusClient(connectionString);
|
|
14
11
|
}
|
|
15
12
|
|
|
16
|
-
async sendMessage(queueName: string, message: QueryMetricDataAll
|
|
13
|
+
async sendMessage(queueName: string, message: QueryMetricDataAll) {
|
|
17
14
|
const sender = this.client.createSender(queueName);
|
|
18
15
|
try {
|
|
19
16
|
return await sender.sendMessages({ body: message });
|
|
@@ -28,10 +25,10 @@ class ServiceBus {
|
|
|
28
25
|
const receiver = this.client.createReceiver(queueName, { receiveMode: "peekLock" });
|
|
29
26
|
try {
|
|
30
27
|
await receiver.subscribe({
|
|
31
|
-
processMessage: async (messageReceived) => {
|
|
28
|
+
processMessage: async (messageReceived: ServiceBusReceivedMessage) => {
|
|
32
29
|
onMessage(messageReceived);
|
|
33
30
|
},
|
|
34
|
-
processError: async (err) => {
|
|
31
|
+
processError: async (err: ProcessErrorArgs) => {
|
|
35
32
|
onError(err);
|
|
36
33
|
}
|
|
37
34
|
});
|
|
@@ -51,7 +48,7 @@ class ServiceBus {
|
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
async scheduleMessage(queueName: string, scheduleTime: number, message: QueryMetricDataAll
|
|
51
|
+
async scheduleMessage(queueName: string, scheduleTime: number, message: QueryMetricDataAll) {
|
|
55
52
|
const sender = this.client.createSender(queueName);
|
|
56
53
|
const scheduledEnqueueTimeUtc = new Date(Date.now() + scheduleTime * 60 * 10000);
|
|
57
54
|
return await sender.scheduleMessages({
|