Skip to content

kubilayeldemir/coupon-api-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This is a learning project. (SQL, Locks, Transactions) It implements a coupon giveaway API that can support concurrent users atomically.

The use case of this API is a situation where thousands of users are waiting to collect coupons. What happens if thousands of users try to collect the same limited coupon at the same time?

API has 3 endpoints to give coupons:

  • /give/:couponId: First comes to mind solution. Wrong way.

  • /give-transaction/:couponId: Gives coupons with a transaction created with database/sql package.

  • give-transaction-pgfunction/:couponId: Gives coupons by calling a PostgreSQL function. Check the "give_coupon_to_user" function below.

Swagger Url: http://localhost:1323/swagger/index.html

You can use a simple load tester for testing, i used load-tester:

npm install -g load-tester

load-tester 5000

http://localhost:5000

Example Test Setup:

{
    "baseUrl": "http://localhost:1323",
    "duration": 15000,
    "connections": 100,
    "sequence": [
    { "method": "POST", "path": "/coupon/api/v1/give-transaction/d7513edf-511c-4515-a7e7-2920d50f1237"}
    ]
}

SQL For Tables:

create table coupon
(
    id       uuid    not null
        constraint coupon_pk
            primary key,
    name     text,
    type     text    not null,
    quantity integer not null
);

create unique index coupon_id_uindex
    on coupon (id);
    
create table coupon_given_events
(
    couponid    text    not null,
    userid      text    not null,
    newquantity integer not null
);

PostgreSQL Function Used By Api(give-transaction-pgfunction):

CREATE OR REPLACE FUNCTION give_coupon_to_user(couponId uuid, userId text) RETURNS void AS
$$
declare
    quantity_of_coupon integer;
begin
    select quantity
    into quantity_of_coupon
    from coupon
    WHERE id = couponId
    FOR UPDATE;

    IF quantity_of_coupon >= 1 THEN
        UPDATE coupon
        SET quantity = quantity - 1
        WHERE id = couponId;

        INSERT INTO coupon_given_events(CouponId, UserId, NewQuantity)
        VALUES (couponId, userId, quantity_of_coupon - 1);
    ELSE
        RAISE EXCEPTION 'Coupon run out!';
    end if;


end;
$$ LANGUAGE plpgsql;

Releases

No releases published

Packages

No packages published

Languages