require "skynet.manager" local skynet = require "skynet" local queue = require "skynet.queue" local profile = require "skynet.profile" local sharetable = require "skynet.sharetable" local hotfixHelper = require "hotfix.helper" local cmdParams, allQueue local CMD = {} local cs = queue() local queueCmds = {} local baseCommand = {} function baseCommand.regQueue(cmd) assert(cmd, "regQueue cmd is nil") queueCmds[cmd] = cmd end function baseCommand.run(source, filename, ...) local output = {} local function print(...) local value = {...} for k, v in ipairs(value) do value[k] = tostring(v) end table.insert(output, table.concat(value, "\t")) end local env = setmetatable({print = print, args = {...}}, {__index = _ENV}) local func, err = load(source, filename, "bt", env) if not func then return {err} end local ok, err = xpcall(func, debug.traceback) if not ok then table.insert(output, err) end return output end function baseCommand.GC() collectgarbage("collect") end ----------------- 其他服务自行实现onStart onStop 接口 -- 服务启动 子服务启动需要返回 true function baseCommand.onStart() -- log.info("服务启动") end -- 服务退出 子服务退出需要返回 true function baseCommand.onStop() -- 服务退出 end -- 更新配置表 function baseCommand.update_config(obj, ...) -- 由于对战机器人等其他服务是传自身对象作为第一个参数 if type(obj) == "string" then sharetable.update(obj, ...) else sharetable.update(...) end end -- 更新协议 function baseCommand.update_proto() end -- 更新逻辑 function baseCommand.update_logic(changeList, params) -- 由于对战机器人等其他服务是传自身对象作为第一个参数 local fileChangeList = changeList for key, value in pairs(changeList) do if type(value) ~= "string" then fileChangeList = params break end end hotfixHelper.update(fileChangeList) end function baseCommand.exit() -- 发送服务停止并提出 local addr = skynet.localname(".steward") local function stop() if CMD.onStop then return CMD.onStop() end return baseCommand.onStop() end if not stop() then skynet.send(addr, "lua", "stop_service", skynet.self()) end if skynet.self() ~= addr then skynet.exit() end end local ti = {} local function profileCall(cmd, ...) local func = CMD[cmd] if not func then func = baseCommand[cmd] end assert(func, cmd .. " not found") -- local func = assert(CMD[cmd], cmd .. " not found") profile.start() local ret if queueCmds[cmd] or allQueue then ret = table.pack(cs(func, ...)) else ret = table.pack(func(...)) end local time = tonumber(string.format("%0.3f", profile.stop())) * 1000 local p = ti[cmd] if p == nil then p = {n = 0, ti = 0} ti[cmd] = p end p.n = p.n + 1 p.ti = p.ti + time p.max = math.max(p.max or 0, time) return table.unpack(ret) end local function dispatch(session, _, cmd, ...) if session > 0 then if not cmdParams then skynet.retpack(profileCall(cmd, ...)) else local params = {...} for i = #cmdParams, 1, -1 do table.insert(params, 1, cmdParams[i]) end skynet.retpack(profileCall(cmd, table.unpack(params))) end else if not cmdParams then profileCall(cmd, ...) else local params = {...} for i = #cmdParams, 1, -1 do table.insert(params, 1, cmdParams[i]) end profileCall(cmd, table.unpack(params)) end end end local root = {} function root.initCmdParams(...) local temp = {...} if next(temp) then cmdParams = temp end end function root.allQueue() allQueue = true end -- 服务别称 local lServiceName function root.setNickName(name) lServiceName = name end function root.getNickName() return lServiceName end function root.start(commond, serviceName, remote) CMD = commond if serviceName then root.setNickName(serviceName) end -- CMD = setmetatable(commond, {__index=baseCommand}) skynet.info_func( function() return {mem = collectgarbage("count"), profile = ti} end ) skynet.start( function() skynet.dispatch("lua", dispatch) end ) skynet.init( function() if serviceName then skynet.register(serviceName) end local noReport, exitLevel, NoClose = CMD.onStart() -- 发送服务启动成功 if not noReport then skynet.send(".steward", "lua", "start_service", skynet.self(), serviceName, remote, exitLevel, NoClose) end -- 热更新初始化 local initFlag = (serviceName and serviceName == ".steward") hotfixHelper.init(initFlag) end ) end return root