@hotmeshio/hotmesh 0.0.54 → 0.0.56
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/README.md +0 -3
- package/build/modules/enums.js +1 -10
- package/build/modules/key.d.ts +0 -38
- package/build/modules/key.js +4 -46
- package/build/modules/utils.d.ts +0 -8
- package/build/modules/utils.js +0 -14
- package/build/package.json +11 -4
- package/build/services/activities/activity.d.ts +0 -28
- package/build/services/activities/activity.js +1 -46
- package/build/services/activities/await.js +0 -4
- package/build/services/activities/cycle.d.ts +0 -7
- package/build/services/activities/cycle.js +1 -16
- package/build/services/activities/hook.d.ts +0 -6
- package/build/services/activities/hook.js +2 -12
- package/build/services/activities/interrupt.js +0 -8
- package/build/services/activities/signal.d.ts +0 -6
- package/build/services/activities/signal.js +0 -15
- package/build/services/activities/trigger.d.ts +0 -4
- package/build/services/activities/trigger.js +1 -7
- package/build/services/activities/worker.js +0 -4
- package/build/services/collator/index.d.ts +0 -70
- package/build/services/collator/index.js +1 -91
- package/build/services/compiler/deployer.js +6 -38
- package/build/services/compiler/index.d.ts +0 -15
- package/build/services/compiler/index.js +0 -20
- package/build/services/compiler/validator.d.ts +0 -3
- package/build/services/compiler/validator.js +0 -25
- package/build/services/connector/clients/ioredis.d.ts +2 -2
- package/build/services/connector/clients/ioredis.js +0 -2
- package/build/services/connector/clients/redis.d.ts +4 -4
- package/build/services/connector/clients/redis.js +1 -3
- package/build/services/connector/index.d.ts +1 -1
- package/build/services/connector/index.js +0 -2
- package/build/services/durable/client.d.ts +1 -26
- package/build/services/durable/client.js +0 -56
- package/build/services/durable/exporter.d.ts +0 -22
- package/build/services/durable/exporter.js +1 -30
- package/build/services/durable/handle.d.ts +0 -36
- package/build/services/durable/handle.js +0 -46
- package/build/services/durable/index.d.ts +0 -4
- package/build/services/durable/index.js +0 -4
- package/build/services/durable/schemas/factory.d.ts +0 -29
- package/build/services/durable/schemas/factory.js +0 -29
- package/build/services/durable/search.d.ts +1 -36
- package/build/services/durable/search.js +57 -56
- package/build/services/durable/worker.js +2 -22
- package/build/services/durable/workflow.d.ts +0 -114
- package/build/services/durable/workflow.js +4 -144
- package/build/services/engine/index.d.ts +1 -6
- package/build/services/engine/index.js +1 -43
- package/build/services/exporter/index.d.ts +0 -27
- package/build/services/exporter/index.js +0 -33
- package/build/services/hotmesh/index.d.ts +2 -2
- package/build/services/hotmesh/index.js +1 -9
- package/build/services/logger/index.js +0 -2
- package/build/services/mapper/index.d.ts +0 -14
- package/build/services/mapper/index.js +0 -14
- package/build/services/pipe/functions/date.d.ts +0 -7
- package/build/services/pipe/functions/date.js +0 -7
- package/build/services/pipe/functions/math.js +0 -2
- package/build/services/pipe/index.d.ts +0 -15
- package/build/services/pipe/index.js +2 -23
- package/build/services/quorum/index.d.ts +0 -7
- package/build/services/quorum/index.js +0 -21
- package/build/services/reporter/index.d.ts +0 -5
- package/build/services/reporter/index.js +0 -9
- package/build/services/router/index.d.ts +0 -9
- package/build/services/router/index.js +2 -38
- package/build/services/serializer/index.js +7 -26
- package/build/services/store/cache.d.ts +0 -18
- package/build/services/store/cache.js +0 -18
- package/build/services/store/clients/ioredis.d.ts +1 -1
- package/build/services/store/clients/ioredis.js +0 -1
- package/build/services/store/clients/redis.d.ts +1 -1
- package/build/services/store/index.d.ts +0 -55
- package/build/services/store/index.js +5 -81
- package/build/services/stream/clients/ioredis.d.ts +1 -1
- package/build/services/stream/clients/ioredis.js +1 -4
- package/build/services/stream/clients/redis.d.ts +1 -1
- package/build/services/sub/clients/ioredis.d.ts +1 -1
- package/build/services/sub/clients/redis.d.ts +1 -1
- package/build/services/task/index.d.ts +0 -9
- package/build/services/task/index.js +0 -31
- package/build/services/telemetry/index.d.ts +0 -7
- package/build/services/telemetry/index.js +1 -13
- package/build/services/worker/index.d.ts +0 -4
- package/build/services/worker/index.js +2 -6
- package/build/types/activity.d.ts +0 -81
- package/build/types/durable.d.ts +25 -177
- package/build/types/exporter.d.ts +0 -13
- package/build/types/hotmesh.d.ts +4 -16
- package/build/types/hotmesh.js +0 -3
- package/build/types/index.d.ts +4 -6
- package/build/types/index.js +4 -3
- package/build/types/job.d.ts +1 -86
- package/build/types/pipe.d.ts +0 -65
- package/build/types/quorum.d.ts +15 -10
- package/build/types/redis.d.ts +225 -7
- package/build/types/redis.js +9 -0
- package/build/types/stream.d.ts +0 -58
- package/build/types/stream.js +0 -4
- package/package.json +11 -4
- package/types/durable.ts +121 -3
- package/types/hotmesh.ts +3 -6
- package/types/index.ts +23 -10
- package/types/job.ts +1 -1
- package/types/quorum.ts +22 -0
- package/types/redis.ts +267 -18
- package/build/types/ioredisclient.d.ts +0 -5
- package/build/types/ioredisclient.js +0 -5
- package/build/types/redisclient.d.ts +0 -26
- package/build/types/redisclient.js +0 -2
- package/modules/enums.ts +0 -62
- package/modules/errors.ts +0 -280
- package/modules/key.ts +0 -101
- package/modules/storage.ts +0 -3
- package/modules/utils.ts +0 -242
- package/services/activities/activity.ts +0 -589
- package/services/activities/await.ts +0 -113
- package/services/activities/cycle.ts +0 -115
- package/services/activities/hook.ts +0 -197
- package/services/activities/index.ts +0 -19
- package/services/activities/interrupt.ts +0 -172
- package/services/activities/signal.ts +0 -148
- package/services/activities/trigger.ts +0 -295
- package/services/activities/worker.ts +0 -107
- package/services/collator/README.md +0 -102
- package/services/collator/index.ts +0 -291
- package/services/compiler/deployer.ts +0 -504
- package/services/compiler/index.ts +0 -98
- package/services/compiler/validator.ts +0 -158
- package/services/connector/clients/ioredis.ts +0 -57
- package/services/connector/clients/redis.ts +0 -72
- package/services/connector/index.ts +0 -42
- package/services/durable/client.ts +0 -266
- package/services/durable/connection.ts +0 -10
- package/services/durable/exporter.ts +0 -232
- package/services/durable/handle.ts +0 -160
- package/services/durable/index.ts +0 -27
- package/services/durable/schemas/factory.ts +0 -2358
- package/services/durable/search.ts +0 -196
- package/services/durable/worker.ts +0 -401
- package/services/durable/workflow.ts +0 -557
- package/services/engine/index.ts +0 -761
- package/services/exporter/index.ts +0 -146
- package/services/hotmesh/index.ts +0 -237
- package/services/logger/index.ts +0 -79
- package/services/mapper/index.ts +0 -89
- package/services/pipe/functions/array.ts +0 -78
- package/services/pipe/functions/bitwise.ts +0 -27
- package/services/pipe/functions/conditional.ts +0 -35
- package/services/pipe/functions/date.ts +0 -220
- package/services/pipe/functions/index.ts +0 -27
- package/services/pipe/functions/json.ts +0 -11
- package/services/pipe/functions/logical.ts +0 -11
- package/services/pipe/functions/math.ts +0 -217
- package/services/pipe/functions/number.ts +0 -75
- package/services/pipe/functions/object.ts +0 -98
- package/services/pipe/functions/string.ts +0 -86
- package/services/pipe/functions/symbol.ts +0 -39
- package/services/pipe/functions/unary.ts +0 -19
- package/services/pipe/index.ts +0 -216
- package/services/quorum/index.ts +0 -319
- package/services/reporter/index.ts +0 -387
- package/services/router/index.ts +0 -426
- package/services/serializer/README.md +0 -10
- package/services/serializer/index.ts +0 -285
- package/services/store/cache.ts +0 -172
- package/services/store/clients/ioredis.ts +0 -145
- package/services/store/clients/redis.ts +0 -191
- package/services/store/index.ts +0 -1091
- package/services/stream/clients/ioredis.ts +0 -157
- package/services/stream/clients/redis.ts +0 -158
- package/services/stream/index.ts +0 -58
- package/services/sub/clients/ioredis.ts +0 -83
- package/services/sub/clients/redis.ts +0 -74
- package/services/sub/index.ts +0 -25
- package/services/task/index.ts +0 -250
- package/services/telemetry/index.ts +0 -273
- package/services/worker/index.ts +0 -248
- package/types/ioredisclient.ts +0 -10
- package/types/redisclient.ts +0 -30
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
import { ILogger } from '../logger';
|
|
2
|
-
import { Pipe } from '../pipe';
|
|
3
|
-
import { StoreService } from '../store';
|
|
4
|
-
import { TriggerActivity } from '../../types/activity';
|
|
5
|
-
import { AppVID } from '../../types/app';
|
|
6
|
-
import { JobState } from '../../types/job';
|
|
7
|
-
import { RedisClient, RedisMulti } from '../../types/redis';
|
|
8
|
-
import {
|
|
9
|
-
GetStatsOptions,
|
|
10
|
-
StatsResponse,
|
|
11
|
-
AggregatedData,
|
|
12
|
-
Measure,
|
|
13
|
-
Segment,
|
|
14
|
-
JobStatsRange,
|
|
15
|
-
IdsData,
|
|
16
|
-
IdsResponse,
|
|
17
|
-
MeasureIds,
|
|
18
|
-
TimeSegment,
|
|
19
|
-
CountByFacet,
|
|
20
|
-
StatsType,
|
|
21
|
-
StatType } from '../../types/stats';
|
|
22
|
-
|
|
23
|
-
class ReporterService {
|
|
24
|
-
private appVersion: AppVID;
|
|
25
|
-
private logger: ILogger;
|
|
26
|
-
private store: StoreService<RedisClient, RedisMulti>;
|
|
27
|
-
static DEFAULT_GRANULARITY = '5m';
|
|
28
|
-
|
|
29
|
-
constructor(appVersion: AppVID, store: StoreService<RedisClient, RedisMulti>, logger: ILogger) {
|
|
30
|
-
this.appVersion = appVersion;
|
|
31
|
-
this.logger = logger;
|
|
32
|
-
this.store = store;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async getStats(options: GetStatsOptions): Promise<StatsResponse> {
|
|
36
|
-
this.logger.debug('reporter-getstats-started', options);
|
|
37
|
-
const { key, granularity, range, end, start } = options;
|
|
38
|
-
this.validateOptions(options);
|
|
39
|
-
const dateTimeSets = this.generateDateTimeSets(granularity, range, end, start);
|
|
40
|
-
const redisKeys = dateTimeSets.map((dateTime) => this.buildRedisKey(key, dateTime));
|
|
41
|
-
const rawData = await this.store.getJobStats(redisKeys);
|
|
42
|
-
const [count, aggregatedData] = this.aggregateData(rawData);
|
|
43
|
-
const statsResponse = this.buildStatsResponse(rawData, redisKeys, aggregatedData, count, options);
|
|
44
|
-
return statsResponse;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private validateOptions(options: GetStatsOptions): void {
|
|
48
|
-
const { start, end, range, granularity } = options;
|
|
49
|
-
if (granularity !== 'infinity' && (start && end && range || !start && !end && !range)) {
|
|
50
|
-
throw new Error('Invalid combination of start, end, and range values. Provide either start+end, end+range, or start+range.');
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private generateDateTimeSets(granularity: string, range: string|undefined, end: string, start?: string): string[] {
|
|
55
|
-
if (granularity === 'infinity') {
|
|
56
|
-
//if granularity is infinity, it means a date/time sequence/slice is not used to further segment the statistics
|
|
57
|
-
return ['0'];
|
|
58
|
-
}
|
|
59
|
-
if (!range) {
|
|
60
|
-
//pluck just a single value when no range provided
|
|
61
|
-
range = '0m';
|
|
62
|
-
}
|
|
63
|
-
const granularitiesInMinutes = {
|
|
64
|
-
'5m': 5,
|
|
65
|
-
'10m': 10,
|
|
66
|
-
'15m': 15,
|
|
67
|
-
'30m': 30,
|
|
68
|
-
'1h': 60,
|
|
69
|
-
};
|
|
70
|
-
const granularityMinutes = granularitiesInMinutes[granularity];
|
|
71
|
-
if (!granularityMinutes) {
|
|
72
|
-
throw new Error('Invalid granularity value.');
|
|
73
|
-
}
|
|
74
|
-
const rangeMinutes = this.convertRangeToMinutes(range);
|
|
75
|
-
if (rangeMinutes === null) {
|
|
76
|
-
throw new Error('Invalid range value.');
|
|
77
|
-
}
|
|
78
|
-
// If start is provided, use it. Otherwise, calculate it from the end time and range.
|
|
79
|
-
let startTime;
|
|
80
|
-
let endTime;
|
|
81
|
-
if (start) {
|
|
82
|
-
startTime = new Date(start);
|
|
83
|
-
endTime = new Date(startTime.getTime() + rangeMinutes * 60 * 1000);
|
|
84
|
-
} else {
|
|
85
|
-
endTime = end === 'NOW' ? new Date() : new Date(end);
|
|
86
|
-
startTime = new Date(endTime.getTime() - rangeMinutes * 60 * 1000);
|
|
87
|
-
}
|
|
88
|
-
// Round the start time to the nearest granularity unit
|
|
89
|
-
startTime.setUTCMinutes(
|
|
90
|
-
Math.floor(startTime.getUTCMinutes() / granularityMinutes) * granularityMinutes
|
|
91
|
-
);
|
|
92
|
-
const dateTimeSets: string[] = [];
|
|
93
|
-
for (
|
|
94
|
-
let time = startTime;
|
|
95
|
-
time <= endTime;
|
|
96
|
-
time.setUTCMinutes(time.getUTCMinutes() + granularityMinutes)
|
|
97
|
-
) {
|
|
98
|
-
const formattedTime = [
|
|
99
|
-
time.getUTCFullYear(),
|
|
100
|
-
String(time.getUTCMonth() + 1).padStart(2, '0'),
|
|
101
|
-
String(time.getUTCDate()).padStart(2, '0'),
|
|
102
|
-
String(time.getUTCHours()).padStart(2, '0'),
|
|
103
|
-
String(time.getUTCMinutes()).padStart(2, '0'),
|
|
104
|
-
].join('');
|
|
105
|
-
dateTimeSets.push(formattedTime);
|
|
106
|
-
}
|
|
107
|
-
return dateTimeSets;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private convertRangeToMinutes(range: string): number | null {
|
|
111
|
-
const timeUnit = range.slice(-1);
|
|
112
|
-
const value = parseInt(range.slice(0, -1), 10);
|
|
113
|
-
if (isNaN(value)) {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
switch (timeUnit) {
|
|
117
|
-
case 'm':
|
|
118
|
-
return value;
|
|
119
|
-
case 'h':
|
|
120
|
-
return value * 60;
|
|
121
|
-
case 'd':
|
|
122
|
-
return value * 60 * 24;
|
|
123
|
-
default:
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
private buildRedisKey(key: string, dateTime: string, subTarget = ''): string {
|
|
129
|
-
return `hmsh:${this.appVersion.id}:s:${key}:${dateTime}${subTarget?':'+subTarget:''}`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private aggregateData(rawData: JobStatsRange): [number, AggregatedData] {
|
|
133
|
-
const aggregatedData: AggregatedData = {};
|
|
134
|
-
let count = 0;
|
|
135
|
-
Object.entries(rawData).forEach(([_, data]) => {
|
|
136
|
-
for (const key in data) {
|
|
137
|
-
if (key.startsWith('count:')) {
|
|
138
|
-
const target = key.slice('count:'.length);
|
|
139
|
-
if (!aggregatedData[target]) {
|
|
140
|
-
aggregatedData[target] = 0;
|
|
141
|
-
}
|
|
142
|
-
aggregatedData[target] += data[key];
|
|
143
|
-
} else if (key === 'count') {
|
|
144
|
-
count += data[key];
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
return [count, aggregatedData];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private buildStatsResponse(rawData: JobStatsRange, redisKeys: string[], aggregatedData: AggregatedData, count: number, options: GetStatsOptions): StatsResponse {
|
|
152
|
-
const measures: Measure[] = [];
|
|
153
|
-
const measureKeys = Object.keys(aggregatedData).filter((key) => key !== "count");
|
|
154
|
-
let segments = undefined;
|
|
155
|
-
if (options.sparse !== true) {
|
|
156
|
-
segments = this.handleSegments(rawData, redisKeys);
|
|
157
|
-
}
|
|
158
|
-
measureKeys.forEach((key) => {
|
|
159
|
-
const measure: Measure = {
|
|
160
|
-
target: key,
|
|
161
|
-
type: "count",
|
|
162
|
-
value: aggregatedData[key],
|
|
163
|
-
};
|
|
164
|
-
measures.push(measure);
|
|
165
|
-
});
|
|
166
|
-
const response: StatsResponse = {
|
|
167
|
-
key: options.key,
|
|
168
|
-
granularity: options.granularity,
|
|
169
|
-
range: options.range,
|
|
170
|
-
end: options.end,
|
|
171
|
-
count,
|
|
172
|
-
measures: measures,
|
|
173
|
-
};
|
|
174
|
-
if (segments) {
|
|
175
|
-
response.segments = segments;
|
|
176
|
-
}
|
|
177
|
-
return response;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
private handleSegments(data: JobStatsRange, hashKeys: string[]): Segment[] {
|
|
181
|
-
const segments: Segment[] = [];
|
|
182
|
-
hashKeys.forEach((hashKey, index) => {
|
|
183
|
-
const segmentData: Measure[] = [];
|
|
184
|
-
data[hashKey] && Object.entries(data[hashKey]).forEach(([key, value]) => {
|
|
185
|
-
if (key.startsWith('count:')) {
|
|
186
|
-
const target = key.slice('count:'.length);
|
|
187
|
-
segmentData.push({ target, type: 'count', value });
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
const isoTimestamp = this.isoTimestampFromKeyTimestamp(hashKey);
|
|
191
|
-
const count = data[hashKey] ? data[hashKey].count : 0;
|
|
192
|
-
segments.push({ count, time: isoTimestamp, measures: segmentData });
|
|
193
|
-
});
|
|
194
|
-
return segments;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private isoTimestampFromKeyTimestamp(hashKey: string): string {
|
|
198
|
-
if (hashKey.endsWith(':')) {
|
|
199
|
-
return '0';
|
|
200
|
-
}
|
|
201
|
-
const keyTimestamp = hashKey.slice(-12);
|
|
202
|
-
const year = keyTimestamp.slice(0, 4);
|
|
203
|
-
const month = keyTimestamp.slice(4, 6);
|
|
204
|
-
const day = keyTimestamp.slice(6, 8);
|
|
205
|
-
const hour = keyTimestamp.slice(8, 10);
|
|
206
|
-
const minute = keyTimestamp.slice(10, 12);
|
|
207
|
-
return `${year}-${month}-${day}T${hour}:${minute}Z`;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
async getIds(options: GetStatsOptions, facets: string[], idRange: [number, number] = [0, -1]): Promise<IdsResponse> {
|
|
211
|
-
if (!facets.length) {
|
|
212
|
-
const stats = await this.getStats(options);
|
|
213
|
-
facets = this.getUniqueFacets(stats);
|
|
214
|
-
}
|
|
215
|
-
const { key, granularity, range, end, start } = options;
|
|
216
|
-
this.validateOptions(options);
|
|
217
|
-
let redisKeys: string[] = [];
|
|
218
|
-
facets.forEach((facet) => {
|
|
219
|
-
const dateTimeSets = this.generateDateTimeSets(granularity, range, end, start);
|
|
220
|
-
redisKeys = redisKeys.concat(dateTimeSets.map((dateTime) => this.buildRedisKey(key, dateTime, `index:${facet}`)));
|
|
221
|
-
});
|
|
222
|
-
const idsData = await this.store.getJobIds(redisKeys, idRange);
|
|
223
|
-
const idsResponse = this.buildIdsResponse(idsData, options, facets);
|
|
224
|
-
return idsResponse;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private buildIdsResponse(idsData: IdsData, options: GetStatsOptions, facets: string[]): IdsResponse {
|
|
228
|
-
const countsByFacet: { [key: string]: number } = {};
|
|
229
|
-
const measureKeys = Object.keys(idsData);
|
|
230
|
-
measureKeys.forEach((key) => {
|
|
231
|
-
const target = this.getTargetForKey(key as string);
|
|
232
|
-
const count = idsData[key].length;
|
|
233
|
-
|
|
234
|
-
if (countsByFacet[target]) {
|
|
235
|
-
countsByFacet[target] += count;
|
|
236
|
-
} else {
|
|
237
|
-
countsByFacet[target] = count;
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
const counts: CountByFacet[] = Object.entries(countsByFacet).map(([facet, count]) => ({ facet, count }));
|
|
241
|
-
const response: IdsResponse = {
|
|
242
|
-
key: options.key,
|
|
243
|
-
facets,
|
|
244
|
-
granularity: options.granularity,
|
|
245
|
-
range: options.range,
|
|
246
|
-
start: options.start,
|
|
247
|
-
counts,
|
|
248
|
-
segments: this.buildTimeSegments(idsData),
|
|
249
|
-
};
|
|
250
|
-
return response;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
private buildTimeSegments(idsData: IdsData): TimeSegment[] {
|
|
254
|
-
const measureKeys = Object.keys(idsData);
|
|
255
|
-
const timeSegments: { [time: string]: MeasureIds[] } = {};
|
|
256
|
-
|
|
257
|
-
measureKeys.forEach((key) => {
|
|
258
|
-
const measure: MeasureIds = {
|
|
259
|
-
type: 'ids',
|
|
260
|
-
target: this.getTargetForKey(key as string),
|
|
261
|
-
time: this.isoTimestampFromKeyTimestamp(this.getTargetForTime(key as string)),
|
|
262
|
-
count: idsData[key].length,
|
|
263
|
-
ids: idsData[key],
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
if (timeSegments[measure.time]) {
|
|
267
|
-
timeSegments[measure.time].push(measure);
|
|
268
|
-
} else {
|
|
269
|
-
timeSegments[measure.time] = [measure];
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
const segments: TimeSegment[] = Object.entries(timeSegments).map(([time, measures]) => ({
|
|
274
|
-
time,
|
|
275
|
-
measures,
|
|
276
|
-
}));
|
|
277
|
-
|
|
278
|
-
return segments;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
getUniqueFacets(data: StatsResponse): string[] {
|
|
282
|
-
const targets = data.measures.map(measure => measure.target);
|
|
283
|
-
return Array.from(new Set(targets));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
getTargetForKey(key: string): string {
|
|
287
|
-
return key.split(':index:')[1];
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
getTargetForTime(key: string): string {
|
|
291
|
-
return key.split(':index:')[0];
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
async getWorkItems(options: GetStatsOptions, facets: string[]): Promise<string[]> {
|
|
295
|
-
if (!facets.length) {
|
|
296
|
-
const stats = await this.getStats(options);
|
|
297
|
-
facets = this.getUniqueFacets(stats);
|
|
298
|
-
}
|
|
299
|
-
const { key, granularity, range, end, start } = options;
|
|
300
|
-
this.validateOptions(options);
|
|
301
|
-
let redisKeys: string[] = [];
|
|
302
|
-
facets.forEach((facet) => {
|
|
303
|
-
const dateTimeSets = this.generateDateTimeSets(granularity, range, end, start);
|
|
304
|
-
redisKeys = redisKeys.concat(dateTimeSets.map((dateTime) => this.buildRedisKey(key, dateTime, `index:${facet}`)));
|
|
305
|
-
});
|
|
306
|
-
const idsData = await this.store.getJobIds(redisKeys, [0, 1]);
|
|
307
|
-
const workerLists = this.buildWorkerLists(idsData);
|
|
308
|
-
return workerLists;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
private buildWorkerLists(idsData: IdsData): string[] {
|
|
312
|
-
const workerLists: string[] = [];
|
|
313
|
-
for (const key in idsData) {
|
|
314
|
-
if (idsData[key].length) {
|
|
315
|
-
workerLists.push(key);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return workerLists;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* called by `trigger` activity to generate the stats that should
|
|
323
|
-
* be saved to the database. doesn't actually save the stats, but
|
|
324
|
-
* just generates the info that should be saved
|
|
325
|
-
*/
|
|
326
|
-
resolveTriggerStatistics({ stats: statsConfig}: TriggerActivity, context: JobState): StatsType {
|
|
327
|
-
const stats: StatsType = {
|
|
328
|
-
general: [],
|
|
329
|
-
index: [],
|
|
330
|
-
median: []
|
|
331
|
-
}
|
|
332
|
-
stats.general.push({ metric: 'count', target: 'count', value: 1 });
|
|
333
|
-
for (const measure of statsConfig.measures) {
|
|
334
|
-
const metric = this.resolveMetric({ metric: measure.measure, target: measure.target }, context);
|
|
335
|
-
if (this.isGeneralMetric(measure.measure)) {
|
|
336
|
-
stats.general.push(metric);
|
|
337
|
-
} else if (this.isMedianMetric(measure.measure)) {
|
|
338
|
-
stats.median.push(metric);
|
|
339
|
-
} else if (this.isIndexMetric(measure.measure)) {
|
|
340
|
-
stats.index.push(metric);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return stats;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
isGeneralMetric(metric: string): boolean {
|
|
347
|
-
return metric === 'sum' || metric === 'avg' || metric === 'count';
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
isMedianMetric(metric: string): boolean {
|
|
351
|
-
return metric === 'mdn';
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
isIndexMetric(metric: string): boolean {
|
|
355
|
-
return metric === 'index';
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
resolveMetric({metric, target}, context: JobState): StatType {
|
|
359
|
-
const pipe = new Pipe([[target]], context);
|
|
360
|
-
const resolvedValue = pipe.process().toString();
|
|
361
|
-
const resolvedTarget = this.resolveTarget(metric, target, resolvedValue);
|
|
362
|
-
if (metric === 'index') {
|
|
363
|
-
return { metric, target: resolvedTarget, value: context.metadata.jid };
|
|
364
|
-
} else if (metric === 'count') {
|
|
365
|
-
return { metric, target: resolvedTarget, value: 1 };
|
|
366
|
-
}
|
|
367
|
-
return { metric, target: resolvedTarget, value: resolvedValue } as StatType;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
isCardinalMetric(metric: string): boolean {
|
|
371
|
-
return metric === 'index' || metric === 'count';
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
resolveTarget(metric: string, target: string, resolvedValue: string): string {
|
|
375
|
-
const trimmed = target.substring(1, target.length - 1);
|
|
376
|
-
const trimmedTarget = trimmed.split('.').slice(3).join('/');
|
|
377
|
-
let resolvedTarget: string;
|
|
378
|
-
if (this.isCardinalMetric(metric)) {
|
|
379
|
-
resolvedTarget = `${metric}:${trimmedTarget}:${resolvedValue}`;
|
|
380
|
-
} else {
|
|
381
|
-
resolvedTarget = `${metric}:${trimmedTarget}`;
|
|
382
|
-
}
|
|
383
|
-
return resolvedTarget;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export { ReporterService };
|