Skip to content

Commit

Permalink
[BUGFIX] Rafraichir le cache LCMS en asynchrone (pgboss)
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge authored Jul 9, 2024
2 parents 45f2b9b + fcccb95 commit d2ad433
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 45 deletions.
9 changes: 3 additions & 6 deletions api/lib/application/cache/cache-controller.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import _ from 'lodash';

import * as learningContentDatasource from '../../../src/shared/infrastructure/datasources/learning-content/datasource.js';
import { sharedUsecases as usecases } from '../../../src/shared/domain/usecases/index.js';
import * as LearningContentDatasources from '../../../src/shared/infrastructure/datasources/learning-content/index.js';
import { logger } from '../../../src/shared/infrastructure/utils/logger.js';

const refreshCacheEntries = function (_, h, dependencies = { learningContentDatasource }) {
dependencies.learningContentDatasource
.refreshLearningContentCacheRecords()
.catch((e) => logger.error('Error while reloading cache', e));
const refreshCacheEntries = async function (_, h) {
await usecases.refreshLearningContentCache();
return h.response({}).code(202);
};

Expand Down
9 changes: 9 additions & 0 deletions api/lib/infrastructure/jobs/lcms/LcmsRefreshCacheJob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { JobPgBoss } from '../JobPgBoss.js';

class LcmsRefreshCacheJob extends JobPgBoss {
constructor(queryBuilder) {
super({ name: 'LcmsRefreshCacheJob', retryLimit: 0 }, queryBuilder);
}
}

export { LcmsRefreshCacheJob };
18 changes: 18 additions & 0 deletions api/lib/infrastructure/jobs/lcms/LcmsRefreshCacheJobHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { LcmsRefreshCacheJob } from './LcmsRefreshCacheJob.js';

class LcmsRefreshCacheJobHandler {
constructor({ learningContentDatasource, logger }) {
this.logger = logger;
this.learningContentDatasource = learningContentDatasource;
}

async handle() {
await this.learningContentDatasource.refreshLearningContentCacheRecords();
}

get name() {
return LcmsRefreshCacheJob.name;
}
}

export { LcmsRefreshCacheJobHandler };
3 changes: 3 additions & 0 deletions api/src/shared/domain/usecases/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { knex } from '../../../../db/knex-database-connection.js';
import { LcmsRefreshCacheJob } from '../../../../lib/infrastructure/jobs/lcms/LcmsRefreshCacheJob.js';
import * as complementaryCertificationBadgeRepository from '../../../certification/complementary-certification/infrastructure/repositories/complementary-certification-badge-repository.js';
import * as badgeRepository from '../../../evaluation/infrastructure/repositories/badge-repository.js';
import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js';
Expand All @@ -15,6 +17,7 @@ const usecasesWithoutInjectedDependencies = {
const dependencies = {
complementaryCertificationBadgeRepository,
badgeRepository,
lcmsRefreshCacheJob: new LcmsRefreshCacheJob(knex),
};

const sharedUsecases = injectDependencies(usecasesWithoutInjectedDependencies, dependencies);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const refreshLearningContentCache = async function ({ lcmsRefreshCacheJob }) {
await lcmsRefreshCacheJob.schedule();
};
export { refreshLearningContentCache };
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { refreshLearningContentCache } from '../../../../../src/shared/domain/usecases/refresh-learning-content-cache.js';
import { expect, sinon } from '../../../../test-helper.js';

describe('Unit | Domain | Usecases | Refresh Learning Content Cache', function () {
it('should use repository to schedule reefresh job', async function () {
// given
const lcmsRefreshCacheJob = { schedule: sinon.stub() };

// when
await refreshLearningContentCache({ lcmsRefreshCacheJob });

// then
expect(lcmsRefreshCacheJob.schedule).to.have.been.calledOnce;
});
});
43 changes: 4 additions & 39 deletions api/tests/unit/application/cache/cache-controller_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { cacheController } from '../../../../lib/application/cache/cache-controller.js';
import { sharedUsecases as usecases } from '../../../../src/shared/domain/usecases/index.js';
import * as learningContentDatasources from '../../../../src/shared/infrastructure/datasources/learning-content/index.js';
import { logger } from '../../../../src/shared/infrastructure/utils/logger.js';
import { expect, hFake, sinon } from '../../../test-helper.js';

describe('Unit | Controller | cache-controller', function () {
Expand Down Expand Up @@ -79,53 +79,18 @@ describe('Unit | Controller | cache-controller', function () {
});

describe('#refreshCacheEntries', function () {
const request = {};
let learningContentDatasourceStub;

beforeEach(function () {
learningContentDatasourceStub = { refreshLearningContentCacheRecords: sinon.stub() };
});

context('nominal case', function () {
it('should reply with http status 202', async function () {
// given
const numberOfDeletedKeys = 0;
learningContentDatasourceStub.refreshLearningContentCacheRecords.resolves(numberOfDeletedKeys);

// when
const response = await cacheController.refreshCacheEntries(request, hFake, {
learningContentDatasource: learningContentDatasourceStub,
});

// then
expect(learningContentDatasourceStub.refreshLearningContentCacheRecords).to.have.been.calledOnce;
expect(response.statusCode).to.equal(202);
});
});

context('error case', function () {
let response;

beforeEach(async function () {
// given
sinon.stub(logger, 'error');
learningContentDatasourceStub.refreshLearningContentCacheRecords.rejects();
sinon.stub(usecases, 'refreshLearningContentCache').resolves();

// when
response = await cacheController.refreshCacheEntries(request, hFake, {
learningContentDatasource: learningContentDatasourceStub,
});
});
const response = await cacheController.refreshCacheEntries({}, hFake);

it('should reply with http status 202', async function () {
// then
expect(usecases.refreshLearningContentCache).to.have.been.calledOnce;
expect(response.statusCode).to.equal(202);
});

it('should call log errors', async function () {
// then
expect(logger.error).to.have.been.calledOnce;
});
});
});
});
7 changes: 7 additions & 0 deletions api/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { SendSharedParticipationResultsToPoleEmploiHandler } from './lib/infrast
import { SendSharedParticipationResultsToPoleEmploiJob } from './lib/infrastructure/jobs/campaign-result/SendSharedParticipationResultsToPoleEmploiJob.js';
import { scheduleCpfJobs } from './lib/infrastructure/jobs/cpf-export/schedule-cpf-jobs.js';
import { JobQueue } from './lib/infrastructure/jobs/JobQueue.js';
import { LcmsRefreshCacheJob } from './lib/infrastructure/jobs/lcms/LcmsRefreshCacheJob.js';
import { LcmsRefreshCacheJobHandler } from './lib/infrastructure/jobs/lcms/LcmsRefreshCacheJobHandler.js';
import { MonitoredJobQueue } from './lib/infrastructure/jobs/monitoring/MonitoredJobQueue.js';
import { ComputeCertificabilityJob } from './lib/infrastructure/jobs/organization-learner/ComputeCertificabilityJob.js';
import { ComputeCertificabilityJobHandler } from './lib/infrastructure/jobs/organization-learner/ComputeCertificabilityJobHandler.js';
Expand All @@ -27,6 +29,7 @@ import { ImportOrganizationLearnersJob } from './src/prescription/learner-manage
import { ImportOrganizationLearnersJobHandler } from './src/prescription/learner-management/infrastructure/jobs/ImportOrganizationLearnersJobHandler.js';
import { ValidateOrganizationImportFileJob } from './src/prescription/learner-management/infrastructure/jobs/ValidateOrganizationImportFileJob.js';
import { ValidateOrganizationImportFileJobHandler } from './src/prescription/learner-management/infrastructure/jobs/ValidateOrganizationImportFileJobHandler.js';
import * as learningContentDatasource from './src/shared/infrastructure/datasources/learning-content/datasource.js';
import { logger } from './src/shared/infrastructure/utils/logger.js';

async function startPgBoss() {
Expand Down Expand Up @@ -73,6 +76,10 @@ export async function runJobs(dependencies = { startPgBoss, createMonitoredJobQu
const pgBoss = await dependencies.startPgBoss();
const monitoredJobQueue = dependencies.createMonitoredJobQueue(pgBoss);

monitoredJobQueue.performJob(LcmsRefreshCacheJob.name, LcmsRefreshCacheJobHandler, {
learningContentDatasource,
logger,
});
monitoredJobQueue.performJob(
ScheduleComputeOrganizationLearnersCertificabilityJob.name,
ScheduleComputeOrganizationLearnersCertificabilityJobHandler,
Expand Down

0 comments on commit d2ad433

Please sign in to comment.