-
Notifications
You must be signed in to change notification settings - Fork 3
Applications
There are two interfaces for LAppS applications (hearafter services) available: Standalone and Reactive. Every service may have several running copies (instances), all working parallel on the same task.
Standalone services are not communicating with clients directly. These services are LUA modules which run indefinitely (until a shutdown is requested) and doing some jobs that may be required by other services.
These services are expected to comply with the following interface:
- Provide methods init() and run() with no arguments.
- Call must_stop() on regular basis to check if LAppS wants to shut down.
Here is an example service (time_broadcast) which may be found in the examples folder of LAppS distribution (broadcasts string with time on CID 0).
time_broadcast={}
time_broadcast.__index=time_broadcast
time_broadcast.init=function()
bcast:create(1000);
time_broadcast.nap=nap:new();
end
time_broadcast.run=function()
print("running")
local oon=nljson.decode([[{
"cid" : 5,
"message" : [ "" ]
}]]);
while not must_stop()
do
time_broadcast.nap:usleep(1000000);
local timenow=os.time();
local timestr=os.date("%c",timenow);
oon.message[1]="Server time: "..timestr;
bcast:send(1000,oon);
end
end
return time_broadcast;
NOTE: Standalone services are declared in service descriptors or within lapps.json by setting the value of the attribute standalone to true.
Reactive services are responding to clients' requests, though NOT limited to request-response schema of communications if using LAppS protocol. Every reactive service instance will have its own set of clients. No clients are shared between these services.
Reactive services are expected to comply to following interface:
- Provide methods onStart(), onShutdown() - without arguments
- For RAW protocol provide method onMessage(handler,opcode, message), Where handler is a WebSocket handler - an integer value; opcode - WebSocket opcode (an integer value); message - lua string value is sent by client (may contain binary data with opcode equal 2 - binary).
- For LAppS protocol provide method onMessage(handler,msg_type, message). The only difference from above is the msg_type - an integer value from 1 to 4; and the message an nljson_object, - see Embedded modules API for details.
- onDisconnect(handler) - this method will be called when the client is disconnected, and its handler will be provided for your service.
Here is an example of a reactive service skeleton:
myapp = {}
myapp.__index = myapp;
myapp.onStart=function()
-- do something on start
end
myapp.onDisconnect=function(handler)
-- handler - is a unique client identifier
-- react on client disconnect
end
myapp.onShutdown=function()
-- do something on shutdown
end
myapp.onMessage=function(handler,opcode, message)
-- it is an echo, - we return back the same message
local result, errmsg=ws:send(handler,opcode,message);
if(not result)
then
print("myapp::OnMessage(): "..errmsg);
end
return result;
end
return myapp;
Here is an example of the onMessage method for LAppS protocol:
--[[
-- @param handler - io handler to use for ws:send and ws:close
-- @param msg_type - helper enum defining type of message:
-- 1 - Client Notification Message as defined in LAppS Specification 1.0 (without params)
-- 2 - Client Notification Message with params attribute
-- 3 - Request as defined in LAppS Specification 1.0 (without params)
-- 4 - Request with params attribute
-- @param message - an nljson userdata object
--]]
console.onMessage = function(handler,msg_type, message)
local switch={
[1] = function() -- a CN without params
local method=methods._cn_wo_params_method[message.method] or console.method_not_found;
end,
[2] = function() -- a CN with params
local method=methods._cn_w_params_method[message.method] or console.method_not_found;
method(handler,message.params,message.cid);
end,
[3] = function() -- request without params
local method=methods._request_wo_params_method[message.method] or console.method_not_found;
method(handler);
end,
[4] = function()
local method=methods._request_w_params_method[message.method] or console.method_not_found;
method(handler,message.params);
end
}
switch[msg_type]();
return true;
end