123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- local skynet = require "skynet"
- require "skynet.manager" -- import skynet.register
- local snax = require "skynet.snax"
- local cmd = {}
- local service = {}
- local function request(name, func, ...)
- local ok, handle = pcall(func, ...)
- local s = service[name]
- assert(type(s) == "table")
- if ok then
- service[name] = handle
- else
- service[name] = tostring(handle)
- end
- for _,v in ipairs(s) do
- skynet.wakeup(v.co)
- end
- if ok then
- return handle
- else
- error(tostring(handle))
- end
- end
- local function waitfor(name , func, ...)
- local s = service[name]
- if type(s) == "number" then
- return s
- end
- local co = coroutine.running()
- if s == nil then
- s = {}
- service[name] = s
- elseif type(s) == "string" then
- error(s)
- end
- assert(type(s) == "table")
- local session, source = skynet.context()
- if s.launch == nil and func then
- s.launch = {
- session = session,
- source = source,
- co = co,
- }
- return request(name, func, ...)
- end
- table.insert(s, {
- co = co,
- session = session,
- source = source,
- })
- skynet.wait()
- s = service[name]
- if type(s) == "string" then
- error(s)
- end
- assert(type(s) == "number")
- return s
- end
- local function read_name(service_name)
- if string.byte(service_name) == 64 then -- '@'
- return string.sub(service_name , 2)
- else
- return service_name
- end
- end
- function cmd.LAUNCH(service_name, subname, ...)
- local realname = read_name(service_name)
- if realname == "snaxd" then
- return waitfor(service_name.."."..subname, snax.rawnewservice, subname, ...)
- else
- return waitfor(service_name, skynet.newservice, realname, subname, ...)
- end
- end
- function cmd.QUERY(service_name, subname)
- local realname = read_name(service_name)
- if realname == "snaxd" then
- return waitfor(service_name.."."..subname)
- else
- return waitfor(service_name)
- end
- end
- local function list_service()
- local result = {}
- for k,v in pairs(service) do
- if type(v) == "string" then
- v = "Error: " .. v
- elseif type(v) == "table" then
- local querying = {}
- if v.launch then
- local session = skynet.task(v.launch.co)
- local launching_address = skynet.call(".launcher", "lua", "QUERY", session)
- if launching_address then
- table.insert(querying, "Init as " .. skynet.address(launching_address))
- table.insert(querying, skynet.call(launching_address, "debug", "TASK", "init"))
- table.insert(querying, "Launching from " .. skynet.address(v.launch.source))
- table.insert(querying, skynet.call(v.launch.source, "debug", "TASK", v.launch.session))
- end
- end
- if #v > 0 then
- table.insert(querying , "Querying:" )
- for _, detail in ipairs(v) do
- table.insert(querying, skynet.address(detail.source) .. " " .. tostring(skynet.call(detail.source, "debug", "TASK", detail.session)))
- end
- end
- v = table.concat(querying, "\n")
- else
- v = skynet.address(v)
- end
- result[k] = v
- end
- return result
- end
- local function register_global()
- function cmd.GLAUNCH(name, ...)
- local global_name = "@" .. name
- return cmd.LAUNCH(global_name, ...)
- end
- function cmd.GQUERY(name, ...)
- local global_name = "@" .. name
- return cmd.QUERY(global_name, ...)
- end
- local mgr = {}
- function cmd.REPORT(m)
- mgr[m] = true
- end
- local function add_list(all, m)
- local harbor = "@" .. skynet.harbor(m)
- local result = skynet.call(m, "lua", "LIST")
- for k,v in pairs(result) do
- all[k .. harbor] = v
- end
- end
- function cmd.LIST()
- local result = {}
- for k in pairs(mgr) do
- pcall(add_list, result, k)
- end
- local l = list_service()
- for k, v in pairs(l) do
- result[k] = v
- end
- return result
- end
- end
- local function register_local()
- local function waitfor_remote(cmd, name, ...)
- local global_name = "@" .. name
- local local_name
- if name == "snaxd" then
- local_name = global_name .. "." .. (...)
- else
- local_name = global_name
- end
- return waitfor(local_name, skynet.call, "SERVICE", "lua", cmd, global_name, ...)
- end
- function cmd.GLAUNCH(...)
- return waitfor_remote("LAUNCH", ...)
- end
- function cmd.GQUERY(...)
- return waitfor_remote("QUERY", ...)
- end
- function cmd.LIST()
- return list_service()
- end
- skynet.call("SERVICE", "lua", "REPORT", skynet.self())
- end
- skynet.start(function()
- skynet.dispatch("lua", function(session, address, command, ...)
- local f = cmd[command]
- if f == nil then
- skynet.ret(skynet.pack(nil, "Invalid command " .. command))
- return
- end
- local ok, r = pcall(f, ...)
- if ok then
- skynet.ret(skynet.pack(r))
- else
- skynet.ret(skynet.pack(nil, r))
- end
- end)
- local handle = skynet.localname ".service"
- if handle then
- skynet.error(".service is already register by ", skynet.address(handle))
- skynet.exit()
- else
- skynet.register(".service")
- end
- if skynet.getenv "standalone" then
- skynet.register("SERVICE")
- register_global()
- else
- register_local()
- end
- end)
|