add georouter creator injection

This commit is contained in:
sbriat 2023-04-13 11:19:04 +02:00
parent 4c3195390e
commit ca03d1769a
13 changed files with 104 additions and 35 deletions

View File

@ -10,6 +10,7 @@ import { Match } from '../../domain/entities/match';
import { MatchQuery } from '../../queries/match.query';
import { MatchPresenter } from '../secondaries/match.presenter';
import { DefaultParamsProvider } from '../secondaries/default-params.provider';
import { GeorouterCreator } from '../secondaries/georouter-creator';
@UsePipes(
new RpcValidationPipe({
@ -23,13 +24,18 @@ export class MatcherController {
private readonly _queryBus: QueryBus,
private readonly _defaultParamsProvider: DefaultParamsProvider,
@InjectMapper() private readonly _mapper: Mapper,
private readonly _georouterCreator: GeorouterCreator,
) {}
@GrpcMethod('MatcherService', 'Match')
async match(data: MatchRequest): Promise<ICollection<Match>> {
try {
const matchCollection = await this._queryBus.execute(
new MatchQuery(data, this._defaultParamsProvider.getParams()),
new MatchQuery(
data,
this._defaultParamsProvider.getParams(),
this._georouterCreator,
),
);
return Promise.resolve({
data: matchCollection.data.map((match: Match) =>

View File

@ -25,8 +25,8 @@ message MatchRequest {
int32 proportion = 16;
bool useAzimuth = 17;
int32 azimuthMargin = 18;
int32 maxDetourDistanceRatio = 19;
int32 maxDetourDurationRatio = 20;
float maxDetourDistanceRatio = 19;
float maxDetourDurationRatio = 20;
repeated int32 exclusions = 21;
int32 identifier = 22;
}

View File

@ -1,8 +1,11 @@
import { Georouter } from '../../domain/interfaces/georouter.interface';
import { Injectable } from '@nestjs/common';
import { ICreateGeorouter } from '../../domain/interfaces/georouter-creator.interface';
import { IGeorouter } from '../../domain/interfaces/georouter.interface';
import { GraphhopperGeorouter } from './graphhopper-georouter';
export class GeorouterCreator {
create(type: string, url: string): Georouter {
@Injectable()
export class GeorouterCreator implements ICreateGeorouter {
create(type: string, url: string): IGeorouter {
switch (type) {
case 'graphhopper':
return new GraphhopperGeorouter(url);

View File

@ -1,19 +1,15 @@
import { Route } from '../../domain/entities/route';
import { Georouter } from '../../domain/interfaces/georouter.interface';
import { IGeorouter } from '../../domain/interfaces/georouter.interface';
import { GeorouterSettings } from '../../domain/types/georouter-settings.type';
export class GraphhopperGeorouter implements Georouter {
export class GraphhopperGeorouter implements IGeorouter {
_url: string;
constructor(url: string) {
this._url = url + '/route?';
}
route(
routesRequested: [],
withPoints: boolean,
withTime: boolean,
withDistance: boolean,
): Route[] {
route(routesRequested: [], settings: GeorouterSettings): Route[] {
throw new Error('Method not implemented.');
}
}

View File

@ -2,6 +2,8 @@ import { IRequestAlgorithmSettings } from '../interfaces/algorithm-settings-requ
import { DefaultAlgorithmSettings } from '../types/default-algorithm-settings.type';
import { Algorithm } from '../types/algorithm.enum';
import { TimingFrequency } from '../types/timing';
import { ICreateGeorouter } from '../interfaces/georouter-creator.interface';
import { IGeorouter } from '../interfaces/georouter.interface';
export class AlgorithmSettings {
_algorithmSettingsRequest: IRequestAlgorithmSettings;
@ -15,13 +17,13 @@ export class AlgorithmSettings {
azimuthMargin: number;
maxDetourDurationRatio: number;
maxDetourDistanceRatio: number;
georouterType: string;
georouterUrl: string;
georouter: IGeorouter;
constructor(
algorithmSettingsRequest: IRequestAlgorithmSettings,
defaultAlgorithmSettings: DefaultAlgorithmSettings,
frequency: TimingFrequency,
georouterCreator: ICreateGeorouter,
) {
this._algorithmSettingsRequest = algorithmSettingsRequest;
this.algorithm =
@ -49,8 +51,10 @@ export class AlgorithmSettings {
this.maxDetourDurationRatio =
algorithmSettingsRequest.maxDetourDurationRatio ??
defaultAlgorithmSettings.maxDetourDurationRatio;
this.georouterType = defaultAlgorithmSettings.georouterType;
this.georouterUrl = defaultAlgorithmSettings.georouterUrl;
this.georouter = georouterCreator.create(
defaultAlgorithmSettings.georouterType,
defaultAlgorithmSettings.georouterUrl,
);
if (this._strict) {
this.restrict = frequency;
}

View File

@ -0,0 +1,5 @@
import { IGeorouter } from './georouter.interface';
export interface ICreateGeorouter {
create(type: string, url: string): IGeorouter;
}

View File

@ -1,10 +1,6 @@
import { Route } from '../entities/route';
import { GeorouterSettings } from '../types/georouter-settings.type';
export interface Georouter {
route(
routesRequested: [],
withPoints: boolean,
withTime: boolean,
withDistance: boolean,
): Array<Route>;
export interface IGeorouter {
route(routesRequested: [], settings: GeorouterSettings): Array<Route>;
}

View File

@ -0,0 +1,5 @@
export type GeorouterSettings = {
withPoints: boolean;
withTime: boolean;
withDistance: boolean;
};

View File

@ -12,6 +12,7 @@ import { CacheModule } from '@nestjs/cache-manager';
import { RedisClientOptions } from '@liaoliaots/nestjs-redis';
import { redisStore } from 'cache-manager-ioredis-yet';
import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider';
import { GeorouterCreator } from './adapters/secondaries/georouter-creator';
@Module({
imports: [
@ -51,6 +52,7 @@ import { DefaultParamsProvider } from './adapters/secondaries/default-params.pro
Messager,
DefaultParamsProvider,
MatchUseCase,
GeorouterCreator,
],
exports: [],
})

View File

@ -6,10 +6,13 @@ import { Role } from '../domain/types/role.enum';
import { AlgorithmSettings } from '../domain/entities/algorithm-settings';
import { Time } from '../domain/entities/time';
import { IDefaultParams } from '../domain/types/default-params.type';
import { IGeorouter } from '../domain/interfaces/georouter.interface';
import { ICreateGeorouter } from '../domain/interfaces/georouter-creator.interface';
export class MatchQuery {
private readonly _matchRequest: MatchRequest;
private readonly _defaultParams: IDefaultParams;
private readonly _georouterCreator: ICreateGeorouter;
person: Person;
roles: Array<Role>;
time: Time;
@ -17,10 +20,16 @@ export class MatchQuery {
exclusions: Array<number>;
requirement: Requirement;
algorithmSettings: AlgorithmSettings;
georouter: IGeorouter;
constructor(matchRequest: MatchRequest, defaultParams: IDefaultParams) {
constructor(
matchRequest: MatchRequest,
defaultParams: IDefaultParams,
georouterCreator: ICreateGeorouter,
) {
this._matchRequest = matchRequest;
this._defaultParams = defaultParams;
this._georouterCreator = georouterCreator;
this._setPerson();
this._setRoles();
this._setTime();
@ -75,6 +84,7 @@ export class MatchQuery {
this._matchRequest,
this._defaultParams.DEFAULT_ALGORITHM_SETTINGS,
this.time.frequency,
this._georouterCreator,
);
}

View File

@ -11,6 +11,12 @@ describe('Graphhopper Georouter', () => {
const graphhopperGeorouter: GraphhopperGeorouter = new GraphhopperGeorouter(
'http://localhost',
);
expect(() => graphhopperGeorouter.route([], false, false, false)).toThrow();
expect(() =>
graphhopperGeorouter.route([], {
withDistance: false,
withPoints: false,
withTime: false,
}),
).toThrow();
});
});

View File

@ -26,6 +26,10 @@ const defaultParams: IDefaultParams = {
},
};
const mockGeorouterCreator = {
create: jest.fn().mockImplementation(),
};
describe('Match query', () => {
it('should be defined', () => {
const matchRequest: MatchRequest = new MatchRequest();
@ -40,7 +44,11 @@ describe('Match query', () => {
lon: 3.045432,
},
];
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery).toBeDefined();
});
@ -59,7 +67,11 @@ describe('Match query', () => {
];
matchRequest.identifier = 125;
matchRequest.exclusions = [126, 127, 128];
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.exclusions.length).toBe(4);
});
@ -77,7 +89,11 @@ describe('Match query', () => {
},
];
matchRequest.driver = true;
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.roles).toEqual([Role.DRIVER]);
});
@ -95,7 +111,11 @@ describe('Match query', () => {
},
];
matchRequest.passenger = true;
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.roles).toEqual([Role.PASSENGER]);
});
@ -114,7 +134,11 @@ describe('Match query', () => {
];
matchRequest.passenger = true;
matchRequest.driver = true;
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.roles.length).toBe(2);
expect(matchQuery.roles).toContain(Role.PASSENGER);
expect(matchQuery.roles).toContain(Role.DRIVER);
@ -135,7 +159,11 @@ describe('Match query', () => {
];
matchRequest.seatsDriver = 1;
matchRequest.seatsPassenger = 2;
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.requirement.seatsDriver).toBe(1);
expect(matchQuery.requirement.seatsPassenger).toBe(2);
});
@ -162,7 +190,11 @@ describe('Match query', () => {
matchRequest.remoteness = 20000;
matchRequest.maxDetourDistanceRatio = 0.41;
matchRequest.maxDetourDurationRatio = 0.42;
const matchQuery: MatchQuery = new MatchQuery(matchRequest, defaultParams);
const matchQuery: MatchQuery = new MatchQuery(
matchRequest,
defaultParams,
mockGeorouterCreator,
);
expect(matchQuery.algorithmSettings.algorithm).toBe(Algorithm.CLASSIC);
expect(matchQuery.algorithmSettings.restrict).toBe(
TimingFrequency.FREQUENCY_PUNCTUAL,

View File

@ -15,6 +15,10 @@ const mockMessager = {
publish: jest.fn().mockImplementation(),
};
const mockGeorouterCreator = {
create: jest.fn().mockImplementation(),
};
const defaultParams: IDefaultParams = {
DEFAULT_IDENTIFIER: 0,
MARGIN_DURATION: 900,
@ -77,7 +81,7 @@ describe('MatchUseCase', () => {
];
matchRequest.departure = '2023-04-01 12:23:00';
const matches = await matchUseCase.execute(
new MatchQuery(matchRequest, defaultParams),
new MatchQuery(matchRequest, defaultParams, mockGeorouterCreator),
);
expect(matches.total).toBe(1);
});