Blame view

publish/skynet/service/service_provider.lua 2.19 KB
4d6f285d   zhouhaihai   增加发布功能
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)