Skip to content

Commit

Permalink
Merge pull request #1729 from filipedeschamps/refactor/database-commu…
Browse files Browse the repository at this point in the history
…nication-contents

Diminui idas ao banco de dados na criação e edição de conteúdos, e na edição de usuários
  • Loading branch information
aprendendofelipe committed Jun 25, 2024
2 parents 1eec26d + 583e89a commit c781819
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 120 deletions.
102 changes: 47 additions & 55 deletions models/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,20 +273,14 @@ async function create(postedContent, options = {}) {

checkRootContentTitle(validContent);

const parentContent = validContent.parent_id
? await checkIfParentIdExists(validContent, {
transaction: options.transaction,
})
: null;

injectIdAndPath(validContent, parentContent);

populatePublishedAtValue(null, validContent);

const newContent = await runInsertQuery(validContent, {
transaction: options.transaction,
});

throwIfSpecifiedParentDoesNotExist(postedContent, newContent);

await creditOrDebitTabCoins(null, newContent, {
eventId: options.eventId,
transaction: options.transaction,
Expand All @@ -310,10 +304,22 @@ async function create(postedContent, options = {}) {
const query = {
text: `
WITH
parent AS (
SELECT
owner_id,
CASE
WHEN id IS NULL THEN ARRAY[]::uuid[]
ELSE ARRAY_APPEND(path, id)
END AS child_path
FROM (SELECT 1) AS dummy
LEFT JOIN contents
ON id = $2
),
inserted_content as (
INSERT INTO
contents (id, parent_id, owner_id, slug, title, body, status, source_url, published_at, path)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, parent.child_path
FROM parent
RETURNING *
)
SELECT
Expand All @@ -330,11 +336,14 @@ async function create(postedContent, options = {}) {
inserted_content.published_at,
inserted_content.deleted_at,
inserted_content.path,
users.username as owner_username
users.username as owner_username,
parent.owner_id as parent_owner_id
FROM
inserted_content
INNER JOIN
users ON inserted_content.owner_id = users.id
LEFT JOIN
parent ON true
;`,
values: [
content.id,
Expand All @@ -346,7 +355,6 @@ async function create(postedContent, options = {}) {
content.status,
content.source_url,
content.published_at,
content.path,
],
};

Expand All @@ -359,18 +367,6 @@ async function create(postedContent, options = {}) {
}
}

function injectIdAndPath(validContent, parentContent) {
validContent.id = uuidV4();

if (parentContent) {
validContent.path = [...parentContent.path, parentContent.id];
}

if (!parentContent) {
validContent.path = [];
}
}

function populateSlug(postedContent) {
if (!postedContent.slug) {
postedContent.slug = getSlug(postedContent.title) || uuidV4();
Expand Down Expand Up @@ -405,17 +401,10 @@ function populateStatus(postedContent) {
postedContent.status = postedContent.status || 'draft';
}

async function checkIfParentIdExists(content, options) {
const existingContent = await findOne(
{
where: {
id: content.parent_id,
},
},
options,
);
function throwIfSpecifiedParentDoesNotExist(postedContent, newContent) {
const existingParentId = newContent.path.at(-1);

if (!existingContent) {
if (postedContent.parent_id && postedContent.parent_id !== existingParentId) {
throw new ValidationError({
message: `Você está tentando criar um comentário em um conteúdo que não existe.`,
action: `Utilize um "parent_id" que aponte para um conteúdo existente.`,
Expand All @@ -425,8 +414,6 @@ async function checkIfParentIdExists(content, options) {
key: 'parent_id',
});
}

return existingContent;
}

function parseQueryErrorToCustomError(error) {
Expand All @@ -446,6 +433,7 @@ function parseQueryErrorToCustomError(error) {

function validateCreateSchema(content) {
const cleanValues = validator(content, {
id: 'required',
parent_id: 'optional',
owner_id: 'required',
slug: 'required',
Expand Down Expand Up @@ -558,23 +546,25 @@ async function creditOrDebitTabCoins(oldContent, newContent, options = {}) {
});
}

// We should not credit if the content has little or no value.
if (newContent.body.split(/[a-z]{5,}/i, 6).length < 6) return;

if (newContent.parent_id) {
const parentContent = await findOne(
{
where: {
id: newContent.parent_id,
},
},
options,
);
let parentOwnerId = newContent.parent_owner_id;

if (parentOwnerId === undefined) {
const queryParent = {
text: `SELECT owner_id FROM contents WHERE id = $1;`,
values: [newContent.parent_id],
};
const parentQueryResult = await database.query(queryParent, options);
const parentContent = parentQueryResult.rows[0];
parentOwnerId = parentContent.owner_id;
}

// We should not credit if the parent content is from the same user.
if (parentContent.owner_id === newContent.owner_id) return;
if (parentOwnerId === newContent.owner_id) return;
}

// We should not credit if the content has little or no value.
// Expected 5 or more words with 5 or more characters.
if (newContent.body.split(/[a-z]{5,}/i, 6).length < 6) return;
}

if (userEarnings > 0) {
Expand Down Expand Up @@ -611,14 +601,16 @@ async function creditOrDebitTabCoins(oldContent, newContent, options = {}) {
async function update(contentId, postedContent, options = {}) {
const validPostedContent = validateUpdateSchema(postedContent);

const oldContent = await findOne(
{
where: {
id: contentId,
const oldContent =
options.oldContent ??
(await findOne(
{
where: {
id: contentId,
},
},
},
options,
);
options,
));

const newContent = { ...oldContent, ...validPostedContent };

Expand Down
22 changes: 0 additions & 22 deletions models/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,6 @@ async function create(object, options = {}) {
return results.rows[0];
}

// Currently it only update "metadata" column.
async function updateMetadata(eventId, object, options = {}) {
object = validateObject(object);

const query = {
text: `
UPDATE
events
SET
metadata = $1
WHERE
id = $2
RETURNING *
;`,
values: [object.metadata, eventId],
};

const results = await database.query(query, options);
return results.rows[0];
}

function validateObject(object) {
const cleanObject = validator(object, {
event: 'required',
Expand All @@ -45,5 +24,4 @@ function validateObject(object) {

export default Object.freeze({
create,
updateMetadata,
});
16 changes: 4 additions & 12 deletions pages/api/v1/contents/[username]/[slug]/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,29 +150,21 @@ async function patchHandler(request, response) {
type: contentToBeUpdated.parent_id ? 'update:content:text_child' : 'update:content:text_root',
originatorUserId: request.context.user.id,
originatorIp: request.context.clientIp,
metadata: {
id: contentToBeUpdated.id,
},
},
{
transaction: transaction,
},
);

const updatedContent = await content.update(contentToBeUpdated.id, filteredBodyValues, {
oldContent: contentToBeUpdated,
eventId: currentEvent.id,
transaction: transaction,
});

await event.updateMetadata(
currentEvent.id,
{
metadata: {
id: updatedContent.id,
},
},
{
transaction: transaction,
},
);

await transaction.query('COMMIT');
await transaction.release();

Expand Down
17 changes: 5 additions & 12 deletions pages/api/v1/contents/index.public.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import nextConnect from 'next-connect';
import { randomUUID as uuidV4 } from 'node:crypto';

import { ForbiddenError } from 'errors';
import database from 'infra/database.js';
Expand Down Expand Up @@ -133,6 +134,7 @@ async function postHandler(request, response) {
}

secureInputValues.owner_id = userTryingToCreate.id;
secureInputValues.id = uuidV4();

const transaction = await database.transaction();

Expand All @@ -144,6 +146,9 @@ async function postHandler(request, response) {
type: secureInputValues.parent_id ? 'create:content:text_child' : 'create:content:text_root',
originatorUserId: request.context.user.id,
originatorIp: request.context.clientIp,
metadata: {
id: secureInputValues.id,
},
},
{
transaction: transaction,
Expand All @@ -155,18 +160,6 @@ async function postHandler(request, response) {
transaction: transaction,
});

await event.updateMetadata(
currentEvent.id,
{
metadata: {
id: createdContent.id,
},
},
{
transaction: transaction,
},
);

await transaction.query('COMMIT');
await transaction.release();

Expand Down
17 changes: 4 additions & 13 deletions pages/api/v1/users/[username]/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,24 +112,15 @@ async function patchHandler(request, response) {
try {
await transaction.query('BEGIN');

const currentEvent = await event.create(
{
type: 'update:user',
originatorUserId: request.context.user.id,
originatorIp: request.context.clientIp,
},
{
transaction: transaction,
},
);

const updatedUser = await user.update(targetUsername, secureInputValues, {
transaction: transaction,
});

await event.updateMetadata(
currentEvent.id,
await event.create(
{
type: 'update:user',
originatorUserId: request.context.user.id,
originatorIp: request.context.clientIp,
metadata: getEventMetadata(targetUser, updatedUser),
},
{
Expand Down
12 changes: 6 additions & 6 deletions tests/orchestrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,19 @@ async function findSessionByToken(token) {
}

async function createContent(contentObject) {
const contentId = contentObject?.id || randomUUID();

const currentEvent = await event.create({
type: contentObject?.parent_id ? 'create:content:text_child' : 'create:content:text_root',
originatorUserId: contentObject?.owner_id,
metadata: {
id: contentId,
},
});

const createdContent = await content.create(
{
id: contentId,
parent_id: contentObject?.parent_id || undefined,
owner_id: contentObject?.owner_id || undefined,
title: contentObject?.title || undefined,
Expand All @@ -197,12 +203,6 @@ async function createContent(contentObject) {
},
);

await event.updateMetadata(currentEvent.id, {
metadata: {
id: createdContent.id,
},
});

return createdContent;
}

Expand Down

0 comments on commit c781819

Please sign in to comment.