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

feat: added get job by job parameters support #32

Merged
merged 9 commits into from
Nov 22, 2023
26 changes: 26 additions & 0 deletions openapi3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,23 @@ paths:
$ref: '#/components/schemas/errorMessage'
tags:
- jobs
/jobs/parameters:
get:
asafMasa marked this conversation as resolved.
Show resolved Hide resolved
operationId: getJobByJobsParameters
parameters:
- $ref: '#/components/parameters/parameters'
summary: find jobs by job job's parameters, temporary only 1 level nested object is supported.
tags:
- jobs
responses:
'200':
description: Array of jobs
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/jobResponse'
/jobs/{jobId}/resettable:
parameters:
- $ref: '#/components/parameters/jobId'
Expand Down Expand Up @@ -550,6 +567,15 @@ components:
required: false
schema:
type: string
parameters:
in: query
name: parameters
description: |
Job's parameters
Query jsonb parameters
schema:
type: object
additionalProperties: true
isCleaned:
in: query
name: isCleaned
Expand Down
3 changes: 3 additions & 0 deletions src/DAL/migration/v3.0.0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CREATE INDEX "jobParametersIndex"
ON "JobManager"."Job" USING btree
(parameters ASC NULLS LAST);
asafMasa marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 21 additions & 1 deletion src/DAL/repositories/jobRepository.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { EntityRepository, FindManyOptions, LessThan, Brackets, Between, LessThanOrEqual, MoreThanOrEqual } from 'typeorm';
import { EntityRepository, FindManyOptions, LessThan, Brackets, Between, LessThanOrEqual, MoreThanOrEqual, Raw } from 'typeorm';
import { container } from 'tsyringe';
import { Logger } from '@map-colonies/js-logger';
import { ConflictError, NotFoundError } from '@map-colonies/error-types';
import { DBConstraintError } from '../../common/errors';
import { SERVICES } from '../../common/constants';
import { JobEntity } from '../entity/job';
import { paramsQueryBuilder } from '../../common/utils';
import {
FindJobsResponse,
ICreateJobBody,
Expand All @@ -18,6 +19,8 @@ import { JobModelConvertor } from '../convertors/jobModelConverter';
import { OperationStatus } from '../../common/dataModels/enums';
import { GeneralRepository } from './generalRepository';

export type JobParameters = Record<string, unknown>;

@EntityRepository(JobEntity)
export class JobRepository extends GeneralRepository<JobEntity> {
private readonly appLogger: Logger; //don't override internal repository logger.
Expand Down Expand Up @@ -66,6 +69,23 @@ export class JobRepository extends GeneralRepository<JobEntity> {
return models;
}

public async getJobByJobParameters(parameters: JobParameters): Promise<FindJobsResponse> {
this.appLogger.info({ parameters }, 'Getting jobs by jobs parameters');
try {
const entities = await this.createQueryBuilder()
.select('job')
.from(JobEntity, 'job')
.where({ parameters: Raw(() => paramsQueryBuilder(parameters), parameters) })
.getMany();

const models = entities.map((entity) => this.jobConvertor.entityToModel(entity));
return models;
} catch (error) {
this.appLogger.error({ parameters, msg: `Failed to get jobs by jobs parameters, error: ${(error as Error).message}` });
throw error;
}
}

public async createJob(req: ICreateJobBody): Promise<ICreateJobResponse> {
this.appLogger.info({ resourceId: req.resourceId, version: req.version, type: req.type, msg: 'Start job creation ' });
try {
Expand Down
15 changes: 15 additions & 0 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const paramsQueryBuilder = (params: Record<string, unknown>): string => {
const queryStringArray: string[] = [];
asafMasa marked this conversation as resolved.
Show resolved Hide resolved
const paramKeys = Object.keys(params);
let fullQuery = '';

paramKeys.forEach((key) => {
const query = `(job.parameters->>'${key}') = :${key}`;
queryStringArray.push(query);
});

if (queryStringArray.length > 0) {
fullQuery = queryStringArray.join(' AND ');
}
return fullQuery;
};
11 changes: 11 additions & 0 deletions src/jobs/controllers/jobController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import {
} from '../../common/dataModels/jobs';
import { DefaultResponse } from '../../common/interfaces';
import { JobManager } from '../models/jobManager';
import { JobParameters } from '../../DAL/repositories/jobRepository';

type CreateResourceHandler = RequestHandler<undefined, ICreateJobResponse, ICreateJobBody>;
type FindResourceHandler = RequestHandler<undefined, FindJobsResponse, undefined, IFindJobsRequest>;
type GetJobsByJobsParametersHandler = RequestHandler<undefined, FindJobsResponse, undefined, JobParameters>;
type GetResourceHandler = RequestHandler<IJobsParams, IGetJobResponse, undefined, IJobsQuery>;
type DeleteResourceHandler = RequestHandler<IJobsParams, DefaultResponse>;
type UpdateResourceHandler = RequestHandler<IJobsParams, DefaultResponse, IUpdateJobBody>;
Expand Down Expand Up @@ -48,6 +50,15 @@ export class JobController {
}
};

public getJobByJobsParameters: GetJobsByJobsParametersHandler = async (req, res, next) => {
asafMasa marked this conversation as resolved.
Show resolved Hide resolved
try {
const jobsRes = await this.manager.getJobsByJobsParameters(req.query);
return res.status(httpStatus.OK).json(jobsRes);
} catch (err) {
return next(err);
}
};

public getResource: GetResourceHandler = async (req, res, next) => {
try {
const job = await this.manager.getJob(req.params, req.query);
Expand Down
9 changes: 8 additions & 1 deletion src/jobs/models/jobManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
IResetJobRequest,
IAvailableActions,
} from '../../common/dataModels/jobs';
import { JobRepository } from '../../DAL/repositories/jobRepository';
import { JobParameters, JobRepository } from '../../DAL/repositories/jobRepository';
import { TransactionActions } from '../../DAL/repositories/transactionActions';
import { OperationStatus } from '../../common/dataModels/enums';

Expand All @@ -32,6 +32,7 @@ export class JobManager {

public async findJobs(req: IFindJobsRequest): Promise<FindJobsResponse> {
const repo = await this.getRepository();

let res = await repo.findJobs(req);

if (req.shouldReturnAvailableActions === true) {
Expand All @@ -47,6 +48,12 @@ export class JobManager {
return res;
}

public async getJobsByJobsParameters(req: JobParameters): Promise<FindJobsResponse> {
const repo = await this.getRepository();
const res = await repo.getJobByJobParameters(req);
return res;
}

public async createJob(req: ICreateJobBody): Promise<ICreateJobResponse> {
this.logger.debug(req, 'Create-job parameters');
const repo = await this.getRepository();
Expand Down
1 change: 1 addition & 0 deletions src/jobs/routes/jobRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const jobRouterFactory: FactoryFunction<Router> = (dependencyContainer) => {

router.get('/', jobsController.findResource);
router.post('/', jobsController.createResource);
router.get('/parameters', jobsController.getJobByJobsParameters);
router.get('/:jobId', jobsController.getResource);
router.put('/:jobId', jobsController.updateResource);
router.delete('/:jobId', jobsController.deleteResource);
Expand Down
2 changes: 1 addition & 1 deletion tests/configurations/integration/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = {
branches: 60,
functions: 80,
lines: 80,
statements: 85,
statements: 83,
},
},
};
Loading