Files
cfw-autumn/server/src/_luaScripts/cusLuaScripts/batchDeleteCustomers.lua
2025-11-20 16:58:07 +00:00

104 lines
3.9 KiB
Lua

-- batchDeleteCustomers.lua
-- Atomically deletes multiple customers and all their associated entity caches
-- ARGV[1]: JSON array of {orgId, env, customerId} objects
-- Returns: number of keys deleted
local customersJson = ARGV[1]
local customers = cjson.decode(customersJson)
local allKeysToDelete = {}
-- Helper function to add balance-related keys for a cache key
local function addBalanceKeys(keysToDelete, cacheKey, featureIds)
if not featureIds or #featureIds == 0 then
return
end
for _, featureId in ipairs(featureIds) do
local balanceKey = buildBalanceCacheKey(cacheKey, featureId)
table.insert(keysToDelete, balanceKey)
-- Get the balance HSET to find breakdown/rollover counts
local balanceData = redis.call("HGETALL", balanceKey)
if balanceData and #balanceData > 0 then
-- Convert array to hash table
local balanceHash = {}
for i = 1, #balanceData, 2 do
balanceHash[balanceData[i]] = balanceData[i + 1]
end
-- Delete rollover keys
local rolloverCount = tonumber(balanceHash["_rollover_count"]) or 0
for i = 0, rolloverCount - 1 do
table.insert(keysToDelete, buildRolloverCacheKey(cacheKey, featureId, i))
end
-- Delete breakdown keys
local breakdownCount = tonumber(balanceHash["_breakdown_count"]) or 0
for i = 0, breakdownCount - 1 do
table.insert(keysToDelete, buildBreakdownCacheKey(cacheKey, featureId, i))
end
end
end
end
-- Process each customer
for _, customerInfo in ipairs(customers) do
local orgId = customerInfo.orgId
local env = customerInfo.env
local customerId = customerInfo.customerId
-- Build versioned cache key using shared utility
local cacheKey = buildCustomerCacheKey(orgId, env, customerId)
-- Get the customer base JSON to find entity and feature IDs
local baseJson = redis.call("GET", cacheKey)
-- Skip if customer not in cache
if baseJson then
table.insert(allKeysToDelete, cacheKey)
local success, customer = pcall(cjson.decode, baseJson)
if success and customer then
local entityIds = customer._entityIds or {}
local balanceFeatureIds = customer._balanceFeatureIds or {}
-- Add customer balance keys (with rollover/breakdown)
addBalanceKeys(allKeysToDelete, cacheKey, balanceFeatureIds)
-- Process each entity
for _, entityId in ipairs(entityIds) do
local entityCacheKey = buildEntityCacheKey(orgId, env, customerId, entityId)
table.insert(allKeysToDelete, entityCacheKey)
-- Get entity to find its feature IDs
local entityJson = redis.call("GET", entityCacheKey)
if entityJson then
local entitySuccess, entity = pcall(cjson.decode, entityJson)
if entitySuccess and entity then
local entityFeatureIds = entity._balanceFeatureIds or {}
-- Add entity balance keys (with rollover/breakdown)
addBalanceKeys(allKeysToDelete, entityCacheKey, entityFeatureIds)
end
end
end
end
end
end
-- Use UNLINK instead of DEL for async deletion (non-blocking)
local deletedCount = 0
if #allKeysToDelete > 0 then
-- UNLINK has a limit, so batch in chunks of 1000 keys
local chunkSize = 1000
for i = 1, #allKeysToDelete, chunkSize do
local chunk = {}
for j = i, math.min(i + chunkSize - 1, #allKeysToDelete) do
table.insert(chunk, allKeysToDelete[j])
end
deletedCount = deletedCount + redis.call("UNLINK", unpack(chunk))
end
end
return deletedCount