Order Masuk Serentak Tanpa Data Rosak: Cara Aku Handle Concurrency di eServe
Published:
Updated:
Handling High-Concurrency Orders in Laravel Without Data Corruption
(Apa yang aku buat dalam eServe)
Masalah concurrency biasanya muncul bila sistem dah mula digunakan betul-betul.
Order masuk serentak.
Merchant on off product.
Payment status update realtime.
Kalau backend tak kemas →
order boleh masuk untuk product yang sepatutnya tak boleh dibeli.
Aku jumpa semua ni masa bina eServe — sistem pure online product ordering yang sengaja tak guna stock, cuma guna konsep availability untuk simplify flow.
Kenapa eServe Tak Guna Stock
Aku tak implement stock atas sebab design, bukan sebab malas.
Dalam eServe:
-
product sama ada available atau not available
-
merchant boleh toggle bila-bila masa
-
tak ada kira-kira kuantiti
Result:
-
logic lebih ringkas
-
kurang edge case
-
kurang concurrency bug
Tapi… concurrency masih wujud.
Masalah Sebenar: Availability & Race Condition
Scenario real:
-
Merchant toggle product ke not available
-
Pada masa sama, beberapa customer tengah checkout
-
Multiple request cuba create order serentak
Kalau logic biasa:
if ($product->is_available)
{
// create order
}
Ini tetap race condition.
Rule Utama Aku di eServe: Availability Disahkan Dalam Transaction
Semua order creation aku bungkus dalam transaction:
DB::transaction(function () {
// lock product row
// recheck availability
// create order
// create order items
});
Maknanya:
-
status availability dibaca dalam lock
-
keputusan konsisten untuk semua request
1. Lock Product Row (Walaupun Tak Ada Stock)
$product = Product::where('id', $id)
->lockForUpdate()
->first();
Kenapa penting?
Sebab availability boleh berubah masa order tengah diproses.
Dengan lock:
-
request lain tunggu
-
tak ada order “terlepas masuk” lepas product ditutup
2. Availability Check Bukan UI Check
Aku tak percaya frontend untuk benda ni.
Button boleh disable, tapi request tetap boleh sampai.
Check sebenar:
if (! $product->is_available)
{
throw new Exception('Product not available');
}
Check ni berlaku dalam transaction, bukan sebelum.
3. Order Creation Kekal Atomic
Walaupun simple:
-
order
-
order items
-
initial payment status
Semua berlaku dalam satu transaction.
Kalau apa-apa fail → rollback.
No zombie order.
4. Payment Validation Kena Idempotent
Payment gateway dan manual action boleh trigger lebih dari sekali.
Dalam eServe:
-
merchant boleh klik PAID (yang payment cash)
-
callback payment boleh datang semula
Logic ringkas:
if ($order->is_paid)
{
return;
}
Simple, tapi selamat.
5. Realtime Guna Websocket, Logic Tetap Sync
eServe guna Websocket untuk:
-
merchant klik PAID → customer nampak popup realtime
-
merchant dapat sound alert bila ada order baru
-
order list update live
Important rule aku:
Realtime event tak pernah ubah data.
Semua update:
-
validate
-
save dalam DB
-
commit
-
baru broadcast
Apa Aku Belajar Dari eServe
-
Takde stock ≠ buang concurrency
-
Availability pun boleh jadi race condition
-
Transaction + row lock masih wajib
-
Realtime UI tak bermakna kalau backend bocor
Penutup
Kalau sistem kau:
-
ada online ordering
-
ada toggle availability
-
ada payment
-
ada realtime update
Concurrency tetap masalah utama, walaupun logic nampak simple.
eServe stabil bukan sebab features sikit.
Ia stabil sebab aku design untuk keadaan paling buruk.
