lundi 7 décembre 2020

LockForUpdate on create?

I have an API endpoint in my Laravel application that should conduct an insert if a row with colum order_id does not exists, otherwise a sequence of updates should take place (Simply calling INSERT (..) UPDATE ON DUPLICATE .. does not work here, its a big transaction that takes place on multiple tables).

Currently, the logic goes like this where order_id is a unique column in the database:

public function updateOrCreate(Request $request) {
  try{
     DB::beginTransaction();
     $tempOrder = TempOrder::create(['order_id' => $request->order_id]);
     TempOrder::where('order_id', '=', $order_id)->lockForUpdate()->get();
     $this->createRelations($tempOrder);
     DB::commit();  
  }
  catch(\ExceoptionDuplicateRow $e)
  {
     DB::rollback();
     $this->update($request->order_id);
  }
      
}


public function update($order_id)
    \DB::transaction(function() {
        TempOrder::where('order_id', '=', $order_id)->lockForUpdate()->get();
        // Do update
   }
}

The problem is, its theoretically possible that if two concurrent calls take place with the same order_id, first an TempOrder may be created but the lock may be triggered first by the call that executes the update, meaning $this->createRelations($tempOrder); will be called after $this->update($request->order_id);.

I have to ensure that this never happens. Is this possible? Something like

TempOrder::create(['order_id' => $request->order_id])->lockForUpdate();

?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire