Model create() method is executed twice SOMETIMES and creates duplicated entry for 1:1 relation

347 views Asked by At

I am making a Laravel 5.7 system which has tons of code and models, but the ones in problem are:

  • Order - first created
  • Transport (1:1 Order) - afterwards created for Order

So Order.php has a function as follows:

public function create_transport(){
    ...

    // Create transport for order
    $transport = Transport::create([
        'order_id' => $this->id,
        'user_id' => $this->user_id,
        'printed' => 0,
        'sent' => 0,
        'commission_id' => $commission->id,
    ]);

    ...
}

Now this function is called in 5 different functions (once) overall in 3 controllers like this:

if( ... && !$order->transport ){
    $order->create_transport();
}

As you can see this should create a Transport only if no transport exists for an order.

However, in our production system we have confirmed 3 cases of duplicate Transport created in last year. The duplicates are exactly same except ID, also same created_at timestamp. Any ideas?

1

There are 1 answers

0
Lukas Grofcik On BEST ANSWER

so answer or update for this.

The reason was actually the Race Condition. There was a double click action performed on the button, which only happened sometimes as well because of the speed of clicking.

The way I handled it in this project is using DB::transaction()

public function create_transport(){
    DB::transaction(function() {
        $transport = $this->transport()->sharedLock()->first();

        ... here was validation if transport exists ...

        // Create transport for order
        $transport = Transport::create([
            'order_id' => $this->id,
            'user_id' => $this->user_id,
            'printed' => 0,
            'sent' => 0,
            'commission_id' => $commission->id,
        ]);

        ...

    }, 5);
}