mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-05-22 05:51:56 +00:00
Events can now be pushed into the engine via webpage.
The events are now queued through the DB.
This commit is contained in:
parent
32f5553471
commit
1342d0b2de
12 changed files with 162 additions and 41 deletions
12
README.md
12
README.md
|
|
@ -3,11 +3,12 @@ README: webapi-eca
|
||||||
|
|
||||||
# TODO Remake
|
# TODO Remake
|
||||||
|
|
||||||
>A Modular ECA Engine Server which acts as a middleware between WebAPI's.
|
> A Modular ECA Engine Server which acts as a middleware between WebAPI's.
|
||||||
>This folder continues examples of an ECA engine and how certain use cases could be implemented together with a rules language.
|
> This folder continues examples of an ECA engine and how certain use cases
|
||||||
|
> could be implemented together with a rules language.
|
||||||
>
|
>
|
||||||
>
|
> The server is started through the [server.js](server.html) module by calling
|
||||||
>The server is started through the [server.js](server.html) module by calling `node rule_server.js`.
|
> `node rule_server.js`.
|
||||||
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
@ -16,7 +17,8 @@ Getting started
|
||||||
**Prerequisites:**
|
**Prerequisites:**
|
||||||
|
|
||||||
- node.js (find it [here](http://nodejs.org/))
|
- node.js (find it [here](http://nodejs.org/))
|
||||||
- *(optional) [CoffeeScript](http://coffeescript.org/), if you want to compile from coffee sources:*
|
- *(optional) [CoffeeScript](http://coffeescript.org/), if you want to develop
|
||||||
|
and compile from coffee sources:*
|
||||||
|
|
||||||
sudo npm -g install coffee-script
|
sudo npm -g install coffee-script
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,27 @@ exports.isConnected = ( cb ) =>
|
||||||
setTimeout fCheckConnection, 500
|
setTimeout fCheckConnection, 500
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Push an event into the event queue.
|
||||||
|
|
||||||
|
@public pushEvent( *event* )
|
||||||
|
@param {Object} event
|
||||||
|
###
|
||||||
|
exports.pushEvent = ( event ) =>
|
||||||
|
log.print 'DB', 'Event pushed into the queue: ' + event.eventid
|
||||||
|
@db.rpush 'event_queue', JSON.stringify(event)
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Pop an event from the event queue and pass it to the callback(err, obj) function.
|
||||||
|
|
||||||
|
@public popEvent( *cb* )
|
||||||
|
@param {function} cb
|
||||||
|
###
|
||||||
|
exports.popEvent = ( cb )=>
|
||||||
|
@db.lpop 'event_queue', cb
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
Hashes a string based on SHA-3-512.
|
Hashes a string based on SHA-3-512.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ exports = module.exports = ( args ) ->
|
||||||
sess_sec = config.getSessionSecret() || sess_sec
|
sess_sec = config.getSessionSecret() || sess_sec
|
||||||
module.exports
|
module.exports
|
||||||
|
|
||||||
exports.addHandlers = ( fEvtHandler, fShutDown ) ->
|
exports.addHandlers = ( fShutDown ) ->
|
||||||
requestHandler.addHandlers fEvtHandler, fShutDown
|
requestHandler.addHandlers fShutDown
|
||||||
# Add cookie support for session handling.
|
# Add cookie support for session handling.
|
||||||
app.use express.cookieParser()
|
app.use express.cookieParser()
|
||||||
app.use express.session { secret: sess_sec }
|
app.use express.session { secret: sess_sec }
|
||||||
|
|
|
||||||
|
|
@ -53,16 +53,16 @@ This allows the parent to add handlers. The event handler will receive
|
||||||
the events that were received. The shutdown function will be called if the
|
the events that were received. The shutdown function will be called if the
|
||||||
admin command shutdown is issued.
|
admin command shutdown is issued.
|
||||||
|
|
||||||
@public addHandlers( *fEvtHandler, fShutdown* )
|
@public addHandlers( *fShutdown* )
|
||||||
@param {function} fEvtHandler
|
|
||||||
@param {function} fShutdown
|
@param {function} fShutdown
|
||||||
###
|
###
|
||||||
exports.addHandlers = ( fEvtHandler, fShutdown ) =>
|
exports.addHandlers = ( fShutdown ) =>
|
||||||
@eventHanlder = fEvtHandler
|
|
||||||
objAdminCmds.shutdown = fShutdown
|
objAdminCmds.shutdown = fShutdown
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
Handles possible events that were posted to this server and pushes them into the
|
||||||
|
event queue.
|
||||||
|
|
||||||
*Requires
|
*Requires
|
||||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||||
|
|
@ -80,7 +80,7 @@ exports.handleEvent = ( req, resp ) =>
|
||||||
# If required event properties are present we process the event #
|
# If required event properties are present we process the event #
|
||||||
if obj and obj.event and obj.eventid
|
if obj and obj.event and obj.eventid
|
||||||
resp.send 'Thank you for the event (' + obj.event + '[' + obj.eventid + '])!'
|
resp.send 'Thank you for the event (' + obj.event + '[' + obj.eventid + '])!'
|
||||||
@eventHandler obj
|
db.pushEvent obj
|
||||||
else
|
else
|
||||||
resp.writeHead 400, { "Content-Type": "text/plain" }
|
resp.writeHead 400, { "Content-Type": "text/plain" }
|
||||||
resp.send 'Your event was missing important parameters!'
|
resp.send 'Your event was missing important parameters!'
|
||||||
|
|
@ -132,14 +132,26 @@ exports.handleLogout = ( req, resp ) ->
|
||||||
resp.send 'Bye!'
|
resp.send 'Bye!'
|
||||||
|
|
||||||
|
|
||||||
getHandlerPath = (name) ->
|
###
|
||||||
|
Resolves the path to a handler webpage.
|
||||||
|
|
||||||
|
@private getHandlerPath( *name* )
|
||||||
|
@param {String} name
|
||||||
|
###
|
||||||
|
getHandlerPath = ( name ) ->
|
||||||
path.resolve __dirname, '..', 'webpages', 'handlers', name + '.html'
|
path.resolve __dirname, '..', 'webpages', 'handlers', name + '.html'
|
||||||
|
|
||||||
|
|
||||||
getHandlerFileAsString = (name) ->
|
|
||||||
fs.readFileSync getHandlerPath( name ), 'utf8'
|
|
||||||
###
|
###
|
||||||
|
Resolves the path to a handler webpage and returns it as a string.
|
||||||
|
|
||||||
|
@private getHandlerFileAsString( *name* )
|
||||||
|
@param {String} name
|
||||||
|
###
|
||||||
|
getHandlerFileAsString = ( name ) ->
|
||||||
|
fs.readFileSync getHandlerPath( name ), 'utf8'
|
||||||
|
|
||||||
|
###
|
||||||
*Requires
|
*Requires
|
||||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ init = ->
|
||||||
engine.addDBLinkAndLoadActionsAndRules db
|
engine.addDBLinkAndLoadActionsAndRules db
|
||||||
log.print 'RS', 'Passing handlers to http listener'
|
log.print 'RS', 'Passing handlers to http listener'
|
||||||
#TODO engine pushEvent needs to go into redis queue
|
#TODO engine pushEvent needs to go into redis queue
|
||||||
http_listener.addHandlers db, engine.pushEvent, shutDown
|
http_listener.addHandlers shutDown
|
||||||
#log.print 'RS', 'Passing handlers to module manager'
|
#log.print 'RS', 'Passing handlers to module manager'
|
||||||
#TODO loadAction and addRule will be removed
|
#TODO loadAction and addRule will be removed
|
||||||
#mm.addHandlers db, engine.loadActionModule, engine.addRule
|
#mm.addHandlers db, engine.loadActionModule, engine.addRule
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,31 @@ DB Interface
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Push an event into the event queue.
|
||||||
|
|
||||||
|
@public pushEvent( *event* )
|
||||||
|
@param {Object} event
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
exports.pushEvent = function(event) {
|
||||||
|
log.print('DB', 'Event pushed into the queue: ' + event.eventid);
|
||||||
|
return _this.db.rpush('event_queue', JSON.stringify(event));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pop an event from the event queue and pass it to the callback(err, obj) function.
|
||||||
|
|
||||||
|
@public popEvent( *cb* )
|
||||||
|
@param {function} cb
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
exports.popEvent = function(cb) {
|
||||||
|
return _this.db.lpop('event_queue', cb);
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Hashes a string based on SHA-3-512.
|
Hashes a string based on SHA-3-512.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ exports = module.exports = function(args) {
|
||||||
poller.on('message', function(evt) {
|
poller.on('message', function(evt) {
|
||||||
exports.pushEvent(evt);
|
exports.pushEvent(evt);
|
||||||
});
|
});
|
||||||
//start to poll the event queue
|
|
||||||
pollQueue();
|
|
||||||
return module.exports;
|
return module.exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -31,6 +29,8 @@ exports = module.exports = function(args) {
|
||||||
*/
|
*/
|
||||||
exports.addDBLinkAndLoadActionsAndRules = function(db_link) {
|
exports.addDBLinkAndLoadActionsAndRules = function(db_link) {
|
||||||
db = db_link;
|
db = db_link;
|
||||||
|
if(!db) log.error('EN', 'No DB!');
|
||||||
|
console.log(db);
|
||||||
if(ml && db) db.getActionModules(function(err, obj) {
|
if(ml && db) db.getActionModules(function(err, obj) {
|
||||||
if(err) log.error('EN', 'retrieving Action Modules from DB!');
|
if(err) log.error('EN', 'retrieving Action Modules from DB!');
|
||||||
else {
|
else {
|
||||||
|
|
@ -68,6 +68,8 @@ function loadRulesFromDB() {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
//start to poll the event queue
|
||||||
|
pollQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -101,22 +103,19 @@ exports.addRule = function(objRule) {
|
||||||
|
|
||||||
function pollQueue() {
|
function pollQueue() {
|
||||||
if(isRunning) {
|
if(isRunning) {
|
||||||
var evt = qEvents.dequeue();
|
db.popEvent(function (err, text) {
|
||||||
if(evt) {
|
if(!err && text) {
|
||||||
processEvent(evt);
|
processEvent(JSON.parse(text));
|
||||||
}
|
}
|
||||||
setTimeout(pollQueue, 50); //TODO adapt to load
|
setTimeout(pollQueue, 50); //TODO adapt to load
|
||||||
|
});
|
||||||
|
// var evt = qEvents.dequeue();
|
||||||
|
// if(evt) {
|
||||||
|
// processEvent(evt);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores correctly posted events in the queue
|
|
||||||
* @param {Object} evt The event object
|
|
||||||
*/
|
|
||||||
exports.pushEvent = function(evt) {
|
|
||||||
qEvents.enqueue(evt);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles correctly posted events
|
* Handles correctly posted events
|
||||||
* @param {Object} evt The event object
|
* @param {Object} evt The event object
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ HTTP Listener
|
||||||
return module.exports;
|
return module.exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.addHandlers = function(fEvtHandler, fShutDown) {
|
exports.addHandlers = function(fShutDown) {
|
||||||
var e, http_port;
|
var e, http_port;
|
||||||
requestHandler.addHandlers(fEvtHandler, fShutDown);
|
requestHandler.addHandlers(fShutDown);
|
||||||
app.use(express.cookieParser());
|
app.use(express.cookieParser());
|
||||||
app.use(express.session({
|
app.use(express.session({
|
||||||
secret: sess_sec
|
secret: sess_sec
|
||||||
|
|
|
||||||
|
|
@ -55,18 +55,18 @@ Request Handler
|
||||||
the events that were received. The shutdown function will be called if the
|
the events that were received. The shutdown function will be called if the
|
||||||
admin command shutdown is issued.
|
admin command shutdown is issued.
|
||||||
|
|
||||||
@public addHandlers( *fEvtHandler, fShutdown* )
|
@public addHandlers( *fShutdown* )
|
||||||
@param {function} fEvtHandler
|
|
||||||
@param {function} fShutdown
|
@param {function} fShutdown
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
exports.addHandlers = function(fEvtHandler, fShutdown) {
|
exports.addHandlers = function(fShutdown) {
|
||||||
_this.eventHanlder = fEvtHandler;
|
|
||||||
return objAdminCmds.shutdown = fShutdown;
|
return objAdminCmds.shutdown = fShutdown;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Handles possible events that were posted to this server and pushes them into the
|
||||||
|
event queue.
|
||||||
|
|
||||||
*Requires
|
*Requires
|
||||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||||
|
|
@ -88,7 +88,7 @@ Request Handler
|
||||||
obj = qs.parse(body);
|
obj = qs.parse(body);
|
||||||
if (obj && obj.event && obj.eventid) {
|
if (obj && obj.event && obj.eventid) {
|
||||||
resp.send('Thank you for the event (' + obj.event + '[' + obj.eventid + '])!');
|
resp.send('Thank you for the event (' + obj.event + '[' + obj.eventid + '])!');
|
||||||
return _this.eventHandler(obj);
|
return db.pushEvent(obj);
|
||||||
} else {
|
} else {
|
||||||
resp.writeHead(400, {
|
resp.writeHead(400, {
|
||||||
"Content-Type": "text/plain"
|
"Content-Type": "text/plain"
|
||||||
|
|
@ -157,16 +157,31 @@ Request Handler
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Resolves the path to a handler webpage.
|
||||||
|
|
||||||
|
@private getHandlerPath( *name* )
|
||||||
|
@param {String} name
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
getHandlerPath = function(name) {
|
getHandlerPath = function(name) {
|
||||||
return path.resolve(__dirname, '..', 'webpages', 'handlers', name + '.html');
|
return path.resolve(__dirname, '..', 'webpages', 'handlers', name + '.html');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Resolves the path to a handler webpage and returns it as a string.
|
||||||
|
|
||||||
|
@private getHandlerFileAsString( *name* )
|
||||||
|
@param {String} name
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
getHandlerFileAsString = function(name) {
|
getHandlerFileAsString = function(name) {
|
||||||
return fs.readFileSync(getHandlerPath(name), 'utf8');
|
return fs.readFileSync(getHandlerPath(name), 'utf8');
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
*Requires
|
*Requires
|
||||||
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
the [request](http://nodejs.org/api/http.html#http_class_http_clientrequest)
|
||||||
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
and [response](http://nodejs.org/api/http.html#http_class_http_serverresponse)
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ Rules Server
|
||||||
log.print('RS', 'Passing handlers to engine');
|
log.print('RS', 'Passing handlers to engine');
|
||||||
engine.addDBLinkAndLoadActionsAndRules(db);
|
engine.addDBLinkAndLoadActionsAndRules(db);
|
||||||
log.print('RS', 'Passing handlers to http listener');
|
log.print('RS', 'Passing handlers to http listener');
|
||||||
return http_listener.addHandlers(db, engine.pushEvent, shutDown);
|
return http_listener.addHandlers(shutDown);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
41
webpages/public/push_event.html
Normal file
41
webpages/public/push_event.html
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Invoke an event</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="mainbody">
|
||||||
|
<div id="pagetitle">Invoke an Event</div>
|
||||||
|
<p>
|
||||||
|
<textarea id="textarea_event" rows="20" cols="50">
|
||||||
|
{
|
||||||
|
"event": "mail",
|
||||||
|
"eventid": "mail_0",
|
||||||
|
"payload": {
|
||||||
|
"subject": "hello"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</textarea>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<button id="but_submit">invoke</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
//{ \"event\": \"mail\", \"eventid\": \"0\",... }"
|
||||||
|
$('#but_submit').click(function() {
|
||||||
|
$.post('../event', JSON.parse($('#textarea_event').val()))
|
||||||
|
.done(function(data) {
|
||||||
|
alert(data);
|
||||||
|
})
|
||||||
|
.fail(function(err) {
|
||||||
|
console.log(err);
|
||||||
|
alert('Posting of event failed: ' + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -5,6 +5,12 @@ body {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
-moz-tab-size: 2;
|
||||||
|
-o-tab-size:2;
|
||||||
|
tab-size:2;
|
||||||
|
}
|
||||||
|
|
||||||
#menubar {
|
#menubar {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue