Skip to content

Commit

Permalink
Merge pull request #67 from yalla-coop/validate-webhooks
Browse files Browse the repository at this point in the history
Validate-webhooks
  • Loading branch information
Karmel99 authored Apr 24, 2024
2 parents eaa1d02 + 3e3da2b commit c48ea46
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 215 deletions.
36 changes: 0 additions & 36 deletions web/webhooks/getStoredHubVariant.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { DeliveryMethod } from '@shopify/shopify-api';
import * as Sentry from '@sentry/node';

import { getClient, query } from '../database/connect.js';
import { getClient } from '../database/connect.js';
import { updateCurrentVariantInventory } from './updateCurrentVariantInventory.js';
import { getStoredHubVariant } from './getStoredHubVariant.js';

export const handleHubVariantUpdate = async (v, activeSalesSession) => {
const { variantId, quantity } = v;
import { addOrdersWebhookToDB } from './utils/addOrdersWebhookToDB.js';
import { validateLineItemsAndCallHandler } from './utils/validateLineItemsAndCallHandler.js';
import { throwError } from '../utils/index.js';

if (!variantId || !quantity) {
export const handleHubVariantUpdate = async (singleVariantFromDB) => {
if (!singleVariantFromDB) {
return;
}

Expand All @@ -18,96 +19,61 @@ export const handleHubVariantUpdate = async (v, activeSalesSession) => {
producerProductId,
hubVariantId,
noOfItemsPerPackage,
mappedProducerVariantId,
numberOfExitingExcessOrders,
} = await getStoredHubVariant({
variantId,
quantity
});
mappedVariantId,
numberOfExcessOrders
} = singleVariantFromDB;

await updateCurrentVariantInventory({
hubProductId,
storedHubVariant: {
hubVariantId,
noOfItemsPerPackage,
mappedVariantId: mappedProducerVariantId,
numberOfExcessOrders: numberOfExitingExcessOrders,
mappedVariantId,
numberOfExcessOrders
},
producerProductId
});
} catch (e) {
console.log(e);
throw new Error(e);
throwError('handleHubVariantUpdate: Error updating variant inventory', e);
}
};

const handleCartCreateUpdateCheckoutCreateUpdateWebhook = async (
const handleCartCreateUpdateCheckoutCreateUpdateWebhook = async ({
topic,
shop,
body,
webhookId
) => {
webhookId,
payload,
activeSalesSessions,
variantsFromPayload,
variantsFromDB
}) => {
const sqlClient = await getClient();
try {
const sqlClient = await getClient();
try {
await sqlClient.query('BEGIN');
const selectWebhookQuery = `
SELECT
*
FROM webhooks
WHERE id = $1
`;
const result = await query(selectWebhookQuery, [webhookId], sqlClient);
const webhook = result.rows[0];
if (webhook) {
return;
}

const payload = JSON.parse(body);
const insertWebhookQuery = `
INSERT INTO webhooks
(id,topic,data)
VALUES ($1,$2,$3)
`;
await query(insertWebhookQuery, [webhookId, topic, payload], sqlClient);
await sqlClient.query('COMMIT');
await addOrdersWebhookToDB(webhookId, topic, payload, sqlClient);

const selectActiveSalesSessionQuery = `
SELECT
*
FROM sales_sessions
WHERE sales_sessions.is_active = true
`;
console.log(`handleCartsWebhook: added webhook with id ${webhookId} to db`);

const activeSalesSessionResult = await query(
selectActiveSalesSessionQuery
);
const activeSalesSession = activeSalesSessions?.[0];

const activeSalesSession = activeSalesSessionResult.rows[0];

if (!activeSalesSession) {
throw new Error('No active sales session found');
}

const variants = payload.line_items.map((lineItem) => ({
variantId: lineItem.variant_id,
quantity: Number(lineItem.quantity)
}));
if (!activeSalesSession) {
throw new Error('No active sales session found');
}

const promises = variants.map(async (v) =>
handleHubVariantUpdate(v, activeSalesSession)
const promises = variantsFromPayload.map(async (v) => {
const singleVariantFromDB = variantsFromDB.find(
(ev) => Number(ev.hubVariantId) === Number(v.variantId)
);
return handleHubVariantUpdate(singleVariantFromDB);
});

await Promise.all(promises);
} catch (err) {
await sqlClient.query('ROLLBACK');
throw new Error(err);
} finally {
sqlClient.release();
}
await Promise.all(promises);
console.log('handleCartWebhook: Updated inventory for variants, all done!');
} catch (err) {
console.log('Error:----', err);
Sentry.captureException(err);
return {
statusCode: 500
};
} finally {
sqlClient.release();
}
};

Expand All @@ -117,13 +83,11 @@ const handleCartCreateUpdateCheckoutCreateUpdateWebhookCallback = async (
body,
webhookId
) => {
console.log('handleCartCreateUpdateCheckoutCreateUpdateWebhookCallback');
handleCartCreateUpdateCheckoutCreateUpdateWebhook(
topic,
shop,
body,
webhookId
validateLineItemsAndCallHandler(
{ topic, shop, body, webhookId },
handleCartCreateUpdateCheckoutCreateUpdateWebhook
);

return {
statusCode: 200
};
Expand Down
7 changes: 6 additions & 1 deletion web/webhooks/handleOrderCancelledWebhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { DeliveryMethod } from '@shopify/shopify-api';
import dotenv from 'dotenv';
import { handleOrderWebhook } from './utils/handleOrderWebhook.js';
import { validateLineItemsAndCallHandler } from './utils/validateLineItemsAndCallHandler.js';

dotenv.config();

Expand All @@ -12,7 +13,11 @@ const handleOrderCancelledWebhookCallback = async (
webhookId
) => {
// without awaiting
handleOrderWebhook(topic, shop, body, webhookId, 'cancelled');
validateLineItemsAndCallHandler(
{ topic, shop, body, webhookId, orderType: 'cancelled' },
handleOrderWebhook
);

return {
statusCode: 200
};
Expand Down
7 changes: 6 additions & 1 deletion web/webhooks/handleOrderPaidWebhookHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
import { DeliveryMethod } from '@shopify/shopify-api';
import dotenv from 'dotenv';
import { handleOrderWebhook } from './utils/handleOrderWebhook.js';
import { validateLineItemsAndCallHandler } from './utils/validateLineItemsAndCallHandler.js';

dotenv.config();

const handleOrderPaidWebhookCallback = async (topic, shop, body, webhookId) => {
// without awaiting
handleOrderWebhook(topic, shop, body, webhookId, 'completed');

validateLineItemsAndCallHandler(
{ topic, shop, body, webhookId, orderType: 'completed' },
handleOrderWebhook
);

return {
statusCode: 200
Expand Down
106 changes: 68 additions & 38 deletions web/webhooks/handleProductDeleteWebhookHandler.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,88 @@
import { DeliveryMethod } from '@shopify/shopify-api';
import * as Sentry from '@sentry/node';
import { DeliveryMethod } from '@shopify/shopify-api';

import { query, getClient } from '../database/connect.js';
import { addOrdersWebhookToDB } from './utils/addOrdersWebhookToDB.js';
import { throwError } from '../utils/index.js';
const deleteVariantsQuery = `
DELETE FROM variants
WHERE product_id = (
SELECT id
FROM products
WHERE hub_product_id = $1
)
`;
const deleteProductQuery = `
DELETE FROM products
WHERE hub_product_id = $1
`;

export const deleteVariantsAndProductCachedData = async (hubProductId) => {
try {
const client = await getClient();
try {
await client.query('BEGIN');

const deleteVariantsQuery = `
DELETE FROM variants
const findVariantQuery = `
SELECT *
FROM variants
WHERE product_id = (
SELECT id
FROM products
WHERE hub_product_id = $1
)
`;
await query(deleteVariantsQuery, [hubProductId], client);

const deleteProductQuery = `
DELETE FROM products
SELECT id
FROM products
WHERE hub_product_id = $1
)
`;

await query(deleteProductQuery, [hubProductId], client);
export const deleteVariantsAndProductCachedData = async (
hubProductId,
sqlClient
) => {
try {
await sqlClient.query('BEGIN');

await client.query('COMMIT');
} catch (err) {
console.log(err);
await query(deleteVariantsQuery, [hubProductId], sqlClient);
await query(deleteProductQuery, [hubProductId], sqlClient);

await client.query('ROLLBACK');
throw new Error(err);
} finally {
client.release();
}
await sqlClient.query('COMMIT');
} catch (err) {
console.log(err);
Sentry.captureException(err);
await sqlClient.query('ROLLBACK');
throwError(
'deleteVariantsAndProductCachedData: Error occurred while processing the query',
err
);
}
};

const handleProductDeleteCallback = async (topic, shop, body, webhookId) => {
const payload = JSON.parse(body);
const sqlClient = await getClient();
try {
const payload = JSON.parse(body);
const { id: hubProductId } = payload;

const { id: producerProductId } = payload;
// we should not await this
// function because it will take a long time and we should reply to shopify as soon as possible
console.log('deleting product webhook');
deleteVariantsAndProductCachedData(producerProductId);
const { rows: variants } = await query(findVariantQuery, [hubProductId]);

if (variants.length < 1) {
return {
statusCode: 200,
body: 'Webhook - handleProductDeleteCallback: No variants found'
};
}
await addOrdersWebhookToDB(webhookId, topic, payload, sqlClient);
console.log(
`handleProductDeleteCallback: added webhook with id ${webhookId} to db for product id ${hubProductId}`
);

return {
statusCode: 200
};
await deleteVariantsAndProductCachedData(hubProductId, sqlClient);

return {
statusCode: 200
};
} catch (err) {
console.error(
'handleProductDeleteWebhook: Error occurred while processing the request',
err
);
Sentry.captureException(err);
return {
statusCode: 500
};
} finally {
sqlClient.release();
}
};

const handleProductDeleteWebhookHandler = {
Expand Down
Loading

0 comments on commit c48ea46

Please sign in to comment.