service_provider.lua
2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
local skynet = require "skynet"
local provider = {}
local function new_service(svr, name)
local s = {}
svr[name] = s
s.queue = {}
return s
end
local svr = setmetatable({}, { __index = new_service })
function provider.query(name)
local s = svr[name]
if s.queue then
table.insert(s.queue, skynet.response())
else
if s.address then
return skynet.ret(skynet.pack(s.address))
else
error(s.error)
end
end
end
local function boot(addr, name, code, ...)
local s = svr[name]
skynet.call(addr, "lua", "init", code, ...)
local tmp = table.pack( ... )
for i=1,tmp.n do
tmp[i] = tostring(tmp[i])
end
if tmp.n > 0 then
s.init = table.concat(tmp, ",")
end
s.time = skynet.time()
end
function provider.launch(name, code, ...)
local s = svr[name]
if s.address then
return skynet.ret(skynet.pack(s.address))
end
if s.booting then
table.insert(s.queue, skynet.response())
else
s.booting = true
local err
local ok, addr = pcall(skynet.newservice,"service_cell", name)
if ok then
ok, err = xpcall(boot, debug.traceback, addr, name, code, ...)
else
err = addr
addr = nil
end
s.booting = nil
if ok then
s.address = addr
for _, resp in ipairs(s.queue) do
resp(true, addr)
end
s.queue = nil
skynet.ret(skynet.pack(addr))
else
if addr then
skynet.send(addr, "debug", "EXIT")
end
s.error = err
for _, resp in ipairs(s.queue) do
resp(false)
end
s.queue = nil
error(err)
end
end
end
function provider.test(name)
local s = svr[name]
if s.booting then
skynet.ret(skynet.pack(nil, true)) -- booting
elseif s.address then
skynet.ret(skynet.pack(s.address))
elseif s.error then
error(s.error)
else
skynet.ret() -- nil
end
end
skynet.start(function()
skynet.dispatch("lua", function(session, address, cmd, ...)
provider[cmd](...)
end)
skynet.info_func(function()
local info = {}
for k,v in pairs(svr) do
local status
if v.booting then
status = "booting"
elseif v.queue then
status = "waiting(" .. #v.queue .. ")"
end
info[skynet.address(v.address)] = {
init = v.init,
name = k,
time = os.date("%Y %b %d %T %z",math.floor(v.time)),
status = status,
}
end
return info
end)
end)