我使用Shopify API来侦听创建新产品时的事件。当我收到一个webhook时,我检索以下JSON数据:
{
"admin_graphql_api_id": "gid://shopify/Product/8867427221826",
"body_html": "<strong>Thshirt in verschiedenen farben</strong>",
"created_at": "2023-10-14T10:51:06-04:00",
"handle": "t-shirt",
"id": 8867427221826,
"product_type": "",
"published_at": "2023-10-14T10:51:06-04:00",
"template_suffix": "",
"title": "T-shirt",
"updated_at": "2023-10-14T10:51:08-04:00",
"vendor": "crystelorbs",
"status": "active",
"published_scope": "global",
"tags": "",
"variants": [
{
"admin_graphql_api_id": "gid://shopify/ProductVariant/47150807122242",
"barcode": "",
"compare_at_price": null,
"created_at": "2023-10-14T10:51:06-04:00",
"fulfillment_service": "manual",
"id": 47150807122242,
"inventory_management": "shopify",
"inventory_policy": "deny",
"position": 1,
"price": "29.95",
"product_id": 8867427221826,
"sku": "321dsfase1231321w",
"taxable": true,
"title": "34 / Blau",
"updated_at": "2023-10-14T10:51:06-04:00",
"option1": "34",
"option2": "Blau",
"option3": null,
"grams": 0,
"image_id": null,
"weight": 0,
"weight_unit": "kg",
"inventory_item_id": 49189935579458,
"inventory_quantity": 0,
"old_inventory_quantity": 0,
"requires_shipping": true
},
{
"admin_graphql_api_id": "gid://shopify/ProductVariant/47150807187778",
"barcode": "",
"compare_at_price": null,
"created_at": "2023-10-14T10:51:07-04:00",
"fulfillment_service": "manual",
"id": 47150807187778,
"inventory_management": "shopify",
"inventory_policy": "deny",
"position": 2,
"price": "29.95",
"product_id": 8867427221826,
"sku": "321dsfase1231321w-2",
"taxable": true,
"title": "33 / Blau",
"updated_at": "2023-10-14T10:51:07-04:00",
"option1": "33",
"option2": "Blau",
"option3": null,
"grams": 0,
"image_id": null,
"weight": 0,
"weight_unit": "kg",
"inventory_item_id": 49189935644994,
"inventory_quantity": 0,
"old_inventory_quantity": 0,
"requires_shipping": true
},
{
"admin_graphql_api_id": "gid://shopify/ProductVariant/47150807220546",
"barcode": "",
"compare_at_price": null,
"created_at": "2023-10-14T10:51:07-04:00",
"fulfillment_service": "manual",
"id": 47150807220546,
"inventory_management": "shopify",
"inventory_policy": "deny",
"position": 3,
"price": "29.95",
"product_id": 8867427221826,
"sku": "321dsfase1231321w-3",
"taxable": true,
"title": "12 / Blau",
"updated_at": "2023-10-14T10:51:07-04:00",
"option1": "12",
"option2": "Blau",
"option3": null,
"grams": 0,
"image_id": null,
"weight": 0,
"weight_unit": "kg",
"inventory_item_id": 49189935677762,
"inventory_quantity": 0,
"old_inventory_quantity": 0,
"requires_shipping": true
}
],
"options": [
{
"name": "Größe",
"id": 11148870222146,
"product_id": 8867427221826,
"position": 1,
"values": [
"34",
"33",
"12"
]
},
{
"name": "Farbe",
"id": 11148870254914,
"product_id": 8867427221826,
"position": 2,
"values": [
"Blau"
]
}
],
"images": [
{
"id": 43049062433090,
"position": 1,
"product_id": 8867427221826,
"width": 650,
"height": 300,
"alt": null,
"src": "https://cdn.shopify.com/s/files/1/0757/6479/3666/files/ggg-modified_6dcaf2fa-d307-4ee7-bdf1-c7a9dbeefd62.png?v=1697295067",
"created_at": "2023-10-14T10:51:07-04:00",
"updated_at": "2023-10-14T10:51:07-04:00",
"admin_graphql_api_id": "gid://shopify/ProductImage/43049062433090",
"variant_ids": []
}
],
"image": {
"id": 43049062433090,
"position": 1,
"product_id": 8867427221826,
"width": 650,
"height": 300,
"alt": null,
"src": "https://cdn.shopify.com/s/files/1/0757/6479/3666/files/ggg-modified_6dcaf2fa-d307-4ee7-bdf1-c7a9dbeefd62.png?v=1697295067",
"created_at": "2023-10-14T10:51:07-04:00",
"updated_at": "2023-10-14T10:51:07-04:00",
"admin_graphql_api_id": "gid://shopify/ProductImage/43049062433090",
"variant_ids": []
}
}
我用交易创建产品。例如,一个产品可能有50个图像和30个变量值,这需要一个50倍的client.query('返回INTO ....')循环。
因为Node.js是单线程的,所以对数组中的每个图像使用for循环是一个坏主意吗?
我听说过工作线程,但我使用队列系统。当我使用队列系统时,我必须使用工作线程吗?
代码:
export const CreateProduct = async ({product, shop_id}: { product: _Product; shop_id: UUID; }): Promise<ReturnQuery> => {
const client = await pool.connect();
try {
let product_options_data: {
p_o_id: number;
values: string[];
}[] = [];
await client.query('BEGIN');
const Product: QueryResult = await client.query(`
INSERT INTO product
(info, name, status, shop_id)
VALUES
($1, $2, $3, $4);
`, [product.body_html, product.title, product.status, shop_id]);
const p_id = Product.rows[0].id;
if(product?.images) {
for(let i = 0; i < product?.images?.length; i++) {
await client.query('INSERT INTO product_media (p_id, src, alt, s_position) VALUES ($1, $2, $3, $4);', [p_id, product.images[i].src, product.images[i].alt, product.images[i].position]);
}
}
if(product?.options) {
if(product.options.length > 0) {
for(let a = 0; a < product.options.length; a++) {
if(product?.options[a].values) {
const p_o_id: QueryResult = await client.query('INSERT INTO product_options (p_id, name, position) VALUES ($1, $2, $3);', [p_id, product.options[a].name, product.options[a].position]);
product_options_data.push({
p_o_id: p_o_id.rows[0].id,
values: product.options[a].values as string[]
})
}
}
}
}
await client.query('COMMIT');
} catch(e) {
await client.query('ROLLBACK');
console.log(e);
Sentry.captureException(e);
return {
message: ErrorMessageQuery,
statusCode: 500,
query: 'SHOPIFY_CREATE_PRODUCT'
}
} finally {
client.release();
}
};
我想知道有没有什么方法可以改进我的代码。我听说建议将事务处理得很小,但如果一个产品有50个图像或许多变体,我必须循环遍历所有图像并将它们添加到我的数据库中。你能给我一些有用的提示,使这个解决方案更好吗?
1条答案
按热度按时间t0ybt7op1#
您正在为每个磁盘使用
await
。很好在做所有这些工作时,你不会干扰JavaScript主循环。因此,服务器上的其他操作将在处理此操作时正常进行,即使需要一段时间。而且,你在一个事务中执行操作(
BEGIN
/COMMIT
),这对你的DBMS的性能很有帮助。在我看来你做得对。👏
如果你有大量的这些东西,你可以将这个操作重构为服务流程从工作队列中完成的一些事情。但这是一个很大的变化,可能是不必要的,除非你的名字是WAL或MART。