Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

# Statistics exchange oracle #20

Merged
merged 12 commits into from
Mar 14, 2024
6 changes: 2 additions & 4 deletions packages/apps/human-app/server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ import { JobsDiscoveryModule } from './modules/jobs-discovery/jobs-discovery.mod
import { JobsDiscoveryController } from './modules/jobs-discovery/jobs-discovery.controller';
import { JobAssignmentController } from './modules/job-assignment/job-assignment.controller';
import { JobAssignmentModule } from './modules/job-assignment/job-assignment.module';
import { CommonUtilModule } from './common/utils/common-util.module';
import { StatisticsModule } from './modules/statistics/statistics.module';
import { StatisticsController } from './modules/statistics/statistics.controller';
import { RequestContext } from './common/utils/request-context.util';
import { ExternalApiModule } from './integrations/external-api/external-api.module';

@Module({
imports: [
CommonUtilModule,
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: true,
Expand All @@ -42,6 +40,7 @@ import { RequestContext } from './common/utils/request-context.util';
JobsDiscoveryModule,
JobAssignmentModule,
ReputationOracleModule,
ExternalApiModule,
CommonConfigModule,
OracleDiscoveryModule,
StatisticsModule,
Expand All @@ -55,7 +54,6 @@ import { RequestContext } from './common/utils/request-context.util';
JobAssignmentController,
StatisticsController,
],
providers: [RequestContext],
exports: [HttpModule],
})
export class AppModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,66 @@ import Joi from 'joi';
import { ConfigService } from '@nestjs/config';
import { Injectable } from '@nestjs/common';

const DEFAULT_PORT = 5010;
const DEFAULT_HOST = 'localhost';
const DEFAULT_REDIS_PORT = 6379;
const DEFAULT_REDIS_HOST = DEFAULT_HOST;
const DEFAULT_REPUTATION_ORACLE_URL = '';
const DEFAULT_CACHE_TTL_ORACLE_STATS = 12 * 60 * 60;
const DEFAULT_CACHE_TTL_USER_STATS = 15 * 60;
const DEFAULT_CACHE_TTL_ORACLE_DISCOVERY = 24 * 60 * 60;
@Injectable()
export class EnvironmentConfigService {

constructor(private configService: ConfigService) {}
get host(): string {
return this.configService.get<string>('HOST', 'localhost');
return this.configService.get<string>('HOST', DEFAULT_HOST);
}
get port(): string {
return this.configService.get<string>('PORT', '5010');
get port(): number {
return this.configService.get<number>('PORT', DEFAULT_PORT);
}
get reputationOracleUrl(): string {
return this.configService.get<string>('REPUTATION_ORACLE_URL', '');
return this.configService.get<string>(
'REPUTATION_ORACLE_URL',
DEFAULT_REPUTATION_ORACLE_URL,
);
}
get cachePort(): number {
return this.configService.get<number>('REDIS_PORT', 6379);
return this.configService.get<number>(
'REDIS_PORT',
DEFAULT_REDIS_PORT,
);
}
get cacheHost(): string {
return this.configService.get<string>('REDIS_HOST', 'localhost');
return this.configService.get<string>(
'REDIS_HOST',
DEFAULT_REDIS_HOST,
);
}
get cacheTtlOracleStats(): number {
return this.configService.get<number>(
'CACHE_TTL_ORACLE_STATS',
12 * 60 * 60,
DEFAULT_CACHE_TTL_ORACLE_STATS,
);
}

get cacheTtlUserStats(): number {
return this.configService.get<number>('CACHE_TTL_USER_STATS', 15 * 60);
return this.configService.get<number>(
'CACHE_TTL_USER_STATS',
DEFAULT_CACHE_TTL_USER_STATS,
);
}

get cacheTtlOracleDiscovery(): number {
return this.configService.get<number>(
'CACHE_TTL_ORACLE_DISCOVERY',
24 * 60 * 60,
DEFAULT_CACHE_TTL_ORACLE_DISCOVERY,
);
}
}

export const envValidator = Joi.object({
HOST: Joi.string().default('localhost'),
PORT: Joi.string().default(5010),
HOST: Joi.string().default(DEFAULT_HOST),
PORT: Joi.number().default(DEFAULT_PORT),
REPUTATION_ORACLE_URL: Joi.string().required(),
});

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { Injectable } from '@nestjs/common';
import {
CamelCaseNamingConvention,
createMap,
Mapper,
namingConventions,
SnakeCaseNamingConvention,
} from '@automapper/core';
import {
JobAssignmentData,
JobAssignmentParams,
JobsFetchParams,
JobsFetchParamsData,
} from '../../modules/job-assignment/interfaces/job-assignment.interface';
import {
JobsDiscoveryParams,
JobsDiscoveryParamsData,
} from '../../modules/jobs-discovery/interfaces/jobs-discovery.interface';

@Injectable()
export class ExternalApiProfile extends AutomapperProfile {
constructor(@InjectMapper() mapper: Mapper) {
super(mapper);
}

override get profile() {
return (mapper: Mapper) => {
createMap(
mapper,
JobAssignmentParams,
JobAssignmentData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
createMap(
mapper,
JobsFetchParams,
JobsFetchParamsData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
createMap(
mapper,
JobsDiscoveryParams,
JobsDiscoveryParamsData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Injectable } from '@nestjs/common';
import { AxiosRequestConfig, AxiosResponse } from 'axios';
import { lastValueFrom } from 'rxjs';
import {
UserStatisticsCommand,
UserStatisticsResponse,
} from '../../modules/statistics/interfaces/user-statistics.interface';
import { HttpService } from '@nestjs/axios';
import {
OracleStatisticsCommand,
OracleStatisticsResponse,
} from '../../modules/statistics/interfaces/oracle-statistics.interface';
import {
JobAssignmentCommand,
JobAssignmentData,
JobAssignmentParams,
JobAssignmentResponse,
JobsFetchParams,
JobsFetchParamsCommand,
JobsFetchParamsData,
JobsFetchResponse,
} from '../../modules/job-assignment/interfaces/job-assignment.interface';
import {
JobsDiscoveryParams,
JobsDiscoveryParamsCommand, JobsDiscoveryParamsData,
JobsDiscoveryResponse,
} from '../../modules/jobs-discovery/interfaces/jobs-discovery.interface';
import { Mapper } from '@automapper/core';
import { InjectMapper } from '@automapper/nestjs';

@Injectable()
export class ExternalApiGateway {
constructor(
private httpService: HttpService,
@InjectMapper() private mapper: Mapper,
) {}
private async callExternalHttpUtilRequest<T>(
options: AxiosRequestConfig,
): Promise<T> {
const response: AxiosResponse<T> = await lastValueFrom(
this.httpService.request(options),
);
return response.data;
}
async fetchUserStatistics(
command: UserStatisticsCommand,
): Promise<UserStatisticsResponse> {
const options: AxiosRequestConfig = {
method: 'GET',
url: `${command.oracleUrl}/stats/assignment`,
headers: {
Authorization: `Bearer ${command.token}`,
},
};
return this.callExternalHttpUtilRequest<UserStatisticsResponse>(options);
}
async fetchOracleStatistics(
command: OracleStatisticsCommand,
): Promise<OracleStatisticsResponse> {
const options: AxiosRequestConfig = {
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
method: 'GET',
url: `${command.oracleUrl}/stats`,
};
return this.callExternalHttpUtilRequest<OracleStatisticsResponse>(options);
}
async fetchAssignedJobs(
command: JobsFetchParamsCommand,
): Promise<JobsFetchResponse> {
const options: AxiosRequestConfig = {
method: 'GET',
url: `${command.exchangeOracleUrl}/assignment`,
params: this.mapper.map(
command.data,
JobsFetchParams,
JobsFetchParamsData,
),
};
return this.callExternalHttpUtilRequest<JobsFetchResponse>(options);
}
async postNewJobAssignment(
command: JobAssignmentCommand,
): Promise<JobAssignmentResponse> {
const options: AxiosRequestConfig = {
method: 'POST',
url: `${command.exchangeOracleUrl}/assignment`,
data: this.mapper.map(
command.data,
JobAssignmentParams,
JobAssignmentData,
),
headers: {
Authorization: `Bearer ${command.token}`,
},
};
return this.callExternalHttpUtilRequest<JobAssignmentResponse>(options);
}
async fetchDiscoveredJobs(command: JobsDiscoveryParamsCommand) {
let options: AxiosRequestConfig = {
method: 'GET',
url: `${command.exchangeOracleUrl}/jobs`,
params: this.mapper.map(
command.data,
JobsDiscoveryParams,
JobsDiscoveryParamsData,
),
headers: {
Authorization: `Bearer ${command.token}`,
},
};
return this.callExternalHttpUtilRequest<JobsDiscoveryResponse>(options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { ExternalApiProfile } from './external-api-profile.service';
import { ExternalApiGateway } from './external-api.gateway';

@Module({
imports: [HttpModule],
providers: [ExternalApiGateway, ExternalApiProfile],
exports: [ExternalApiGateway],
})
export class ExternalApiModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,8 @@ export class ReputationOracleGateway {
private async handleRequestToReputationOracle<T>(
options: AxiosRequestConfig,
): Promise<T> {
try {
const response = await lastValueFrom(this.httpService.request(options));
return response.data;
} catch (error) {
throw error;
}
const response = await lastValueFrom(this.httpService.request(options));
return response.data;
}
async sendWorkerSignup(command: SignupWorkerCommand): Promise<void> {
const signupWorkerData = this.mapper.map(
Expand Down
2 changes: 1 addition & 1 deletion packages/apps/human-app/server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async function bootstrap() {
app.useGlobalFilters(new GlobalExceptionsFilter());

await app.listen(port, host, async () => {
logger.log(`Human APP server is running on http://${host}:${port}`);
logger.log(`Human APP server is running on https://${host}:${port}`);
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
});
}
bootstrap();
Loading
Loading