Skip to content

Commit

Permalink
[TECH] Retirer complètement le code lié à l'ancien cache référentiel (P…
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge authored Dec 13, 2024
2 parents c17f912 + 1443659 commit 744b50b
Show file tree
Hide file tree
Showing 92 changed files with 4,326 additions and 7,484 deletions.
83 changes: 65 additions & 18 deletions api/db/seeds/data/common/learningcontent-builder.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,81 @@
import { config } from '../../../../src/shared/config.js';
import { lcmsClient } from '../../../../src/shared/infrastructure/lcms-client.js';
import { logger, SCOPES } from '../../../../src/shared/infrastructure/utils/logger.js';

export async function learningContentBuilder({ databaseBuilder }) {
const learningContent = await lcmsClient.getLatestRelease();

const totalSkillsCount = learningContent.skills.length;
const totalChallengesCount = learningContent.challenges.length;
const totalTutorialsCount = learningContent.tutorials.length;
const totalCounts = Object.entries(learningContent).map(([model, entities]) => [model, entities.length]);

learningContent.skills = learningContent.skills.filter(isActiveOrArchived);
learningContent.frameworks = learningContent.frameworks.filter((framework) =>
config.seeds.learningContent.frameworks.includes(framework.name),
);

learningContent.areas = learningContent.areas.filter(belongsToOneOfFrameworks(learningContent.frameworks));

learningContent.competences = learningContent.competences.filter(belongsToOneOfAreas(learningContent.areas));

learningContent.thematics = learningContent.thematics.filter(belongsToOneOfCompetences(learningContent.competences));

learningContent.tubes = learningContent.tubes.filter(belongsToOneOfThematics(learningContent.thematics));

learningContent.skills = learningContent.skills
.filter(belongsToOneOfTubes(learningContent.tubes))
.filter(isActiveOrArchived);

learningContent.challenges = learningContent.challenges
.filter(belongsToOneOf(learningContent.skills))
.filter(belongsToOneOfSkills(learningContent.skills))
.filter(isValidatedOrArchived)
.filter(hasOneOfLocales(config.seeds.learningContent.locales))
.filter(keepingPrototypeAndOneAlternativeBySkillAndLocale());

learningContent.tutorials = learningContent.tutorials.filter(isUsedByOneOf(learningContent.skills));

logger.debug(
{ event: SCOPES.LEARNING_CONTENT },
`inserting ${learningContent.skills.length} skills out of ${totalSkillsCount}`,
);
logger.debug(
{ event: SCOPES.LEARNING_CONTENT },
`inserting ${learningContent.challenges.length} challenges out of ${totalChallengesCount}`,
);
logger.debug(
{ event: SCOPES.LEARNING_CONTENT },
`inserting ${learningContent.tutorials.length} tutorials out of ${totalTutorialsCount}`,
);
learningContent.courses = learningContent.courses.filter(hasChallengesAvailable(learningContent.challenges));

learningContent.missions = learningContent.missions.filter(belongsToOneOfCompetences(learningContent.competences));

totalCounts.forEach(([model, totalCount]) => {
logger.debug(
{ event: SCOPES.LEARNING_CONTENT },
`inserting ${learningContent[model].length} ${model} out of ${totalCount}`,
);
});

databaseBuilder.factory.learningContent.build(learningContent);
await databaseBuilder.commit();
}

function belongsToOneOfFrameworks(frameworks) {
const frameworkIds = new Set(frameworks.map((framework) => framework.id));
return (area) => frameworkIds.has(area.frameworkId);
}

function belongsToOneOfAreas(areas) {
const areaIds = new Set(areas.map((area) => area.id));
return (competence) => areaIds.has(competence.areaId);
}

function belongsToOneOfCompetences(competences) {
const competenceIds = new Set(competences.map((competence) => competence.id));
return (thematicOrMission) => competenceIds.has(thematicOrMission.competenceId);
}

function belongsToOneOfThematics(thematics) {
const thematicIds = new Set(thematics.map((thematic) => thematic.id));
return (tube) => thematicIds.has(tube.thematicId);
}

function belongsToOneOfTubes(tubes) {
const tubeIds = new Set(tubes.map((tube) => tube.id));
return (skill) => tubeIds.has(skill.tubeId);
}

function isActiveOrArchived(skill) {
return ['actif', 'archivé'].includes(skill.status);
}

function belongsToOneOf(skills) {
function belongsToOneOfSkills(skills) {
const skillIds = new Set(skills.map((skill) => skill.id));
return (challenge) => skillIds.has(challenge.skillId);
}
Expand All @@ -47,6 +84,11 @@ function isValidatedOrArchived(challenge) {
return ['validé', 'archivé'].includes(challenge.status);
}

function hasOneOfLocales(locales) {
const localesSet = new Set(locales);
return (challenge) => challenge.locales.some((locale) => localesSet.has(locale));
}

function keepingPrototypeAndOneAlternativeBySkillAndLocale() {
const alternativesCountBySkillAndLocale = new Map();

Expand All @@ -66,3 +108,8 @@ function isUsedByOneOf(skills) {
const tutorialIds = new Set(skills.flatMap((skill) => [...skill.tutorialIds, skill.learningMoreTutorialIds]));
return (tutorial) => tutorialIds.has(tutorial.id);
}

function hasChallengesAvailable(challenges) {
const challengeIds = new Set(challenges.map((challenge) => challenge.id));
return (course) => course.challenges.every((challengeId) => challengeIds.has(challengeId));
}
59 changes: 9 additions & 50 deletions api/db/seeds/seed.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { config } from '../../src/shared/config.js';
import { logger } from '../../src/shared/infrastructure/utils/logger.js';
import { DatabaseBuilder } from '../database-builder/database-builder.js';
import { commonBuilder } from './data/common/common-builder.js';
Expand All @@ -15,12 +16,8 @@ import { teamDevcompDataBuilder } from './data/team-devcomp/data-builder.js';
import { teamEvaluationDataBuilder } from './data/team-evaluation/data-builder.js';
import { teamPrescriptionDataBuilder } from './data/team-prescription/data-builder.js';

const seed = async function (knex) {
export async function seed(knex) {
logger.info('START Seeding');
const seedsContext = process.env.SEEDS_CONTEXT ? process.env.SEEDS_CONTEXT.split('|') : [];

const hasToSeed = _buildContextToSeed(seedsContext);
logger.info({ seedsContext }, 'Seeds Context');

const databaseBuilder = new DatabaseBuilder({ knex });

Expand All @@ -41,81 +38,43 @@ const seed = async function (knex) {
await organizationBuilder({ databaseBuilder });

// SCOPE
if (hasToSeed.prescription) {
if (config.seeds.context.prescription) {
logger.info('Seeding : Prescription');
await teamPrescriptionDataBuilder({ databaseBuilder });
}

if (hasToSeed.devcomp) {
if (config.seeds.context.devcomp) {
logger.info('Seeding : Devcomp');
await teamDevcompDataBuilder({ databaseBuilder });
}

if (hasToSeed.acces) {
if (config.seeds.context.acces) {
logger.info('Seeding : Acces');
await teamAccesDataBuilder(databaseBuilder);
}

if (hasToSeed.junior) {
if (config.seeds.context.junior) {
logger.info('Seeding : Junior');
await team1dDataBuilder(databaseBuilder);
}

if (hasToSeed.contenu) {
if (config.seeds.context.contenu) {
logger.info('Seeding : Contenu');
await teamContenuDataBuilder({ databaseBuilder });
}

if (hasToSeed.certification) {
if (config.seeds.context.certification) {
logger.info('Seeding : Certification');
await complementaryCertificationBuilder({ databaseBuilder });
await teamCertificationDataBuilder({ databaseBuilder });
}

if (hasToSeed.evaluation) {
if (config.seeds.context.evaluation) {
logger.info('Seeding : Evaluation');
await teamEvaluationDataBuilder({ databaseBuilder });
}

await databaseBuilder.commit();
await databaseBuilder.fixSequences();
logger.info('END Seeding');
};

function _buildContextToSeed(params) {
if (params.length === 0) {
return {
prescription: true,
devcomp: true,
acces: true,
junior: true,
contenu: true,
certification: true,
evaluation: true,
};
}

const hasToSeed = {
prescription: false,
devcomp: false,
acces: false,
junior: false,
contenu: false,
certification: false,
evaluation: false,
};

params.forEach((seedContext) => {
if (seedContext === 'PRESCRIPTION') hasToSeed.prescription = true;
if (seedContext === 'DEVCOMP') hasToSeed.devcomp = true;
if (seedContext === 'JUNIOR') hasToSeed.junior = true;
if (seedContext === 'ACCES') hasToSeed.acces = true;
if (seedContext === 'CONTENU') hasToSeed.contenu = true;
if (seedContext === 'CERTIFICATION') hasToSeed.certification = true;
if (seedContext === 'EVALUATION') hasToSeed.evaluation = true;
});

return hasToSeed;
}

export { seed };
16 changes: 1 addition & 15 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,14 @@ validateEnvironmentVariables();
import { disconnect, prepareDatabaseConnection } from './db/knex-database-connection.js';
import { createServer } from './server.js';
import { config } from './src/shared/config.js';
import { sharedUsecases as usecases } from './src/shared/domain/usecases/index.js';
import { learningContentCache } from './src/shared/infrastructure/caches/learning-content-cache.js';
import { temporaryStorage } from './src/shared/infrastructure/temporary-storage/index.js';
import { logger, SCOPES } from './src/shared/infrastructure/utils/logger.js';
import { logger } from './src/shared/infrastructure/utils/logger.js';
import { redisMonitor } from './src/shared/infrastructure/utils/redis-monitor.js';

let server;

async function _setupEcosystem() {
if (!config.featureToggles.useNewLearningContent) {
/*
Load learning content from Redis to memory cache can take some time
Hence, we force this loading before the server starts so the requests can
immediately be responded.
*/
await usecases.initLearningContentCache();
}
/*
First connection with Knex requires infrastructure operations such as
DNS resolution. So we execute one harmless query to our database
Expand All @@ -33,11 +24,6 @@ async function _setupEcosystem() {
}

const start = async function () {
if (config.featureToggles.useNewLearningContent) {
logger.info({ event: SCOPES.LEARNING_CONTENT }, 'will use new learning content');
} else {
logger.info({ event: SCOPES.LEARNING_CONTENT }, 'will use old learning content');
}
if (config.featureToggles.setupEcosystemBeforeStart) {
await _setupEcosystem();
}
Expand Down
2 changes: 1 addition & 1 deletion api/lib/domain/usecases/get-correction-for-answer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AssessmentNotCompletedError, NotFoundError } from '../../../src/shared/domain/errors.js';
import { LearningContentResourceNotFound } from '../../../src/shared/infrastructure/datasources/learning-content/LearningContentResourceNotFound.js';
import { LearningContentResourceNotFound } from '../../../src/shared/domain/errors.js';

const getCorrectionForAnswer = async function ({
assessmentRepository,
Expand Down
5 changes: 0 additions & 5 deletions api/lib/infrastructure/repositories/framework-repository.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { config } from '../../../src/shared/config.js';
import { NotFoundError } from '../../../src/shared/domain/errors.js';
import { Framework } from '../../../src/shared/domain/models/index.js';
import { LearningContentRepository } from '../../../src/shared/infrastructure/repositories/learning-content-repository.js';
import * as oldFrameworkRepository from './framework-repository_old.js';

const TABLE_NAME = 'learningcontent.frameworks';

export async function list() {
if (!config.featureToggles.useNewLearningContent) return oldFrameworkRepository.list();
const cacheKey = 'list';
const listCallback = (knex) => knex.orderBy('name');
const frameworkDtos = await getInstance().find(cacheKey, listCallback);
return frameworkDtos.map(toDomain);
}

export async function getByName(name) {
if (!config.featureToggles.useNewLearningContent) return oldFrameworkRepository.getByName(name);
const cacheKey = `getByName(${name})`;
const findByNameCallback = (knex) => knex.where('name', name).limit(1);
const [frameworkDto] = await getInstance().find(cacheKey, findByNameCallback);
Expand All @@ -26,7 +22,6 @@ export async function getByName(name) {
}

export async function findByRecordIds(ids) {
if (!config.featureToggles.useNewLearningContent) return oldFrameworkRepository.findByRecordIds(ids);
const frameworkDtos = await getInstance().getMany(ids);
return frameworkDtos
.filter((frameworkDto) => frameworkDto)
Expand Down
35 changes: 0 additions & 35 deletions api/lib/infrastructure/repositories/framework-repository_old.js

This file was deleted.

6 changes: 0 additions & 6 deletions api/lib/infrastructure/repositories/thematic-repository.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
import { config } from '../../../src/shared/config.js';
import { LOCALE } from '../../../src/shared/domain/constants.js';
import { Thematic } from '../../../src/shared/domain/models/Thematic.js';
import { getTranslatedKey } from '../../../src/shared/domain/services/get-translated-text.js';
import { LearningContentRepository } from '../../../src/shared/infrastructure/repositories/learning-content-repository.js';
import * as oldThematicRepository from './thematic-repository_old.js';

const { FRENCH_FRANCE } = LOCALE;
const TABLE_NAME = 'learningcontent.thematics';

export async function list({ locale = FRENCH_FRANCE } = {}) {
if (!config.featureToggles.useNewLearningContent) return oldThematicRepository.list({ locale });
const cacheKey = 'list()';
const listCallback = (knex) => knex.orderBy('id');
const thematicDtos = await getInstance().find(cacheKey, listCallback);
return thematicDtos.map((thematicDto) => toDomain(thematicDto, locale));
}

export async function findByCompetenceIds(competenceIds, locale) {
if (!config.featureToggles.useNewLearningContent)
return oldThematicRepository.findByCompetenceIds(competenceIds, locale);
const cacheKey = `findByCompetenceIds([${competenceIds.sort()}])`;
const findByCompetenceIdsCallback = (knex) => knex.whereIn('competenceId', competenceIds).orderBy('id');
const thematicDtos = await getInstance().find(cacheKey, findByCompetenceIdsCallback);
return thematicDtos.map((thematicDto) => toDomain(thematicDto, locale));
}

export async function findByRecordIds(ids, locale) {
if (!config.featureToggles.useNewLearningContent) return oldThematicRepository.findByRecordIds(ids, locale);
const thematicDtos = await getInstance().getMany(ids);
return thematicDtos
.filter((thematic) => thematic)
Expand Down
Loading

0 comments on commit 744b50b

Please sign in to comment.