Skip to content

Commit 2bf0cfb

Browse files
feat: initially implement locations as id
1 parent f38f289 commit 2bf0cfb

File tree

5 files changed

+40
-22
lines changed

5 files changed

+40
-22
lines changed

Diff for: src/lib/http/middleware/ratelimit.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ const setResponseHeaders = (ctx: Context, response: RateLimiterRes) => {
1212
};
1313

1414
export const rateLimitHandler = () => async (ctx: Context, next: Next) => {
15-
const { isAdmin } = ctx;
15+
// const { isAdmin } = ctx;
1616
const clientIp = requestIp.getClientIp(ctx.req) ?? '';
17-
const request = ctx.request.body as MeasurementRequest;
18-
const limit = request.locations.some(l => l.limit) ? request.locations.reduce((sum, { limit = 1 }) => sum + limit, 0) : request.limit;
17+
// const request = ctx.request.body as MeasurementRequest;
18+
// const limit = request.locations.some(l => l.limit) ? request.locations.reduce((sum, { limit = 1 }) => sum + limit, 0) : request.limit;
1919

20-
if (isAdmin) {
21-
return next();
22-
}
20+
// if (isAdmin) {
21+
// return next();
22+
// }
2323

24-
const currentState = await rateLimiter.get(clientIp) ?? defaultState as RateLimiterRes;
24+
// const currentState = await rateLimiter.get(clientIp) ?? defaultState as RateLimiterRes;
2525

26-
if (currentState.remainingPoints < limit) {
27-
setResponseHeaders(ctx, currentState);
28-
throw createHttpError(429, 'API rate limit exceeded.', { type: 'rate_limit_exceeded' });
29-
}
26+
// if (currentState.remainingPoints < limit) {
27+
// setResponseHeaders(ctx, currentState);
28+
// throw createHttpError(429, 'API rate limit exceeded.', { type: 'rate_limit_exceeded' });
29+
// }
3030

3131
await next();
3232
const response = ctx.response.body as object & { probesCount?: number };

Diff for: src/measurement/schema/global-schema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const schema = Joi.object({
1313
type: Joi.string().valid('ping', 'traceroute', 'dns', 'mtr', 'http').insensitive().required(),
1414
target: targetSchema,
1515
measurementOptions: measurementSchema,
16-
locations: locationSchema,
16+
locations: Joi.alternatives().try(locationSchema, Joi.string()),
1717
limit: Joi.number().min(1).max(measurementConfig.limits.global).default(GLOBAL_DEFAULTS.limit),
1818
inProgressUpdates: Joi.bool().default(GLOBAL_DEFAULTS.inProgressUpdates),
1919
});

Diff for: src/measurement/store.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const substractObjects = (obj1: Record<string, unknown>, obj2: Record<string, un
2121
const value1 = obj1[key];
2222
const value2 = obj2[key];
2323

24-
if (_.isPlainObject(value1)) {
24+
if (_.isPlainObject(value1) && _.isPlainObject(value2)) {
2525
const difference = substractObjects(value1 as Record<string, unknown>, value2 as Record<string, unknown>);
2626

2727
if (!_.isEmpty(difference)) {
@@ -93,6 +93,12 @@ export class MeasurementStore {
9393
]);
9494
}
9595

96+
async getIpsByMeasurementId (id: string): Promise<string[]> {
97+
const key = getMeasurementKey(id, 'ips');
98+
const ips = await this.redis.json.get(key) as string[] | null;
99+
return ips || [];
100+
}
101+
96102
async markFinishedByTimeout (ids: string[]): Promise<void> {
97103
if (ids.length === 0) {
98104
return;
@@ -151,8 +157,11 @@ export class MeasurementStore {
151157

152158
removeDefaults (measurement: MeasurementRecord, request: MeasurementRequest): Partial<MeasurementRecord> {
153159
const defaults = getDefaults(request);
160+
154161
// Removes `"limit": 1` from locations. E.g. [{"country": "US", "limit": 1}] => [{"country": "US"}]
155-
measurement.locations = measurement.locations.map(location => location.limit === 1 ? _.omit(location, 'limit') : location);
162+
if (_.isArray(measurement.locations)) {
163+
measurement.locations = measurement.locations.map(location => location.limit === 1 ? _.omit(location, 'limit') : location);
164+
}
156165

157166
return substractObjects(measurement, defaults) as Partial<MeasurementRecord>;
158167
}

Diff for: src/measurement/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export type MeasurementRequest = {
176176
type: 'ping' | 'traceroute' | 'dns' | 'http' | 'mtr';
177177
target: string;
178178
measurementOptions: MeasurementOptions;
179-
locations: LocationWithLimit[];
179+
locations: LocationWithLimit[] | string;
180180
limit: number;
181181
inProgressUpdates: boolean;
182182
};
@@ -207,7 +207,7 @@ export type MeasurementRecord = {
207207
target: string;
208208
limit: number;
209209
probesCount: number;
210-
locations: LocationWithLimit[];
210+
locations: LocationWithLimit[] | string;
211211
measurementOptions?: MeasurementOptions;
212212
results: MeasurementResult[];
213213
};

Diff for: src/probe/router.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,25 @@ import type { LocationWithLimit } from '../measurement/types.js';
55
import type { Location } from '../lib/location/types.js';
66
import type { Probe } from './types.js';
77
import { SocketsLocationFilter } from './sockets-location-filter.js';
8+
import { getMeasurementStore } from '../measurement/store.js';
89

910
export class ProbeRouter {
10-
constructor (
11-
private readonly fetchWsSockets: typeof fetchSockets,
12-
private readonly socketsFilter = new SocketsLocationFilter(),
13-
) {}
11+
private readonly socketsFilter = new SocketsLocationFilter();
12+
13+
private readonly store = getMeasurementStore();
14+
15+
constructor (private readonly fetchWsSockets: typeof fetchSockets) {}
1416

1517
public async findMatchingProbes (
16-
locations: LocationWithLimit[] = [],
18+
locations: LocationWithLimit[] | string = [],
1719
globalLimit = 1,
1820
): Promise<Probe[]> {
1921
const sockets = await this.fetchSockets();
2022
let filtered: RemoteProbeSocket[] = [];
2123

22-
if (locations.some(l => l.limit)) {
24+
if (typeof locations === 'string') {
25+
filtered = await this.findWithMeasurementId(sockets, locations);
26+
} else if (locations.some(l => l.limit)) {
2327
filtered = this.findWithLocationLimit(sockets, locations);
2428
} else if (locations.length > 0) {
2529
filtered = this.findWithGlobalLimit(sockets, locations, globalLimit);
@@ -68,6 +72,11 @@ export class ProbeRouter {
6872

6973
return [ ...picked ];
7074
}
75+
76+
private async findWithMeasurementId (sockets: RemoteProbeSocket[], measurementId: string): Promise<RemoteProbeSocket[]> {
77+
const ips = await this.store.getIpsByMeasurementId(measurementId);
78+
return sockets.filter(socket => ips.includes(socket.data.probe.ipAddress));
79+
}
7180
}
7281

7382
// Factory

0 commit comments

Comments
 (0)