Mohammad Jawad Barati
Mohammad Jawad Barati
خواندن ۳ دقیقه·۴ سال پیش

استفاده از transaction ها تو Sequelize

وقتی پروژه رو میخوای توی مد production ببری باید transaction ها رو حتما استفاده بکنی.

اول اصلا یه مورد کاربرد خیلی قشنگ از این transaction ها رو بگم تا با ذوق بیشتری بخونید. فرض کن چند تا رکورد تو دیتابیس که به هم مربوط هستن، میخوای اضافه بکنی، حالا وسط ساختن این رکوردا یه اروری بنا به هر دلیلی اروری رخ میده.

در نتیجه حالا نصفش (فرض کن ۲ تاش) ساخته شده تو دیتابیس ولی نصف دیگش نه (فرض کن ۳ تا رکورد اضافه نشدن). حالا باید چجوری rollback بزنی؟ این تیکه کدو ببین:

const t = await sequelize.transaction(); try { // Then, we do some calls passing this transaction as an option: const user = await User.create({ firstName: 'Bart', lastName: 'Simpson' }, { transaction: t }); await user.addSibling({ firstName: 'Lisa', lastName: 'Simpson' }, { transaction: t }); // If the execution reaches this line, no errors were thrown. // We commit the transaction. await t.commit(); } catch (error) { // If the execution reaches this line, an error was thrown. // We rollback the transaction. await t.rollback(); }

دو راه برای استفاده از transaction ها در Sequelize

برای استفاده از تراکنش ها دو راه داریم:

  • تو روش Unmanaged کار ها دستی انجام میشه. مثل مثال بالا که ترکنش رو خودمن گفتیم commit یا rollback بکن.
  • روش managed کار ها اتوماتیک انجام میشه و اگه اروری رخ بده خودش rollback میکنه.

خب توی روش managed ما میایم callback رو به sequelize.transaction میدیم. این کال‌بک میتونه async باشه. که معمولا هم آسنک هست.

مراحل کار برای managed

  1. یه transaction به صورت اتوماتیک شروع میشه. (همون t که توی دستی خودمون میساختیم اینجا به صورت اتوماتیک ساخته میشه)
  2. تو قدم بعدی sequelize اون کال‌بک رو با t فراخونی میکنه
  3. اگه کال‌بک چیزی throw بکنی، sequelize به صورت خودکار transaction رو rollback میکنه
  4. اگه کال‌بک با موفقیت اجرا بشه sequelize میاد اون transaction رو commit میکنه.
  5. در آخرین مرحله sequelize.transaction ممکنه به دو صورت فراخونی بشه: صورت اول اینه که resolve میشه، صورت دوم اینه که reject میشه.

البته این موضوع به اینجا ختم نمیشه و کلی داستان داره. داستان اونجایی هست که تو خودت برای یه ریکوئست تست میکنی و همه چی ظاهرا اوکی هست ولی برای تعداد ریکوئست بالا در لحظه کدت درست کار نمیکنه.

خب حالا برای اینکه ممکنه از چند جا به sequelize وصل بشیم باید یه connection pool استفاده بکنیم:

import Sequelize from 'sequelize'; const _sequelize = new Sequelize(config.database, config.user, config.password, { host: config.host, dialect: 'mysql', port: config.port, pool: { max: 5, min: 1, idle: 10000, evict: 10000, } }); export { _sequelize, };

قدم بعدی اینه که بیای transaction رو استفاده بکنی:

try { const result = await sequelize.transaction(async (t) => { const user = await User.create({ firstName: 'Abraham', lastName: 'Lincoln' }, { transaction: t }); await user.setShooter({ firstName: 'John', lastName: 'Boothe' }, { transaction: t }); return user; }); // If the execution reaches this line, the transaction has been committed successfully // `result` is whatever was returned from the transaction callback (the `user`, in this case) } catch (error) { // If the execution reaches this line, an error occurred. // The transaction has already been rolled back automatically by Sequelize! };

منابع:

sequelizenode jsroolbacktransactionsql base database
برنانه نویس، مدرس، محقق. عاشق انیمه هستم و دنبال چالش ها جدید.
شاید از این پست‌ها خوشتان بیاید