vendredi 19 juin 2020

Software Design a Highly Available Scratch Card System

In an interview, I was asked to design a Scratch Card system like the Google Pay scratch card.

I have come up with a design but is not scalable. Can you suggest a scalable solution?

Requirements:

1. start time and end time -> scratch card should appear after x interval of mins
2. pool of rewards - [{10:1000, 5: 20000, 50:100, Missed: unlimited}] ie, key - amount, value -quantity of rewards available
3. weightage of rewards(probability) - [{10:20, 5:50, 50: 2, Missed: 25}] ie, key -amount, value -weightage
4. 1 user can have 1 reward from a pool within x interval
5. Scratch card availability timings: 10 A.M - 4 P.M and each scratch card is presented after 2 hours
6. in a day 4 scratches person can do, At max, he can actually earn a reward is a number y

Here I am concentrating only on the 'claim' API design. ie, the design for claiming a scratch card.

API:

POST /scratch/
{
"user_id": <user_id>
}

Tables

Format: table_name - column, column...

user - user_id, user_name
screatch_card - scratch_card_id, amount, available_pool, weightage, generated_time, end_time, availability_interval
user_scratch_card_map - user_id, scratch_card_id, scratched_time

Algorithmic Steps(pseudo-code):

  1. receives a request POST /scratch/
  2. Lookup user_scratch_card_map with userid and current day(timestamp)
  3. If the amount received is greater than allowed, reject the transaction
  4. If the time is outside the given range, also reject the transaction
  5. Else:
# get the slot to see if the user availed a scratch card during this time
index = Floor[(current_time - generated_time ) / availability_interval]

if scratched time in between [generated_time + availability_interval: generated_time + index * availability_interval]:
 skip this scratch card

# Logic to select a scratch card

total weight -> 87 (sum of all the weights of scratch cards)
index = floor(Math.rand()* total_weight )

selected_scratch_card = List_available_scratch_card[index]

  1. After selecting the scratch card, update the tables 'user_scratch_card_map', 'screatch_card' by locking both the tables(a transaction)

The problem lies mostly in step 6. It is hardly extensible. I have to make a lock on screatch_card means not allowed to other users when one update in progress.

Can you help me to extend this logic to a distributed system so that it is highly available and huge traffic is there?

Aucun commentaire:

Enregistrer un commentaire