Roadmap: interface-based callbacks for Event Collaboration
Aim is to implement notification events triggered from the server side, very easily from Delphi code, even over a single HTTP connection - for instance, WCF does not allow this: it will need a dual binding, so will need to open a firewall port and such.
It will be the ground of an Event
Collaboration stack included within mORMot, in a KISS way.
Event Collaboration is really a very interesting pattern, and even if not all your application domain should be written using it, some part may definitively benefit from it.
The publish / subscribe pattern provides greater network scalability and a more dynamic SOA implementation: for instance, you can add listeners to your main system events (even third-party developed), without touching your main server.
Or it could be the root of the Event Sourcing part of your business domain: since callbacks can also be executed on the server side (without communication), they can be used to easily add nice features like: complete rebuild, data consolidation (and CQRS), temporal query, event replay, logging, audit, backup, replication.
interface may be registered via a new
EventRegister() method - similar to
- on both
In fact, a callback / event can be seen as a service, but in the reverse order: from server to client.
interface shall have methods with no result, i.e.
defined only as
procedure, never as
are meant to define events (or messages), not actual request-response
Due to this stateless implementation design, events will be
executed on the server side asynchronously: in the server code,
interface method calls will be added to an internal FIFO, and
return immediately, without waiting for the client to be notified.
Then the clients will retrieve and handle notifications, at their own pace.
Clients needing to receive those messages will call an overloaded
EventRegister() method, with an implementation
corresponding to one of the server-side registered
will implement a strong and KISS publish / subscribe pattern. The
interface will define the so-called "topics" to be published.
Over HTTP, two client-side implementation modes are possible:
- Polling from client using a
WM_TIMERto maintain an user-friendly heart-beat (e.g. 500 ms), and retrieve all pending events (as JSON messages);
- Lock-and-wait request, similar to the Comet implementations.
In fact, both implementation modes may coexist: IMHO the lock-and-wait request may trigger a dedicated polling request. It is up to the client to add a lock-and-wait channel if its reaction time does matter, or if the heart-beat period is problematic.
TSQLRest callback internal methods will be abstract,
knowing nothing about polling or the underneath communication used.
We will try to code the most generic implementation, allowing polling and lock-and-wait for HTTP, but certainly some dedicated mechanism for other protocols (in-process, GDI, named pipes).
The mORMot architecture was designed to be truly RESTful, without the necessity to mimic HTTP, e.g. using its headers to transmit data, cookies for session handling or WebSockets for push emulation. The framework also implements direct in-process, GDI messages and named pipes communications. In fact, since GDI messages are two-way communications, we may implement a direct callback feature (via a simple
call), with no polling; and maybe change the named pipe mode to
duplex, or allow direct callback event for in-process/stand alone
So we should never be stuck to one implementation, but open to alternatives, and able to use the fastest mean of communication, depending on the transmission protocol involved. In the future, the HTTP part may use WebSockets, but it is currently not compatible with the http.sys kernel-mode server provided by Windows, and blocked by some packet inspectors / antivirus, since its content is not valid HTTP.
Since calls are added in a server-side FIFO, it could be the root of proper
off-line synchronization of multiple clients: if a client is disconnected from
the server, all future events will be stacked on the server side, and sent on
the next available connection, to be replayed on the client side.
We may therefore consider using not only memory, but also an ACID database to handle the message queue - e.g. via a dedicated
As we already stated in the beginning of this article, such a publish /
subscribe pattern would also benefit on the server side.
At data persistence level, we may, for instance, add a dedicated
IORMEvent interface to the
TSQLRestServer instance, publishing all CRUD operations of
the ORM, directly from its core (for both internal and external DB engines), so
that Event Sourcing features would be available to any number of
subscribers, even with on-the-fly registration. Generic per-table consolidation
or backup/replication features may be therefore be activated on need.
At application level, you may easily add external gateways (like a SOAP service or some HTML/RSS content), or integrate authenticated third-party components.
At domain level, it could be used to communicate between domain objects, in an Event Collaboration pattern, e.g. between multiple processes or PCs.
Similarly, an integrated scheduler (like cron) could be made available on the server side, with a dedicated threading model (not to interfere with the client-server process).
A whole horizon of extensions to the framework... we are open to any proposals!
Our framework has all the needed pieces of code:
stubbing and interception, persistence of the messages via ORM, JSON
serialization, security (using regular
methods), communication over several protocols...
So it would probably be the next feature to come, just after 1.17 release.
Stay tuned! Feedback / ideas are always welcome on our forum!