48 lines
1.3 KiB
Lua
48 lines
1.3 KiB
Lua
-- Atomic ticket purchase script
|
|
-- KEYS[1]: event tickets key (e.g., "event:1:tickets")
|
|
-- KEYS[2]: event metadata key (e.g., "event:1:meta")
|
|
-- KEYS[3]: global stats key ("global:stats")
|
|
-- ARGV[1]: timestamp
|
|
-- ARGV[2]: purchase ID (UUID)
|
|
|
|
local ticketKey = KEYS[1]
|
|
local metaKey = KEYS[2]
|
|
local globalKey = KEYS[3]
|
|
local timestamp = ARGV[1]
|
|
local purchaseId = ARGV[2]
|
|
|
|
-- Check if event exists
|
|
if redis.call('EXISTS', metaKey) == 0 then
|
|
return {nil, "EVENT_NOT_FOUND"}
|
|
end
|
|
|
|
-- Atomically pop a ticket from the list
|
|
local ticket = redis.call('LPOP', ticketKey)
|
|
|
|
if not ticket then
|
|
return {nil, "NO_TICKETS_AVAILABLE"}
|
|
end
|
|
|
|
-- Update event metadata
|
|
local soldCount = redis.call('HINCRBY', metaKey, 'soldTickets', 1)
|
|
redis.call('HSET', metaKey, 'lastSoldAt', timestamp)
|
|
|
|
-- Update global stats
|
|
redis.call('HINCRBY', globalKey, 'totalSold', 1)
|
|
|
|
-- Store purchase record
|
|
local purchaseKey = 'purchase:' .. purchaseId
|
|
local eventIdFromKey = string.match(ticketKey, 'event:(%d+):tickets')
|
|
redis.call('HSET', purchaseKey,
|
|
'ticketId', ticket,
|
|
'eventId', eventIdFromKey,
|
|
'purchaseId', purchaseId,
|
|
'timestamp', timestamp,
|
|
'status', 'completed'
|
|
)
|
|
|
|
-- Set expiration for purchase record (24 hours)
|
|
redis.call('EXPIRE', purchaseKey, 86400)
|
|
|
|
return {ticket, "SUCCESS", soldCount}
|