Skip to content

Commit

Permalink
Merge pull request #493 from MTES-MCT/fix/group-creation-slowness
Browse files Browse the repository at this point in the history
Speed up the creation of groups
  • Loading branch information
Falinor authored Nov 27, 2023
2 parents 03cc866 + 0cdaf99 commit effde8f
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ function GroupAddHousingModal(props: Props) {
};

const [title, setTitle] = useState('');
const [buttonsDisabled, setButtonsDisabled] = useState(false);
const [description, setDescription] = useState('');

const shape = {
Expand All @@ -89,18 +90,21 @@ function GroupAddHousingModal(props: Props) {
children: 'Annuler',
priority: 'secondary',
className: 'fr-mr-2w',
disabled: buttonsDisabled,
},
{
children: 'Confirmer',
doClosesModal: false,
onClick: async () => {
await form.validate(() => {
setButtonsDisabled(true);
props.onGroupCreate({
title,
description,
});
});
},
disabled: buttonsDisabled,
},
],
};
Expand Down
4 changes: 3 additions & 1 deletion server/controllers/campaignController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { User1 } from '../../database/seeds/test/003-users';
import { formatOwnerApi, Owners } from '../repositories/ownerRepository';
import { formatOwnerHousingApi, HousingOwners } from '../repositories/housingOwnerRepository';
import { isDefined } from '../../shared';
import { wait } from '@hapi/hoek';

const { app } = createServer();

Expand Down Expand Up @@ -104,7 +105,7 @@ describe('Campaign controller', () => {
housingIds: [Housing1.id, Housing2.id],
allHousing: false,
})
.expect(constants.HTTP_STATUS_OK);
.expect(constants.HTTP_STATUS_CREATED);

expect(res.body).toMatchObject(
expect.objectContaining({
Expand Down Expand Up @@ -241,6 +242,7 @@ describe('Campaign controller', () => {
);

expect(status).toBe(constants.HTTP_STATUS_CREATED);
await wait(1000);
const housingIds = groupHousing.map((housing) => housing.id);
const housingEvents = await HousingEvents().whereIn(
'housing_id',
Expand Down
85 changes: 46 additions & 39 deletions server/controllers/campaignController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
import { isArrayOf, isString, isUUID, isUUIDParam } from '../utils/validators';
import sortApi from '../models/SortApi';
import CampaignMissingError from '../errors/campaignMissingError';
import { HousingEventApi } from '../models/EventApi';

const getCampaignValidators = [param('id').notEmpty().isUUID()];

Expand Down Expand Up @@ -94,7 +95,7 @@ const createCampaignValidators: ValidationChain[] = [
const createCampaign = async (
request: Request,
response: Response
): Promise<Response> => {
): Promise<void> => {
logger.info('Create campaign');

const { establishmentId, userId } = (request as AuthenticatedRequest).auth;
Expand Down Expand Up @@ -157,25 +158,28 @@ const createCampaign = async (
},
});

await eventRepository.insertManyHousingEvents(
housingList.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans une campagne',
kind: 'Create',
category: 'Campaign',
section: 'Suivi de campagne',
old: housingList.find((_) => _.id === housing.id),
new: newHousingList
.map((housing) => ({ ...housing, campaignIds: [newCampaignApi.id] }))
.find((_) => _.id === housing.id),
createdBy: userId,
createdAt: new Date(),
housingId: housing.id,
housingGeoCode: housing.geoCode,
}))
);
response.status(constants.HTTP_STATUS_CREATED).json(newCampaignApi);

return response.status(constants.HTTP_STATUS_OK).json(newCampaignApi);
const events: HousingEventApi[] = housingList.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans une campagne',
kind: 'Create',
category: 'Campaign',
section: 'Suivi de campagne',
old: housingList.find((_) => _.id === housing.id),
new: newHousingList
.map((housing) => ({ ...housing, campaignIds: [newCampaignApi.id] }))
.find((_) => _.id === housing.id),
createdBy: userId,
createdAt: new Date(),
housingId: housing.id,
housingGeoCode: housing.geoCode,
}));
eventRepository
.insertManyHousingEvents(events)
.catch((error) =>
logger.error('Error while inserting housing events', error)
);
};

const createCampaignFromGroup = async (
Expand Down Expand Up @@ -217,29 +221,32 @@ const createCampaignFromGroup = async (
});
await campaignHousingRepository.insertHousingList(campaign.id, housingList);

await eventRepository.insertManyHousingEvents(
housingList.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans une campagne',
kind: 'Create',
category: 'Campaign',
section: 'Suivi de campagne',
old: housing,
new: {
...housing,
campaignIds: [...housing.campaignIds, campaign.id],
},
createdBy: auth.userId,
createdAt: new Date(),
housingId: housing.id,
housingGeoCode: housing.geoCode,
}))
);

response.status(constants.HTTP_STATUS_CREATED).json(campaign);

const events: HousingEventApi[] = housingList.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans une campagne',
kind: 'Create',
category: 'Campaign',
section: 'Suivi de campagne',
old: housing,
new: {
...housing,
campaignIds: [...housing.campaignIds, campaign.id],
},
createdBy: auth.userId,
createdAt: new Date(),
housingId: housing.id,
housingGeoCode: housing.geoCode,
}));
eventRepository
.insertManyHousingEvents(events)
.catch((error) =>
logger.error('Error while inserting housing events', error)
);
};
const createCampaignFromGroupValidators: ValidationChain[] = [
param('id').isString().isUUID().notEmpty(),
param('id').isUUID().notEmpty(),
body('title').isString().notEmpty(),
];

Expand Down
6 changes: 5 additions & 1 deletion server/controllers/groupController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
HousingOwnerDBO,
HousingOwners,
} from '../repositories/housingOwnerRepository';
import { wait } from '@hapi/hoek';

describe('Group controller', () => {
const { app } = createServer();
Expand Down Expand Up @@ -238,8 +239,8 @@ describe('Group controller', () => {
'Content-Type': 'application/json',
})
);

expect(status).toBe(constants.HTTP_STATUS_CREATED);
await wait(1000);
const establishmentHousingList = housingList.filter((housing) =>
Establishment1.geoCodes.includes(housing.geoCode)
);
Expand Down Expand Up @@ -472,6 +473,7 @@ describe('Group controller', () => {
);

expect(status).toBe(constants.HTTP_STATUS_OK);
await wait(1000);
const events = await Events()
.join(
groupHousingEventsTable,
Expand Down Expand Up @@ -596,6 +598,7 @@ describe('Group controller', () => {
);

expect(status).toBe(constants.HTTP_STATUS_OK);
await wait(1000);
const events = await Events()
.join(
groupHousingEventsTable,
Expand Down Expand Up @@ -684,6 +687,7 @@ describe('Group controller', () => {
);

expect(status).toBe(constants.HTTP_STATUS_OK);
await wait(1000);
const after = await GroupHousingEvents()
.whereNull('group_id')
.join(
Expand Down
114 changes: 67 additions & 47 deletions server/controllers/groupController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,23 @@ const create = async (request: Request, response: Response): Promise<void> => {
const { body, establishment, user } = request as AuthenticatedRequest;

// Keep the housing list that are in the same establishment as the group
const housingList = await housingRepository
.find({
filters: {
...body.housing.filters,
establishmentIds: [establishment.id],
},
pagination: { paginate: false },
})
.then((housingList) => {
const ids = new Set(body.housing.ids);
return housingList.filter((housing) =>
body.housing.all ? !ids.has(housing.id) : ids.has(housing.id)
);
});
const housingList =
body.housing.all !== undefined
? await housingRepository
.find({
filters: {
...body.housing.filters,
establishmentIds: [establishment.id],
},
pagination: { paginate: false },
})
.then((housingList) => {
const ids = new Set(body.housing.ids);
return housingList.filter((housing) =>
body.housing.all ? !ids.has(housing.id) : ids.has(housing.id)
);
})
: [];
const owners = housingList.map((housing) => housing.owner);

const group: GroupApi = {
Expand All @@ -65,27 +68,33 @@ const create = async (request: Request, response: Response): Promise<void> => {
establishmentId: establishment.id,
archivedAt: null,
};
await groupRepository.save(group, housingList);

const events: GroupHousingEventApi[] = housingList.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans un groupe',
kind: 'Create',
category: 'Group',
section: 'Ajout d’un logement dans un groupe',
conflict: false,
old: undefined,
new: group,
createdAt: new Date(),
createdBy: user.id,
groupId: group.id,
housingId: housing.id,
housingGeoCode: housing.geoCode,
}));
await eventRepository.insertManyGroupHousingEvents(events);
await groupRepository.save(group, housingList);

response.status(constants.HTTP_STATUS_CREATED).json(toGroupDTO(group));

const events: GroupHousingEventApi[] = housingList.map(
(housing): GroupHousingEventApi => ({
id: uuidv4(),
name: 'Ajout dans un groupe',
kind: 'Create',
category: 'Group',
section: 'Ajout d’un logement dans un groupe',
conflict: false,
old: undefined,
new: group,
createdAt: new Date(),
createdBy: user.id,
groupId: group.id,
housingId: housing.id,
housingGeoCode: housing.geoCode,
})
);
eventRepository.insertManyGroupHousingEvents(events).catch((error) => {
logger.error(error);
});
};

const createValidators: ValidationChain[] = [
body('title').isString().notEmpty(),
body('description').isString().notEmpty(),
Expand Down Expand Up @@ -197,6 +206,13 @@ const addHousing = async (

await groupRepository.addHousing(group, diff);

const updatedGroup: GroupApi = {
...group,
housingCount: uniqueHousingList.length,
ownerCount: uniqueOwners.length,
};
response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(updatedGroup));

const events: GroupHousingEventApi[] = diff.map((housing) => ({
id: uuidv4(),
name: 'Ajout dans un groupe',
Expand All @@ -212,14 +228,9 @@ const addHousing = async (
housingId: housing.id,
housingGeoCode: housing.geoCode,
}));
await eventRepository.insertManyGroupHousingEvents(events);

const updatedGroup: GroupApi = {
...group,
housingCount: uniqueHousingList.length,
ownerCount: uniqueOwners.length,
};
response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(updatedGroup));
eventRepository.insertManyGroupHousingEvents(events).catch((error) => {
logger.error(error);
});
};
const addHousingValidators: ValidationChain[] = [
isUUIDParam('id'),
Expand Down Expand Up @@ -278,6 +289,8 @@ const removeHousing = async (request: Request, response: Response) => {
};
await groupRepository.removeHousing(updatedGroup, removingHousingList);

response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(updatedGroup));

const events: GroupHousingEventApi[] = removingHousingList.map((housing) => ({
id: uuidv4(),
name: 'Retrait d’un groupe',
Expand All @@ -293,9 +306,9 @@ const removeHousing = async (request: Request, response: Response) => {
housingId: housing.id,
housingGeoCode: housing.geoCode,
}));
await eventRepository.insertManyGroupHousingEvents(events);

response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(updatedGroup));
eventRepository.insertManyGroupHousingEvents(events).catch((error) => {
logger.error(error);
});
};
const removeHousingValidators: ValidationChain[] = addHousingValidators;

Expand Down Expand Up @@ -328,6 +341,9 @@ const remove = async (request: Request, response: Response): Promise<void> => {

if (campaigns.length > 0) {
const archived = await groupRepository.archive(group);

response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(archived));

const events = housingList.map<GroupHousingEventApi>((housing) => ({
id: uuidv4(),
name: 'Archivage d’un groupe',
Expand All @@ -343,11 +359,15 @@ const remove = async (request: Request, response: Response): Promise<void> => {
housingGeoCode: housing.geoCode,
groupId: null,
}));
await eventRepository.insertManyGroupHousingEvents(events);
response.status(constants.HTTP_STATUS_OK).json(toGroupDTO(archived));
eventRepository.insertManyGroupHousingEvents(events).catch((error) => {
logger.error(error);
});
return;
}

await groupRepository.remove(group);
response.status(constants.HTTP_STATUS_NO_CONTENT).send();

const events = housingList.map<GroupHousingEventApi>((housing) => ({
id: uuidv4(),
name: 'Suppression d’un groupe',
Expand All @@ -363,9 +383,9 @@ const remove = async (request: Request, response: Response): Promise<void> => {
housingGeoCode: housing.geoCode,
groupId: null,
}));
await groupRepository.remove(group);
await eventRepository.insertManyGroupHousingEvents(events);
response.status(constants.HTTP_STATUS_NO_CONTENT).send();
eventRepository.insertManyGroupHousingEvents(events).catch((error) => {
logger.error(error);
});
};
const removeValidators: ValidationChain[] = [param('id').isString().notEmpty()];

Expand Down
Loading

0 comments on commit effde8f

Please sign in to comment.