Skip to content

Commit

Permalink
[TECH] Appliquer le patch dans PG lorsque la release est patchée (PIX…
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge authored Nov 29, 2024
2 parents ba1f0a8 + 227e80e commit 0bf766c
Show file tree
Hide file tree
Showing 9 changed files with 370 additions and 111 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { sharedUsecases } from '../../shared/domain/usecases/index.js';
import { usecases } from '../domain/usecases/index.js';

const createRelease = async function (request, h) {
Expand All @@ -17,7 +16,7 @@ const patchCacheEntry = async function (request, h) {
const updatedRecord = request.payload;
const recordId = request.params.id;
const modelName = request.params.model;
await sharedUsecases.patchLearningContentCacheEntry({ recordId, updatedRecord, modelName });
await usecases.patchLearningContentCacheEntry({ recordId, updatedRecord, modelName });
return h.response().code(204);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const createLearningContentRelease = withTransaction(
competenceRepository,
thematicRepository,
tubeRepository,
challengeRepository,
skillRepository,
challengeRepository,
courseRepository,
tutorialRepository,
missionRepository,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/** @param {import('./dependencies.js').Dependencies} */
export async function patchLearningContentCacheEntry({
recordId,
updatedRecord,
modelName,
LearningContentCache,
frameworkRepository,
areaRepository,
competenceRepository,
thematicRepository,
tubeRepository,
skillRepository,
challengeRepository,
courseRepository,
tutorialRepository,
missionRepository,
}) {
const currentLearningContent = await LearningContentCache.instance.get();
const patch = generatePatch(currentLearningContent, recordId, updatedRecord, modelName);
await LearningContentCache.instance.patch(patch);
await patchDatabase(
modelName,
updatedRecord,
frameworkRepository,
areaRepository,
competenceRepository,
thematicRepository,
tubeRepository,
skillRepository,
challengeRepository,
courseRepository,
tutorialRepository,
missionRepository,
);
}

function generatePatch(currentLearningContent, id, newEntry, modelName) {
const index = currentLearningContent[modelName].findIndex((element) => element?.id === id);
if (index === -1) {
return {
operation: 'push',
path: modelName,
value: newEntry,
};
}
return {
operation: 'assign',
path: `${modelName}[${index}]`,
value: newEntry,
};
}

async function patchDatabase(
modelName,
patchedRecord,
frameworkRepository,
areaRepository,
competenceRepository,
thematicRepository,
tubeRepository,
skillRepository,
challengeRepository,
courseRepository,
tutorialRepository,
missionRepository,
) {
if (modelName === 'frameworks') {
await frameworkRepository.save([patchedRecord]);
}
if (modelName === 'areas') {
await areaRepository.save([patchedRecord]);
}
if (modelName === 'competences') {
await competenceRepository.save([patchedRecord]);
}
if (modelName === 'thematics') {
await thematicRepository.save([patchedRecord]);
}
if (modelName === 'tubes') {
await tubeRepository.save([patchedRecord]);
}
if (modelName === 'skills') {
await skillRepository.save([patchedRecord]);
}
if (modelName === 'challenges') {
await challengeRepository.save([patchedRecord]);
}
if (modelName === 'courses') {
await courseRepository.save([patchedRecord]);
}
if (modelName === 'tutorials') {
await tutorialRepository.save([patchedRecord]);
}
if (modelName === 'missions') {
await missionRepository.save([patchedRecord]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const refreshLearningContentCache = withTransaction(
competenceRepository,
thematicRepository,
tubeRepository,
challengeRepository,
skillRepository,
challengeRepository,
courseRepository,
tutorialRepository,
missionRepository,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
databaseBuilder,
expect,
generateValidRequestAuthorizationHeader,
knex,
mockLearningContent,
} from '../../../test-helper.js';

Expand Down Expand Up @@ -67,16 +68,21 @@ describe('Acceptance | Controller | lcms-controller', function () {
LearningContentCache.instance = null;
});

it('should store patches in Redis', async function () {
it('should store patches in Redis and patch the DB for an assign operation', async function () {
// given
await mockLearningContent({ frameworks: [{ id: `frameworkId` }] });
await mockLearningContent({
frameworks: [
{ id: 'frameworkId', name: 'old name' },
{ id: 'frameworkId_other', name: 'other name' },
],
});
const superAdminUserId = databaseBuilder.factory.buildUser.withRole({
role: ROLES.SUPER_ADMIN,
}).id;
await databaseBuilder.commit();
const payload = {
id: `frameworkId`,
param: `updated framework`,
id: 'frameworkId',
name: 'new name',
};

// when
Expand All @@ -93,6 +99,50 @@ describe('Acceptance | Controller | lcms-controller', function () {
expect(await redis.lrange('cache:LearningContent:patches', 0, -1)).to.deep.equal([
JSON.stringify({ operation: 'assign', path: `frameworks[0]`, value: payload }),
]);
const frameworksInDB = await knex.select('*').from('learningcontent.frameworks').orderBy('name');
expect(frameworksInDB).to.deep.equal([
{ id: 'frameworkId', name: 'new name' },
{ id: 'frameworkId_other', name: 'other name' },
]);
});

it('should store patches in Redis and patch the DB for a push operation', async function () {
// given
await mockLearningContent({
frameworks: [
{ id: 'frameworkId1', name: 'name 1' },
{ id: 'frameworkId3', name: 'name 3' },
],
});
const superAdminUserId = databaseBuilder.factory.buildUser.withRole({
role: ROLES.SUPER_ADMIN,
}).id;
await databaseBuilder.commit();
const payload = {
id: 'frameworkId2',
name: 'name 2',
};

// when
const response = await server.inject({
method: 'PATCH',
url: `/api/cache/frameworks/frameworkId2`,
headers: { authorization: generateValidRequestAuthorizationHeader(superAdminUserId) },
payload,
});

// then
expect(response.statusCode).to.equal(204);
const redis = new Redis(process.env.TEST_REDIS_URL);
expect(await redis.lrange('cache:LearningContent:patches', 0, -1)).to.deep.equal([
JSON.stringify({ operation: 'push', path: `frameworks`, value: payload }),
]);
const frameworksInDB = await knex.select('*').from('learningcontent.frameworks').orderBy('name');
expect(frameworksInDB).to.deep.equal([
{ id: 'frameworkId1', name: 'name 1' },
{ id: 'frameworkId2', name: 'name 2' },
{ id: 'frameworkId3', name: 'name 3' },
]);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { learningContentController } from '../../../../src/learning-content/application/learning-content-controller.js';
import { usecases } from '../../../../src/learning-content/domain/usecases/index.js';
import { sharedUsecases } from '../../../../src/shared/domain/usecases/index.js';
import { expect, hFake, sinon } from '../../../test-helper.js';

describe('Unit | Controller | learning-content-controller', function () {
describe('Learning Content | Unit | Controller | learning-content-controller', function () {
describe('#createRelease', function () {
it('should schedule createRelease job', async function () {
// given
Expand Down Expand Up @@ -40,13 +39,13 @@ describe('Unit | Controller | learning-content-controller', function () {

it('should call the usecase and return 204', async function () {
// given
sinon.stub(sharedUsecases, 'patchLearningContentCacheEntry');
sinon.stub(usecases, 'patchLearningContentCacheEntry');

// when
const response = await learningContentController.patchCacheEntry(request, hFake);

// then
expect(sharedUsecases.patchLearningContentCacheEntry).to.have.been.calledWithExactly({
expect(usecases.patchLearningContentCacheEntry).to.have.been.calledWithExactly({
recordId: 'recId',
updatedRecord: {
property: 'updatedValue',
Expand Down
Loading

0 comments on commit 0bf766c

Please sign in to comment.