Skip to content

Commit

Permalink
move time range parsing logic
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellacosse committed Nov 14, 2024
1 parent 97c5317 commit 50ac9b4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 33 deletions.
16 changes: 15 additions & 1 deletion src/shadowbox/server/manager_service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as restify from 'restify';
import {InMemoryConfig, JsonConfig} from '../infrastructure/json_config';
import {AccessKey, AccessKeyRepository, DataLimit} from '../model/access_key';
import {ManagerMetrics} from './manager_metrics';
import {bindService, ShadowsocksManagerService} from './manager_service';
import {bindService, ShadowsocksManagerService, convertTimeRangeToHours} from './manager_service';
import {FakePrometheusClient, FakeShadowsocksServer} from './mocks/mocks';
import {AccessKeyConfigJson, ServerAccessKeyRepository} from './server_access_key';
import {ServerConfigJson} from './server_config';
Expand Down Expand Up @@ -1200,6 +1200,20 @@ describe('bindService', () => {
});
});

describe('convertTimeRangeToHours', () => {
it('properly parses time ranges', () => {
expect(convertTimeRangeToHours('30d')).toEqual(30 * 24);
expect(convertTimeRangeToHours('20h')).toEqual(20);
expect(convertTimeRangeToHours('3w')).toEqual(7 * 3 * 24);
});

it('throws when an invalid time range is provided', () => {
expect(() => convertTimeRangeToHours('30dd')).toThrow();
expect(() => convertTimeRangeToHours('hi mom')).toThrow();
expect(() => convertTimeRangeToHours('1j')).toThrow();
});
});

class ShadowsocksManagerServiceBuilder {
private defaultServerName_ = 'default name';
private serverConfig_: JsonConfig<ServerConfigJson> = null;
Expand Down
58 changes: 26 additions & 32 deletions src/shadowbox/server/manager_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,23 @@ function redirect(url: string): restify.RequestHandlerType {
};
}

export function convertTimeRangeToHours(timeRange: string): number {
const TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER = {
h: 1,
d: 24,
w: 7 * 24,
};

const timeRangeValue = Number(timeRange.slice(0, -1));
const timeRangeUnit = timeRange.slice(-1);

if (isNaN(timeRangeValue) || !TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER[timeRangeUnit]) {
throw new TypeError(`Invalid time range: ${timeRange}`);
}

return timeRangeValue * TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER[timeRangeUnit];
}

function validateAccessKeyId(accessKeyId: unknown): string {
if (!accessKeyId) {
throw new restifyErrors.MissingParameterError({statusCode: 400}, 'Parameter `id` is missing');
Expand Down Expand Up @@ -610,47 +627,24 @@ export class ShadowsocksManagerService {
}

async getServerMetrics(req: RequestType, res: ResponseType, next: restify.Next) {
const TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER = {
h: 1,
d: 24,
w: 7 * 24,
};
logging.debug(`getServerMetrics request ${JSON.stringify(req.params)}`);

let hours;
try {
logging.debug(`getServerMetrics request ${JSON.stringify(req.params)}`);

if (!req.query?.since) {
return next(
new restifyErrors.MissingParameterError({statusCode: 400}, 'Parameter `since` is missing')
);
}

const timeRange = req.query.since as string;
const timeRangeValue = Number(timeRange.slice(0, -1));

if (isNaN(timeRangeValue)) {
return next(
new restifyErrors.InvalidArgumentError(
{statusCode: 400},
`'since' parameter must be a time range in <number><unit> format. Got ${req.query.since}`
)
);
}

const timeRangeUnit = timeRange.slice(-1);

if (!(timeRangeUnit in TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER)) {
return next(
new restifyErrors.InvalidArgumentError(
{statusCode: 400},
`'since' parameter must be a time range with units in hours, days or weeks. Got ${req.query.since}`
)
);
}
hours = convertTimeRangeToHours(req.query.since as string);
} catch (error) {
logging.error(error);
return next(new restifyErrors.InvalidArgumentError({statusCode: 400}, error.message));
}

const response = await this.managerMetrics.getServerMetrics({
hours: timeRangeValue * TIME_RANGE_UNIT_TO_HOURS_MULTIPLYER[timeRangeUnit],
});
try {
const response = await this.managerMetrics.getServerMetrics({hours});
res.send(HttpSuccess.OK, response);
logging.debug(`getServerMetrics response ${JSON.stringify(response)}`);
return next();
Expand Down

0 comments on commit 50ac9b4

Please sign in to comment.