lk.StemCell

:quit ()

local lib = {type='lk.StemCell'} lib.__index = lib lk.StemCell = lib

local private = {}

setmetatable(lib, { -- new method __call = function(lib) local self = { -- Machine name name = Lubyk.host, -- List of pids in case we must restart a process. processes = {}, } setmetatable(self, lib)

private.start(self) return self end})

--============================================= lk.Service delegate

local execute_url, quit_url = lubyk.execute_url, lubyk.quit_url

if url == execute_url then return private.execute(self, ...) elseif url == quit_url then self:quit() else -- ignore self:error("Invalid url '%s'.", url) end end

-- TODO: notify errors. printf(...) end

-- The stem cell is the parent of the following processes, it cannot die -- before them. for name, pid in pairs(self.processes) do private.kill(pid) end

sched:quit() end

--=============================================== PRIVATE --- Start service. private.actions = {}

function private:start() local srv_opts = { callback = function(...) return self:callback(...) end, registration_callback = function(req, service) private.registrationCallback(self, service) end, type = 'lk.StemCell', quit = function() self:quit() end, } self.service = lk.Service(Lubyk.zone .. ':@' .. self.name , srv_opts) end

function private:registrationCallback(service) if (Lubyk.zone .. ':@' .. self.name) ~= service.name then -- We do not want to have two stem cells with the same name running printf("Another stem cell with name '%s' exists in zone '%s'. Quit.", self.name, Lubyk.zone) self:quit() end end

function private:execute(action, ...) local func = private.actions[action] if func then func(self, ...) else printf("Unknown action '%s'.", action) end end

--=============================================== ACTIONS

-- Spawn a new process that will callback to get data (yml definition, assets). function private.actions:spawn(name) -- Spawn Process. If a process dies, the stem cell will restart it. self.processes[name] = lk.spawn([[ require 'lubyk' process = lk.Process(%s) run() ]], name) -- the process will find the morph's ip/port by it's own service discovery end

-- Restart a given process (kill and let morph restart). function private.actions:kill(name) local pid = self.processes[name] -- kill if pid then private.kill(pid) end -- The process will be restarted. end