Rumah > rangka kerja php > Laravel > teks badan

Menggunakan peristiwa Pemerhati dalam Laravel menyebabkan masalah pengecualian baris gilir Redis

藏色散人
Lepaskan: 2021-12-03 09:33:48
ke hadapan
2310 orang telah melayarinya

Lajur tutorial Laravel berikut akan berkongsi dengan anda rekod tentang pengecualian baris gilir Redis yang disebabkan oleh Laravel Observer, saya harap ia akan membantu semua orang!

1. Logik perniagaan

Selepas mencipta model baharu, gunakan acara model Observer Created untuk menolak ke dalam baris gilir penghantaran SMS tak segerak

AppHttpControllersUsersController

    public function store(User $user)
    {
        \DB::beginTransaction();

        try{
            $input = request()->validated();
            $user->fill($input);
            $user->save();
            //do something......
            //其他数据表操作

            \DB::commit();
        } catch ($e \Exception) {
            \DB::rollBack();
        }

    }
Salin selepas log masuk

AppObserversUserObserver

class UserObserver{
    public function created (User $user)
    {
        dispatch(new SmsQueue($user));
    }}
Salin selepas log masuk

2 Keabnormalan ditemui

Jabatan perniagaan melaporkan bahawa kadangkala pengguna tidak dapat menerima pemberitahuan SMS. , jadi saya menyemak Log mendapati terdapat ralat dan pengecualian sekali-sekala: Tiada hasil pertanyaan untuk model [AppModelsUser]. selepas mencipta model..., jadi saya membetulkan Kod perniagaan telah diperiksa dengan teliti dan meneka bahawa ia sepatutnya dipengaruhi oleh transaksi.

Sahkan sangkaan:

Sudah tentu, selepas menunggu selama tiga saat, pengecualian baris gilir penyerahan 100% dicetuskan.
    public function store(User $user)
    {
        \DB::beginTransaction();

        try{
            $input = request()->validated();
            $user->fill($input);
            $user->save();
            //do something......
            //其他数据表操作

            sleep(3); //三秒之后再提交事务            
            \DB::commit();
        } catch ($e \Exception) {
            \DB::rollBack();
        }

    }
Salin selepas log masuk

3. Analisis sebab

    $user->save() Kaedah ini akan mencetuskan penjadual jika data berjaya dibuat model acara satu persatu.
  • Tolak model ke baris gilir dalam acara dan proses baris gilir menggunakan data dalam baris gilir secara berterusan.
  • Dalam kebanyakan kes, jika melakukan sesuatu kelajuan pemprosesan adalah normal, proses giliran akan berjalan seperti biasa.
  • Jika terdapat kelewatan sekali-sekala semasa fasa melakukan sesuatu, menyebabkan transaksi dilakukan tetapi baris gilir telah mula menggunakan model baharu oleh itu, ralat di atas berlaku;
  • Kemudian apabila saya mencari rekod Isu Github, saya mendapati bahawa isu ini telah dibangkitkan dalam Isu pada tahun 2015, dan dalam Laravel 8.X akhirnya menambah sokongan untuk acara model transaksi Sokongan; learnku.com/docs/laravel/8.x/eloqu... , tetapi nampaknya tiada arahan berkaitan ditemui dalam dokumentasi komuniti~

Memandangkan versi saya ialah 6.x, saya tidak boleh menggunakan yang baharu ini ciri [ Menangis]~~

4 Menyelesaikan pengecualian

1 Ubah suai tahap pengasingan transaksi MySQL (tidak disyorkan) Ini melibatkan tahap pengasingan transaksi MySQL Tahap pengasingan lalai bagi enjin InnoDB ialah BACA BERULANG Perbezaan antara setiap peringkat boleh didapati dalam dokumentasi rasmi.

Menukar tahap pengasingan kepada READ UNCOMMITTED boleh menyelesaikan masalah ini, tetapi untuk mengelakkan masalah yang lebih besar, saya menasihati anda untuk tidak menggunakan kaedah ini~

2 pemantauan acara Semak kod sumber untuk mengetahui bahawa selepas transaksi selesai, acara yang sepadan akan dipanggil, jadi anda hanya perlu menambah pemantauan acara.

Menggunakan peristiwa Pemerhati dalam Laravel menyebabkan masalah pengecualian baris gilir Redis

    Tambah kelas baharu
  1. AppHandlersTransactionHandler

    class TransactionHandler{
        public array $handlers;
    
        public function __construct()
        {
            $this->handlers = [];
        }
    
        public function add(\Closure $handler)
        {
            $this->handlers[] = $handler;
        }
    
        public function run()
        {
            foreach ($this->handlers as $handler) {
                $handler();
            }
            $this->handlers = [];
        }}
    Salin selepas log masuk
  2. Buat fungsi tambahan
  3. app/helpers.php

    if (! function_exists('after_transaction')) {
        /*
         * 事务结束之后再进行操作
         * */
        function after_transaction(Closure $job)
        {
            app()->singletonIf(\App\Handlers\TransactionHandler::class, function (){
                return new \App\Handlers\TransactionHandler();
            });
            app(\App\Handlers\TransactionHandler::class)->add($job);
        }}
    Salin selepas log masuk
  4. Buat pendengar
  5. AppListenersTransactionListener

    namespace App\Listeners;use App\Handlers\TransactionHandler;class TransactionListener{
        public function handle()
        {
            app(TransactionHandler::class)->run();
        }}
    Salin selepas log masuk
  6. Ikat pendengar
  7. AppProvidersEventServiceProvider

    namespace App\Providers;use App\Listeners\TransactionListener;use Illuminate\Database\Events\TransactionCommitted;use Illuminate\Database\Events\TransactionRolledBack;use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;;class EventServiceProvider extends ServiceProvider{
        /**
         * The event listener mappings for the application.
         *
         * @var array
         */
        protected $listen = [
            TransactionCommitted::class => [
                TransactionListener::class
            ],
            TransactionRolledBack::class => [
                TransactionListener::class
            ]
        ];}
    Salin selepas log masuk
  8. Tukar kaedah panggilan
  9. AppObserversUserObserver

OK, penyelesaian yang elegan telah selesai~~
class UserObserver{
    public function created (User $user)
    {
        after_transaction(function() use ($user) {
            dispatch(new SmsQueue($user));
        });
    }}
Salin selepas log masuk

Cadangan berkaitan:

Video Five Laravel terkini tutorial

Atas ialah kandungan terperinci Menggunakan peristiwa Pemerhati dalam Laravel menyebabkan masalah pengecualian baris gilir Redis. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:learnku.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan