add skynet.service

This commit is contained in:
Cloud Wu
2017-06-01 16:58:51 +08:00
parent 25763fc70b
commit 1d364b5c22
5 changed files with 207 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
root = "./"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua"
lualoader = root .. "lualib/loader.lua"
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
lua_cpath = root .. "luaclib/?.so"

43
lualib/skynet/service.lua Normal file
View File

@@ -0,0 +1,43 @@
local skynet = require "skynet"
local service = {}
local cache = {}
local provider
local function get_provider()
provider = provider or skynet.uniqueservice "service_provider"
return provider
end
local function check(func)
local info = debug.getinfo(func, "u")
assert(info.nups == 1)
assert(debug.getupvalue(func,1) == "_ENV")
end
function service.new(name, mainfunc, ...)
local p = get_provider()
local addr, booting = skynet.call(p, "lua", "test", name)
if addr then
service.address = addr
else
if booting then
service.address = skynet.call(p, "lua", "query", name)
else
check(mainfunc)
local code = string.dump(mainfunc)
service.address = skynet.call(p, "lua", "launch", name, code, ...)
end
end
cache[name] = service.address
return service.address
end
function service.query(name)
if not cache[name] then
cache[name] = skynet.call(get_provider(), "lua", "query", name)
end
return cache[name]
end
return service

View File

@@ -0,0 +1,113 @@
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.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)

View File

@@ -0,0 +1,7 @@
local skynet = require "skynet"
local kvdb = require "kvdb"
skynet.start(function()
kvdb.set("A", 1)
print(kvdb.get "A")
end)

43
test/testservice/kvdb.lua Normal file
View File

@@ -0,0 +1,43 @@
local skynet = require "skynet"
local service = require "skynet.service"
local kvdb = {}
-- service.address is the default address registered by itself.
function kvdb.get(key)
return skynet.call(service.address, "lua", "get", key)
end
function kvdb.set(key, value)
skynet.call(service.address, "lua", "set", key , value)
end
-- this function will be injected into an unique service, so don't refer any upvalues
local function service_mainfunc(...)
local skynet = require "skynet"
skynet.error(...) -- (...) passed from service.new
local db = {}
local command = {}
function command.get(key)
return db[key]
end
function command.set(key, value)
db[key] = value
end
-- skynet.start is compatible
skynet.dispatch("lua", function(session, address, cmd, ...)
skynet.ret(skynet.pack(command[cmd](...)))
end)
end
skynet.init(function()
service.new("kvdb", service_mainfunc, "Service Init")
end)
return kvdb