Skip to content

[FEATURE] Mise à jour d'un script pour remplir les snapshots vides des KE-snapshots (pix-1465) #12034

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/scripts/prod/clean-ke-snapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ function getKnowlegdeElementSnapshotCount() {
return getKnowlegdeElementSnapshotsQuery().count({ count: 1 }).first();
}

UPDATE products
SET details = jsonb_set(details, '{specs,storage}', '"1TB SSD"')
WHERE name = 'Laptop';

// Définition du script
export class CleanKeSnapshotScript extends Script {
constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as url from 'node:url';

import yargs from 'yargs';

import { disconnect, knex } from '../../db/knex-database-connection.js';
import * as knowledgeElementSnapshotRepository from '../../src/prescription/campaign/infrastructure/repositories/knowledge-element-snapshot-repository.js';
import { KnowledgeElementCollection } from '../../src/prescription/shared/domain/models/KnowledgeElementCollection.js';
Expand All @@ -12,39 +10,7 @@ import { PromiseUtils } from '../../src/shared/infrastructure/utils/promise-util
const DEFAULT_MAX_SNAPSHOT_COUNT = 5000;
const DEFAULT_CONCURRENCY = 3;

function _validateAndNormalizeMaxSnapshotCount(maxSnapshotCount) {
if (isNaN(maxSnapshotCount)) {
maxSnapshotCount = DEFAULT_MAX_SNAPSHOT_COUNT;
}
if (maxSnapshotCount <= 0 || maxSnapshotCount > 50000) {
throw new Error(`Nombre max de snapshots ${maxSnapshotCount} ne peut pas être inférieur à 1 ni supérieur à 50000.`);
}

return maxSnapshotCount;
}

function _validateAndNormalizeConcurrency(concurrency) {
if (isNaN(concurrency)) {
concurrency = DEFAULT_CONCURRENCY;
}
if (concurrency <= 0 || concurrency > 10) {
throw new Error(`Concurrent ${concurrency} ne peut pas être inférieur à 1 ni supérieur à 10.`);
}

return concurrency;
}

function _validateAndNormalizeArgs({ concurrency, maxSnapshotCount }) {
const finalMaxSnapshotCount = _validateAndNormalizeMaxSnapshotCount(maxSnapshotCount);
const finalConcurrency = _validateAndNormalizeConcurrency(concurrency);

return {
maxSnapshotCount: finalMaxSnapshotCount,
concurrency: finalConcurrency,
};
}

async function getEligibleCampaignParticipations(maxSnapshotCount) {
async function getEligibleCampaignParticipations(maxSnapshotCount = DEFAULT_MAX_SNAPSHOT_COUNT) {
return knex('campaign-participations')
.select('campaign-participations.id', 'campaign-participations.userId', 'campaign-participations.sharedAt')
.leftJoin(
Expand All @@ -53,16 +19,14 @@ async function getEligibleCampaignParticipations(maxSnapshotCount) {
'campaign-participations.id',
)
.whereNotNull('campaign-participations.sharedAt')
.where((qb) => {
qb.whereNull('knowledge-element-snapshots.campaignParticipationId');
})
.where('knowledge-element-snapshots.snapshot', '{}')
.orderBy('campaign-participations.id')
.limit(maxSnapshotCount);
}

async function generateKnowledgeElementSnapshots(
campaignParticipationData,
concurrency,
concurrency = DEFAULT_CONCURRENCY,
dependencies = { knowledgeElementRepository, knowledgeElementSnapshotRepository },
) {
return PromiseUtils.map(
Expand Down Expand Up @@ -92,23 +56,9 @@ const modulePath = url.fileURLToPath(import.meta.url);
const isLaunchedFromCommandLine = process.argv[1] === modulePath;

async function main() {
const commandLineArgs = yargs
.option('maxSnapshotCount', {
description: 'Nombre de snapshots max. à générer.',
type: 'number',
default: DEFAULT_MAX_SNAPSHOT_COUNT,
})
.option('concurrency', {
description: 'Concurrence',
type: 'number',
default: DEFAULT_CONCURRENCY,
})
.help().argv;
const { maxSnapshotCount, concurrency } = _validateAndNormalizeArgs(commandLineArgs);

const campaignParticipationData = await getEligibleCampaignParticipations(maxSnapshotCount);
const campaignParticipationData = await getEligibleCampaignParticipations();

await generateKnowledgeElementSnapshots(campaignParticipationData, concurrency);
await generateKnowledgeElementSnapshots(campaignParticipationData);
}

(async () => {
Expand All @@ -117,7 +67,6 @@ async function main() {
await main();
} catch (error) {
console.error('\x1b[31mErreur : %s\x1b[0m', error.message);
yargs.showHelp();
process.exitCode = 1;
} finally {
await disconnect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import {
getEligibleCampaignParticipations,
} from '../../../../scripts/prod/generate-knowledge-element-snapshots-for-campaigns.js';
import { KnowledgeElementCollection } from '../../../../src/prescription/shared/domain/models/KnowledgeElementCollection.js';
import { databaseBuilder, domainBuilder, expect, sinon } from '../../../test-helper.js';
import { databaseBuilder, domainBuilder, expect, knex, sinon } from '../../../test-helper.js';

describe('Integration | Scripts | generate-knowledge-element-snapshots-for-campaigns.js', function () {
describe('#getEligibleCampaignParticipations', function () {
const maxParticipationCountToGet = 5;

it('should avoid returning campaign participations that are not shared', async function () {
it('should not return not shared campaign participations', async function () {
// given
const campaignId = databaseBuilder.factory.buildCampaign({ archivedAt: null }).id;
databaseBuilder.factory.buildCampaignParticipation({ campaignId, sharedAt: null });
Expand All @@ -22,7 +22,7 @@ describe('Integration | Scripts | generate-knowledge-element-snapshots-for-campa
expect(campaignParticipationData).to.have.lengthOf(0);
});

it('should avoid returning campaign participations that already have a corresponding snasphot', async function () {
it('should not return campaign participations with a not empty snapshot', async function () {
// given
const campaignId = databaseBuilder.factory.buildCampaign({ archivedAt: null }).id;
const userId = databaseBuilder.factory.buildUser().id;
Expand All @@ -38,12 +38,13 @@ describe('Integration | Scripts | generate-knowledge-element-snapshots-for-campa

// when
const campaignParticipationData = await getEligibleCampaignParticipations(maxParticipationCountToGet);

const knowledgeElementSnapshot = await knex('knowledge-element-snapshots').first();
// then
expect(campaignParticipationData).to.have.lengthOf(0);
expect(knowledgeElementSnapshot.snapshot[0]).to.not.be.empty;
});

it('should return shared campaign participations from active campaigns that does not have a corresponding snapshot', async function () {
it('should return shared campaign participations from active campaigns that have an empty snapshot', async function () {
// given
const campaignId = databaseBuilder.factory.buildCampaign({ archivedAt: null }).id;
const userId = databaseBuilder.factory.buildUser().id;
Expand All @@ -52,78 +53,15 @@ describe('Integration | Scripts | generate-knowledge-element-snapshots-for-campa
sharedAt: new Date('2020-01-01'),
userId,
});
await databaseBuilder.commit();

// when
const campaignParticipationData = await getEligibleCampaignParticipations(maxParticipationCountToGet);

// then
expect(campaignParticipationData).to.have.lengthOf(1);
expect(campaignParticipationData[0]).to.deep.equal({
id: campaignParticipation.id,
userId: campaignParticipation.userId,
sharedAt: campaignParticipation.sharedAt,
});
});

it('should return shared campaign participations from active campaigns even if there is a snapshot from a different date that already exists', async function () {
// given
const userId = databaseBuilder.factory.buildUser().id;
const campaignParticipationWithoutSnapshot = databaseBuilder.factory.buildCampaignParticipation({
sharedAt: new Date('2020-01-01'),
userId,
});

const firstCampaignParticiationId = databaseBuilder.factory.buildCampaignParticipation({
sharedAt: new Date('2020-02-01'),
userId,
}).id;
const secondCampaignParticiationId = databaseBuilder.factory.buildCampaignParticipation({
sharedAt: new Date('2020-03-01'),
userId,
}).id;
databaseBuilder.factory.buildKnowledgeElementSnapshot({
snappedAt: new Date('2020-02-01'),
campaignParticipationId: firstCampaignParticiationId,
});
databaseBuilder.factory.buildKnowledgeElementSnapshot({
snappedAt: new Date('2020-03-01'),
campaignParticipationId: secondCampaignParticiationId,
campaignParticipationId: campaignParticipation.id,
snapshot: {},
});
await databaseBuilder.commit();

// when
const campaignParticipationData = await getEligibleCampaignParticipations(maxParticipationCountToGet);

// then
expect(campaignParticipationData).to.have.lengthOf(1);
expect(campaignParticipationData[0]).to.deep.equal({
id: campaignParticipationWithoutSnapshot.id,
userId: campaignParticipationWithoutSnapshot.userId,
sharedAt: campaignParticipationWithoutSnapshot.sharedAt,
});
});

it('should return maximum campaign participation as set in the parameter', async function () {
// given
const campaignId = databaseBuilder.factory.buildCampaign({ archivedAt: null }).id;
const userId1 = databaseBuilder.factory.buildUser().id;
const userId2 = databaseBuilder.factory.buildUser().id;
const campaignParticipation = databaseBuilder.factory.buildCampaignParticipation({
campaignId,
sharedAt: new Date('2020-01-01'),
userId: userId1,
});
databaseBuilder.factory.buildCampaignParticipation({
campaignId,
sharedAt: new Date('2020-01-01'),
userId: userId2,
});
await databaseBuilder.commit();

// when
const campaignParticipationData = await getEligibleCampaignParticipations(1);

// then
expect(campaignParticipationData).to.have.lengthOf(1);
expect(campaignParticipationData[0]).to.deep.equal({
Expand Down