Skip to content

My solution for handling race conditions using Laravel Redis Lock and InnoDB Record Lock.

Notifications You must be signed in to change notification settings

uhcakip/coupon-race-condition

Repository files navigation

Table of contents

Description

My solution for handling race conditions by using Laravel Redis Lock & InnoDB Record Lock. This project includes stress tests to validate the effectiveness of the implemented solution.

Flowchart

flowchart TB

Client --> |Submit signup data| Server
Server --> DB[(Database)]
DB --> |Register a member| memberTable[/Member/]
memberTable --> |Get available coupon and mark as used| couponTable[/Coupon/]
Loading

Code written by others before optimizing

public sendCoupon(Member $member) {
    $coupon = Coupon::where('member_id', null)->get()->first();
    
    if (is_null($coupon)) {
        throw new Exception('no issuable coupon', 1);
    }
    
    try {
        DB::beginTransaction();
        $coupon->member_id = $member->id;
        $coupon->redeemed_at = date('Y-m-d H:i:s');
        $coupon->save();
        DB::commit();
    } catch (Throwable $th) {
        DB::rollback();
        throw new Exception('send coupon failed', 1);
    }
}

Requirement

  • Docker

Installation

  1. By running commands below, docker will build 4 containers: app (including PHP 8.1, Golang 1.18, k6, xk6), nginx, mysql, redis

    git clone https://github.com/uhcakip/coupon-race-condition.git
    
    cd path/to/project
    
    make start
  2. Access Docker container and build k6 with extension

    make exec-app
    
    cd k6
    
    xk6 build --with github.com/szkiba/xk6-faker
  3. Running API stress test

    ./k6 run scripts/sign-up.js

About

My solution for handling race conditions using Laravel Redis Lock and InnoDB Record Lock.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published