Redis2.6以后引入对lua的支持,再结合spring data redis,我们就可以使用redis做更多的事情。
以下是我设计的客服和客户断开连接的业务逻辑,不做文字描述。如果大家发现有缺陷的地方,可以一起来讨论分析。
--[[
会话断线
入参:
seatId:坐席id
返回值:
code:返回值
数据结构:
string:坐席信息
hash:坐席静态配置(SEAT_STATIC_CONFIG)、坐席动态配置(SEAT_DYNAMIC_CONFIG)
sorted set:客户等待队列(SEAT_WAIT_QUEUE)、坐席队列(SEAT_SESSION_QUEUE_KEY)
--]]
---------------------------参数配置---------------------------
local seatId = KEYS[1];
local SEAT_IDEL = "1"; -- 空闲
local SEAT_IN_SESSION = "2"; -- 解答中
local SEAT_BUSY = "3";-- 繁忙
local SEAT_LEAVE = "4"; -- 示忙
local SEAT_INFO_SUFFIX = "_seat_info";-- 坐席信息后缀
local SEAT_SCORE_DECREMENT = -86400000;-- 坐席分数减量
local SEAT_WAIT_QUEUE = "seat_wait_queue"; -- 等待坐席队列名
local SEAT_SESSION_CURRENT_KEY = "seat_session_current_key"; -- 坐席当前话务总量key
local SEAT_SESSION_QUEUE_KEY = "seat_session_queue_key"; -- 坐席会话session队列
local SEAT_CAPACITY_CURRENT_MAX_KEY = "seat_capacity_current_max_key"; -- 坐席最大容量key
local SEAT_INFO_SUFFIX = "_seat_info";-- 坐席信息后缀
local resp = {}; -- 返回值
---------------------------坐席配置---------------------------
local SEAT_STATIC_CONFIG = "seat_static_config";-- 坐席静态配置
local SEAT_CAPACITY_MAX = redis.call("hget",SEAT_STATIC_CONFIG,"Online_customer_service_ceiling");-- 每个坐席的最大容量
local SEAT_WAIT_QUEUE_MAX = redis.call("hget",SEAT_STATIC_CONFIG,"Queue_upper_limit_set");-- 等待队列上限数量
local SEAT_DYNAMIC_CONFIG = "seat_dynamic_config";-- 坐席动态配置
local SEAT_CAPACITY_CURRENT_MAX = redis.call("hget",SEAT_DYNAMIC_CONFIG,SEAT_CAPACITY_CURRENT_MAX_KEY); -- 坐席当前最大容量
---------------------------异常编码---------------------------
local OK = "100"; -- 成功
local INVALID_SEAT = "103"; -- 无效的坐席信息
---------------------------会话断线---------------------------
-- 获取当前坐席信息
local seat = redis.call("get",seatId..SEAT_INFO_SUFFIX);
if seat~=nil and seat~=false then
-- 更新坐席话务容量
local seatInfo = cjson.decode(seat);
seatInfo["currentSession"] = tonumber(seatInfo["currentSession"]) -1; -- 当前话务量-1
if seatInfo["status"]==SEAT_IDEL then
-- 如果坐席信息为空闲,则返回无效的坐席信息
resp["code"]=INVALID_SEAT;
return cjson.encode(resp);
end
-- 坐席队列分数减少
redis.call("zincrby",SEAT_SESSION_QUEUE_KEY,SEAT_SCORE_DECREMENT,seatId);
-- 坐席当前话务总量-1
redis.call("hincrby",SEAT_DYNAMIC_CONFIG,SEAT_SESSION_CURRENT_KEY,-1);
if seatInfo["status"]==SEAT_LEAVE then
-- 如果当前坐席状态为暂离,则坐席总话务容量-1
redis.call("hincrby",SEAT_DYNAMIC_CONFIG,SEAT_CAPACITY_CURRENT_MAX_KEY,-1);
if seatInfo["currentSession"]==0 then
-- 最后一个会话结束,则该坐席下线
-- 将坐席从坐席队列中移除
redis.call("zrem",SEAT_SESSION_QUEUE_KEY,seatId);
-- 将坐席信息删除
redis.call("del",seatId..SEAT_INFO_SUFFIX);
--
resp["code"]=OK;
return cjson.encode(resp);
else
-- 当前坐席容量更改为当前会话数量
seatInfo["capacity"] = seatInfo["currentSession"] ;
end
elseif seatInfo["status"]==SEAT_BUSY then
-- 如果当前坐席状态为繁忙,则更改状态为解答中
seatInfo["status"] = SEAT_IN_SESSION;
else
if seatInfo["status"]==SEAT_IN_SESSION and tonumber(seatInfo["currentSession"])==0 then
-- 如果当前坐席状态为解答中,而坐席最后一个会话结束,则更改状态为空闲
seatInfo["status"] = SEAT_IDEL;
end
end
-- 更新坐席信息
local seatInfoEncode = cjson.encode(seatInfo);
redis.log(redis.LOG_NOTICE,"seatInfoEncode is "..seatInfoEncode);
redis.call("set",seatId..SEAT_INFO_SUFFIX,seatInfoEncode);
--
resp["code"]=OK;
else
resp["code"]=OK;
end
---------------------------返回值---------------------------
local respEncode = cjson.encode(resp);
redis.log(redis.LOG_NOTICE,"resp is "..respEncode);
return respEncode;