I'm developing a factory automation software (a totem vehicle gate) in node.js.
The program has manage a bunch of 'tasks', by example it has to:
- monitor and control some I/O digital signals
- manage messages from external hosts, say via TCP socket messages
- poll other devices via HTTP REST (I need to convert a polling into an event)
- interface with a user though a keypad (and a screen terminal / voice output)
- query a relational DB, on an external server
- etc.
It's common sense that node.js is a perfect environment to manage (I/O) events and I'm aware about the fact I can generate custom events with EventEmitter
class.
Let assume that, for all tasks above detailed:
- any task could be managed in asynchronous way (HTTP/TCP/keyboard),
- I'm able to manage all above 'tasks' within a Node.js single thread (1 CPU core)
So I could design my main program as event-driven, implementing application logics as callbacks to SW events (Node.js customs events) mapping these with I/O (HW) events.
Here below a pseudocode:
// -----------------------------
// module A: keyboard management
// -----------------------------
// when user enter 5 digits (code) on the keypad keystroke (code omitted),
// emit the SW event 'digitsEntered'
keyBoardDialog.emit('digitsEntered', code)
// ----------------------------------------
// module B: I/O digital signals management
// ----------------------------------------
// poll (every ~300 msecs) through HTTP GET
// to get a buffer containing all digital input bits
// and when the digital input 1 goes ON, emit SW event, 'DI1ON' (code omitted)
digitalInputs.emit('DI1ON')
// -----------
// main module
// -----------
// all events handler
keyBoardDialog.on ('digitsEntered', (code) => doActionWithDigits(code) )
digitalInputs.on ('DI1ON', doAnotherAction() )
function doActionWithDigits(code) {
writeOnDatabase(code) // asynch
writeDigitalOutput(4) // HTTP GET = asynch
// any other synch or asynch function
}
Custom events callbacks (handlers), could contain sequential and/or asyncronous (asynch) functions.
By example let's focus on the task to read keystrokes from a keyboard.
The user has to input 5 digits and the keyboard module logic triggers the custom event ('digitsEntered'
).
The doActionWithDigits()
handler contains async functions.
Here possible timing/ data-sharing issues arise.
Because the event-based, but single thread architecture, I have to manage sort of 'no interrupt' logic inside the custom e event handler. To avoid data R/W overlap. To avoid that custom event is triggered again when running, etc. etc.
It seems to me that I'm facing classical multi thread management nightmares.
My questions:
- There is any good practice / guideline about how to manage custom events handlers in similar scenarios?
- What's the real advantage to use custom events, instead of Node.js callbacks? It's all in all a matter of decoupling logic?
- May you suggest something to read (articles/books) about design patterns good practices?