Skip to content

Commit

Permalink
error logs on PG discussion aggr queries
Browse files Browse the repository at this point in the history
  • Loading branch information
bbohec committed Jul 7, 2023
1 parent 4eaef6b commit 42f837c
Showing 1 changed file with 85 additions and 139 deletions.
224 changes: 85 additions & 139 deletions back/src/adapters/secondary/pg/PgDiscussionAggregateRepository.ts
Original file line number Diff line number Diff line change
@@ -1,132 +1,67 @@
import { PoolClient } from "pg";
import { PoolClient, QueryConfig, QueryResult, QueryResultRow } from "pg";
import format from "pg-format";
import { DiscussionId, SiretDto } from "shared";
import {
DiscussionAggregate,
ExchangeEntity,
} from "../../../domain/immersionOffer/entities/DiscussionAggregate";
import { DiscussionAggregateRepository } from "../../../domain/immersionOffer/ports/DiscussionAggregateRepository";
import { createLogger } from "../../../utils/logger";

const logger = createLogger(__filename);

export class PgDiscussionAggregateRepository
implements DiscussionAggregateRepository
{
constructor(private client: PoolClient) {}

async insert(discussion: DiscussionAggregate) {
await this.client.query(
`INSERT INTO discussions (
id,
contact_mode,
siret,
appellation_code,
potential_beneficiary_first_name,
potential_beneficiary_last_name,
potential_beneficiary_email,
potential_beneficiary_phone,
immersion_objective,
potential_beneficiary_resume_link,
created_at,
establishment_contact_email,
establishment_contact_first_name,
establishment_contact_last_name,
establishment_contact_phone,
establishment_contact_job,
establishment_contact_copy_emails,
street_number_and_address,
postcode,
department_code,
city,
business_name
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22)`,
[
discussion.id,
discussion.establishmentContact.contactMode,
discussion.siret,
discussion.appellationCode,
discussion.potentialBeneficiary.firstName,
discussion.potentialBeneficiary.lastName,
discussion.potentialBeneficiary.email,
discussion.potentialBeneficiary.phone,
discussion.immersionObjective,
discussion.potentialBeneficiary.resumeLink,
discussion.createdAt.toISOString(),
discussion.establishmentContact.email,
discussion.establishmentContact.firstName,
discussion.establishmentContact.lastName,
discussion.establishmentContact.phone,
discussion.establishmentContact.job,
JSON.stringify(discussion.establishmentContact.copyEmails),
discussion.address.streetNumberAndAddress,
discussion.address.postcode,
discussion.address.departmentCode,
discussion.address.city,
discussion.businessName,
],
);

const query = `INSERT INTO discussions (
id, contact_mode, siret, appellation_code, potential_beneficiary_first_name,
potential_beneficiary_last_name, potential_beneficiary_email, potential_beneficiary_phone, immersion_objective, potential_beneficiary_resume_link,
created_at, establishment_contact_email, establishment_contact_first_name, establishment_contact_last_name, establishment_contact_phone,
establishment_contact_job, establishment_contact_copy_emails, street_number_and_address, postcode, department_code,
city, business_name
) VALUES (
$1, $2, $3, $4, $5,
$6, $7, $8, $9, $10,
$11, $12, $13, $14, $15,
$16, $17, $18, $19, $20,
$21, $22
)`;
// prettier-ignore
const values = [ discussion.id, discussion.establishmentContact.contactMode, discussion.siret, discussion.appellationCode, discussion.potentialBeneficiary.firstName, discussion.potentialBeneficiary.lastName, discussion.potentialBeneficiary.email, discussion.potentialBeneficiary.phone, discussion.immersionObjective, discussion.potentialBeneficiary.resumeLink, discussion.createdAt.toISOString(), discussion.establishmentContact.email, discussion.establishmentContact.firstName, discussion.establishmentContact.lastName, discussion.establishmentContact.phone, discussion.establishmentContact.job, JSON.stringify(discussion.establishmentContact.copyEmails), discussion.address.streetNumberAndAddress, discussion.address.postcode, discussion.address.departmentCode, discussion.address.city, discussion.businessName, ];
await this.executeQuery("insert", query, values);
await this.insertAllExchanges(discussion.id, discussion.exchanges);
}

async update(discussion: DiscussionAggregate) {
await this.client.query(
`UPDATE discussions SET
contact_mode = $1,
siret = $2,
appellation_code = $3,
potential_beneficiary_first_name = $4,
potential_beneficiary_last_name = $5,
potential_beneficiary_email = $6,
potential_beneficiary_phone = $7,
immersion_objective = $8,
potential_beneficiary_resume_link = $9,
created_at = $10,
establishment_contact_email = $11,
establishment_contact_first_name = $12,
establishment_contact_last_name = $13,
establishment_contact_phone = $14,
establishment_contact_job = $15,
establishment_contact_copy_emails = $16,
street_number_and_address = $17,
postcode = $18,
department_code = $19,
city = $20,
business_name = $22
WHERE id = $21`,
[
discussion.establishmentContact.contactMode,
discussion.siret,
discussion.appellationCode,
discussion.potentialBeneficiary.firstName,
discussion.potentialBeneficiary.lastName,
discussion.potentialBeneficiary.email,
discussion.potentialBeneficiary.phone,
discussion.immersionObjective,
discussion.potentialBeneficiary.resumeLink,
discussion.createdAt.toISOString(),
discussion.establishmentContact.email,
discussion.establishmentContact.firstName,
discussion.establishmentContact.lastName,
discussion.establishmentContact.phone,
discussion.establishmentContact.job,
JSON.stringify(discussion.establishmentContact.copyEmails),
discussion.address.streetNumberAndAddress,
discussion.address.postcode,
discussion.address.departmentCode,
discussion.address.city,
discussion.id,
discussion.businessName,
],
);

const query = `
UPDATE discussions SET
contact_mode = $1, siret = $2, appellation_code = $3, potential_beneficiary_first_name = $4, potential_beneficiary_last_name = $5,
potential_beneficiary_email = $6, potential_beneficiary_phone = $7, immersion_objective = $8, potential_beneficiary_resume_link = $9, created_at = $10,
establishment_contact_email = $11, establishment_contact_first_name = $12, establishment_contact_last_name = $13, establishment_contact_phone = $14, establishment_contact_job = $15,
establishment_contact_copy_emails = $16, street_number_and_address = $17, postcode = $18, department_code = $19, city = $20,
business_name = $22
WHERE id = $21`;
// prettier-ignore
const values = [
discussion.establishmentContact.contactMode, discussion.siret, discussion.appellationCode, discussion.potentialBeneficiary.firstName, discussion.potentialBeneficiary.lastName,
discussion.potentialBeneficiary.email, discussion.potentialBeneficiary.phone, discussion.immersionObjective, discussion.potentialBeneficiary.resumeLink, discussion.createdAt.toISOString(),
discussion.establishmentContact.email, discussion.establishmentContact.firstName, discussion.establishmentContact.lastName, discussion.establishmentContact.phone, discussion.establishmentContact.job,
JSON.stringify(discussion.establishmentContact.copyEmails), discussion.address.streetNumberAndAddress, discussion.address.postcode, discussion.address.departmentCode, discussion.address.city,
discussion.id,
discussion.businessName,
];
await this.executeQuery("update", query, values);
await this.clearAllExistingExchanges(discussion);
await this.insertAllExchanges(discussion.id, discussion.exchanges);
}

async getById(
discussionId: DiscussionId,
): Promise<DiscussionAggregate | undefined> {
const pgResult = await this.client.query(
`
const query = `
WITH exchanges_by_id AS (
SELECT discussion_id,
ARRAY_AGG(
Expand Down Expand Up @@ -175,61 +110,72 @@ export class PgDiscussionAggregateRepository
FROM discussions
LEFT JOIN exchanges_by_id ON exchanges_by_id.discussion_id = discussions.id
WHERE id = $1
`,
[discussionId],
);
const discussion: DiscussionAggregate = pgResult.rows[0]?.discussion;
if (!discussion) return;
return {
...discussion,
createdAt: new Date(discussion.createdAt),
immersionObjective: discussion.immersionObjective ?? null,
exchanges: discussion.exchanges.map((exchange) => ({
...exchange,
sentAt: new Date(exchange.sentAt),
})),
};
`;
const values = [discussionId];
const pgResult = await this.executeQuery("getById", query, values);
const discussion: DiscussionAggregate = pgResult.rows.at(0)?.discussion;
return discussion
? {
...discussion,
createdAt: new Date(discussion.createdAt),
immersionObjective: discussion.immersionObjective ?? null,
exchanges: discussion.exchanges.map((exchange) => ({
...exchange,
sentAt: new Date(exchange.sentAt),
})),
}
: undefined;
}

async countDiscussionsForSiretSince(
siret: SiretDto,
since: Date,
): Promise<number> {
const pgResult = await this.client.query(
`SELECT COUNT(*)
const query = `SELECT COUNT(*)
FROM discussions
WHERE siret = $1 AND created_at >= $2`,
[siret, since],
WHERE siret = $1 AND created_at >= $2`;
const values = [siret, since];
const pgResult = await this.executeQuery(
"countDiscussionsForSiretSince",
query,
values,
);

return parseInt(pgResult.rows[0].count);
}

private async insertAllExchanges(
discussionId: DiscussionId,
exchanges: ExchangeEntity[],
) {
const sql = format(
`
const query = `
INSERT INTO exchanges (discussion_id, message, sender, recipient, sent_at, subject)
VALUES %L
`,
exchanges.map((exchange) => [
discussionId,
exchange.message,
exchange.sender,
exchange.recipient,
exchange.sentAt.toISOString(),
exchange.subject,
]),
`;
// prettier-ignore
const values = exchanges.map(
({ message, recipient, sender, sentAt, subject }) =>
[ discussionId, message, sender, recipient, sentAt.toISOString(), subject],
);

await this.client.query(sql);
await this.executeQuery("insertAllExchanges", format(query, values));
}

private async clearAllExistingExchanges(discussion: DiscussionAggregate) {
await this.client.query("DELETE FROM exchanges WHERE discussion_id = $1", [
discussion.id,
]);
const query = "DELETE FROM exchanges WHERE discussion_id = $1";
const values = [discussion.id];
await this.executeQuery("clearAllExistingExchanges", query, values);
}

private executeQuery<R extends QueryResultRow = any, I extends any[] = any[]>(
queryName: string,
queryTextOrConfig: string | QueryConfig<I>,
values?: I,
): Promise<QueryResult<R>> {
return this.client.query(queryTextOrConfig, values).catch((error) => {
logger.error(
{ query: queryTextOrConfig, values, error },
`PgDiscussionAggregateRepository_${queryName}_queryErrored`,
);
throw error;
});
}
}

0 comments on commit 42f837c

Please sign in to comment.