vendredi 23 mars 2018

how to use transactions with laravel to avoid race conditions

I got some code where an order gets created.. then a series of entries to the db are made that are specific to that order.. something like this:

public function arrived($id)

    .. validation logic

    $order->save();

    StoreWallet::collectCashFromDeliveryGuy($order);
    ..

    return response()->success(compact('order'));
}

// example in another file
public static function collectCashFromDeliveryGuy(Order $order)
{
    // I know that technically I can search here 
    // if a record with the same order id exists, 
    // but that would be too expensive 
    self::create([
        ..
        'order_id' => $order->id,
    ]);
}

the problem is that in our db logs, we are seeing that for some reason that for the same order created (and in this arrived controller), we are calling collectCashFromDeliveryGuy multiple times on the same order

I've read about database transactions and such, but it seems that this is more about rolling back all transactions if an error happens during the db update, rather than preventing a race condition from happening. What should I do?

update

this is the typical code, and this is my concern:

  public function arrived($id)

        .. validation logic

        DB::beginTransaction();

        try {

            $order->save();

            // what guarantees me that this won't be 
            // called more than once from a different process?
            StoreWallet::collectCashFromDeliveryGuy($order);
            ..
            DB::commit();
            // all good

            } catch (\Exception $e) {
                DB::rollback();
                // NOTE: this isn't about something that's 
                // going wrong, this is about multiple processes
                // working in parallel
                // something went wrong

            }
        return response()->success(compact('order'));
    }



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire