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

View File

@ -25,8 +25,8 @@ message MatchRequest {
int32 proportion = 16; int32 proportion = 16;
bool useAzimuth = 17; bool useAzimuth = 17;
int32 azimuthMargin = 18; int32 azimuthMargin = 18;
int32 maxDetourDistanceRatio = 19; float maxDetourDistanceRatio = 19;
int32 maxDetourDurationRatio = 20; float maxDetourDurationRatio = 20;
repeated int32 exclusions = 21; repeated int32 exclusions = 21;
int32 identifier = 22; 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'; import { GraphhopperGeorouter } from './graphhopper-georouter';
export class GeorouterCreator { @Injectable()
create(type: string, url: string): Georouter { export class GeorouterCreator implements ICreateGeorouter {
create(type: string, url: string): IGeorouter {
switch (type) { switch (type) {
case 'graphhopper': case 'graphhopper':
return new GraphhopperGeorouter(url); return new GraphhopperGeorouter(url);

View File

@ -1,19 +1,15 @@
import { Route } from '../../domain/entities/route'; 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; _url: string;
constructor(url: string) { constructor(url: string) {
this._url = url + '/route?'; this._url = url + '/route?';
} }
route( route(routesRequested: [], settings: GeorouterSettings): Route[] {
routesRequested: [],
withPoints: boolean,
withTime: boolean,
withDistance: boolean,
): Route[] {
throw new Error('Method not implemented.'); 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 { DefaultAlgorithmSettings } from '../types/default-algorithm-settings.type';
import { Algorithm } from '../types/algorithm.enum'; import { Algorithm } from '../types/algorithm.enum';
import { TimingFrequency } from '../types/timing'; import { TimingFrequency } from '../types/timing';
import { ICreateGeorouter } from '../interfaces/georouter-creator.interface';
import { IGeorouter } from '../interfaces/georouter.interface';
export class AlgorithmSettings { export class AlgorithmSettings {
_algorithmSettingsRequest: IRequestAlgorithmSettings; _algorithmSettingsRequest: IRequestAlgorithmSettings;
@ -15,13 +17,13 @@ export class AlgorithmSettings {
azimuthMargin: number; azimuthMargin: number;
maxDetourDurationRatio: number; maxDetourDurationRatio: number;
maxDetourDistanceRatio: number; maxDetourDistanceRatio: number;
georouterType: string; georouter: IGeorouter;
georouterUrl: string;
constructor( constructor(
algorithmSettingsRequest: IRequestAlgorithmSettings, algorithmSettingsRequest: IRequestAlgorithmSettings,
defaultAlgorithmSettings: DefaultAlgorithmSettings, defaultAlgorithmSettings: DefaultAlgorithmSettings,
frequency: TimingFrequency, frequency: TimingFrequency,
georouterCreator: ICreateGeorouter,
) { ) {
this._algorithmSettingsRequest = algorithmSettingsRequest; this._algorithmSettingsRequest = algorithmSettingsRequest;
this.algorithm = this.algorithm =
@ -49,8 +51,10 @@ export class AlgorithmSettings {
this.maxDetourDurationRatio = this.maxDetourDurationRatio =
algorithmSettingsRequest.maxDetourDurationRatio ?? algorithmSettingsRequest.maxDetourDurationRatio ??
defaultAlgorithmSettings.maxDetourDurationRatio; defaultAlgorithmSettings.maxDetourDurationRatio;
this.georouterType = defaultAlgorithmSettings.georouterType; this.georouter = georouterCreator.create(
this.georouterUrl = defaultAlgorithmSettings.georouterUrl; defaultAlgorithmSettings.georouterType,
defaultAlgorithmSettings.georouterUrl,
);
if (this._strict) { if (this._strict) {
this.restrict = frequency; 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 { Route } from '../entities/route';
import { GeorouterSettings } from '../types/georouter-settings.type';
export interface Georouter { export interface IGeorouter {
route( route(routesRequested: [], settings: GeorouterSettings): Array<Route>;
routesRequested: [],
withPoints: boolean,
withTime: boolean,
withDistance: boolean,
): 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 { RedisClientOptions } from '@liaoliaots/nestjs-redis';
import { redisStore } from 'cache-manager-ioredis-yet'; import { redisStore } from 'cache-manager-ioredis-yet';
import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider'; import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider';
import { GeorouterCreator } from './adapters/secondaries/georouter-creator';
@Module({ @Module({
imports: [ imports: [
@ -51,6 +52,7 @@ import { DefaultParamsProvider } from './adapters/secondaries/default-params.pro
Messager, Messager,
DefaultParamsProvider, DefaultParamsProvider,
MatchUseCase, MatchUseCase,
GeorouterCreator,
], ],
exports: [], exports: [],
}) })

View File

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

View File

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

View File

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