ممکنه بعضی وقتا توی پروژه هاتون با دیتای زیاد و سنگینی سروکار داشته باشید که قراره محاسباتی روشون انجام بشه ، توی دیتابیس ذخیره بشن یا توی فایل save بشن . اما خب اگر کلاینت درخواست بده و شما بلافاصله مشغول انجام این کار بشید ممکنه کارتون توی back-end خیلی طول بکشه و کاربر خطای 504 Gateway Timeout بگیره .
یا حتی ممکنه بخواین یه کار ساده و سبک رو بعدا انجام بدید ( مثلا ارسال یک ایمیل یا sms به مشتری در روز و ساعت خاصی ) ... ولی خب مثال و بحث ما یه همچین چیزی نخواهد بود و بیشتر تمرکزمون توی این پست روی دیتای سنگین هست .
راه حل چیه ؟
یکی از امکانات خوب لاراول ، Queues هست که شما رو برای سپردن کارها به بکگراند راحت میکنه .
اگر داکیومنت خود لاراول رو بخونین میبینین که چقدر امکانات داره برای timeout , failure , ignore , retry و و و ... من در ادامه فرض میکنم که حداقل 3-4 دقیقه ای رو توی این صفحه گذروندید و حداقل تیتر هاشو خوندید :)
یکی از کارهایی که نوشته و معمولا از دست دوستان در میره تنظیم کردن cron job سرور هست . در نظر داشته باشید که شما اموری رو به " صف کارها " میسپارین و در نهایت با مطالعه و پیاده سازی بخش Scheduling به سرور میگید که مثلا هر شب یا هر 5 دقیقه لیست کارهای من رو چک کن و اونایی که باید رو انجام بده .
من قصدم اینه که وقتی کلاینت درخواستش رو میده سریع بهش بگم OK برو خیالت راحت ... و از طرفی بلافاصله توی بکگراند کارش رو برم انجام بدم و در نهایت مثلا بهش sms بدم و بگم برو نتیجشو چک کن مثلا ! نمیخوام خودمو درگیر scheduling بکنم ( بستگی به کارتون داره بالاتر گفتم که هدف ما انجام امور سنگین هست نه زمان بندی و تقسیم بندی ) . پس باید چه کنم ؟
طبق داکیومنت دیدین که برای اینکه queue رو به حالت آماده باش برای اجرا در بیارین از dispatch استفاده میکنین و اگر میخواین که بلافاصله اجرا بشه از dispatchNow استفاده میکنین که کار رو بصورت Synchronous انجام میده . طبق تجربه ، استفاده از پکیج barryvdh/laravel-async-queue رو شدیدا بهتون پیشنهاد میکنم از خیلی چیزا خلاصتون میکنه . توضیحاتش گویای همه چیز هست :
Just like the 'sync' driver, this is not a real queue driver. It is always fired immediatly. The only difference is that the closure is sent to the background without waiting for the response. This package is more usable as an alternative for running incidental tasks in the background, without setting up a 'real' queue driver.
bigJobClassHere::dispatch([ 'data' => $data, 'username' => auth()->user()->username, ])->onConnection('async');
ممکنه شما هم مثل من توی این کارهای سنگین بجز ارسال sms و کار با دیتابیس و ... بخواین با فایل هم کار کنین !
و هر چقدر کدی که توی controller ها به خوبی کار میکنه ( مثلا pdf ذخیره میشه یا Excelتون save میشه و ... ) رو داخل این job میندازین میبینین که نه ... انگار نه انگار ... ! اگر یکمی با کدتون ور رفته باشین مثلا شاید به این نتیجه برسین که implements ShouldQueue رو برمیدارم و حل میشه در صورتی که غافل از این هستید که کار ، دیگه توی بکگراند انجام نمیشه . اما راه حل چیه ؟
بعد از اینکه مطمئن شدین مشکل شما از سطح دسترسی ( permission ) فولدر مقصد نیست ، کافیه آدرس فایل هاتون رو از root سرور بدین . مثلا اگر قبلا میگفتین uploads حالا بگید :
/home/admin/domains/XXXXX.ir/public/uploads
ممکنه برای تست ( یا در حین کار با سیستم ) سرور رو درگیر یک Transaction سنگین بکنید بطوری که باقی کوئری ها دیرتر جوابشون بیاد و مثلا اگر از phpmyadmin ، mysql استفاده میکنید .. جدول ها باز نشن .. مقادیر آپدیت نشن و ...
سوال : چجوری لغوش کنم ؟
ج : وارد phpmyadmin بشین ( من این رو مثال میزنم چون میدونم اکثریت رو شامل میشه ) .. بخش status رو از همون صفحه ی اول انتخاب کنید . وارد processes بشین و پروسس مربوطه رو kill کنید .
در نهایت بعد از این همه پر حرفی امیدوارم این پست کمکی کرده باشه . من نمیخواستم همون آموزشی که توی داکیومنت لاراول هست رو اینجا مطرح کنم . هدف صرفا معرفی کتابخونه ی بالا و حل مشکل ذخیره فایل ها بود . متشکرم .