CEL Lightweight Message Bus
The CELLMB provides a node-internal backbone for an application architecture using sevices together with the publish/subscribe paradigm. So the business logic of a system can be organized in those services which can be exchanged easily when the interface stays unchanged. A service implementation is just a module providing three fixed and several service callback functions. The fixed ones are
start(SvcArgs) ->
% Start the service with the given arguments immediately after subscription.
% May be used to start a gen_server.
...
stop(SvcArgs) ->
% Stop the service with the arguments after unsubscription or shutdown.
...
processes(Msg, SvcArgs) ->
% Check if the passed message shall be processed by this service.
% A priority between 1 and 99 has to be returned, 0 means no processing.
...
The service functions depend on the commands the service shall process. Each publishing of a message contains the parts service, command, and arguments. The command part is the one controlling which callback function is called.
For example here's one synchronous request:
Responses = cellmb:request(sampleservice, do_something, [WithThis, AndThat]).
If the subscribed service myservice exports the function
processes(#msg{svc = sampleservice}, _SvcArgs) ->
?WITH_PRIO_NORMAL.
it signals the interest on handling all messages addressing the service sampleservice. This may be done through several services parallely, the priority defines the order of their processing. This processing is done in the service callback functions. In the example above the CELLMB checks if the function do_something/4 exists, otherwise process/4 is used. This may be used for flexible interceptor functions. See
do_something(Args, Ctx, SvcArgs, Msg) ->
...,
NewCtx = cellmb:ctxset(foo, bar),
...,
{ok, NewCtx, Response}.
or
process(Args, Ctx, SvcArgs, Msg) ->
...,
...,
noresponse.
The response of the service call is a structure containing the worst status code of all responses and the individual results.
{ok, [{ok, myservice, do_something, Response},
{ok, otherservice, process, OtherResponse}]}
The functions svcres and svcval help to extract the individual responses and their values for a status. Beside receiving those responses synchronously an asynchronous publishing and receiving is possible.
MH = cellmb:publish(anyservice, anycommand, Args), ..., ..., Responses = cellmb:rcvres(MH, Timeout).
If the response isn't relevant for the further program the message can simply be sent to the CELLMB:
cellmb:send(onemoreservice, onemorecommand, Args).
CEL Execution Time Measuring
The CELETM module supports the developer in analyzing the runtime behaviour of his application. Critical blocks can be surrounded with the begin and end of the measuring identified by a name. All measurings will be accumulated for each name, the result can be retrieved in an Erlang format or written to any I/O device - like the standard I/O.
So a typical block looks like
Measuring = celetm:begin_measuring({?MODULE, any, detailed, identifier}),
doing_this(),
doing_that(),
doing_more(),
celetm:end_measuring(Measuring).
Instead of begin_measuring/1 and end_measuring/1 the abbreviations bm/1 and em/1 can be used. The whole work of the begin of a measuring is done in the calling process while the end of a measuring leads to the sending of the measuring to a background gen_server process. This background process accumulates the measurings for a given name every 5000 measurings or when they results are retrieved.
This retrieving will be done through the call of
Measurings = celetm:retrieve().
Additionally a number between 1 and 6 for the sort field and a filter fun can be passed. The fun has to answer true or false for a tuple argument {Name, Count, MinTime, MaxTime, AvgTime, TotalTime}. Another output options is
celetm:io().
with optional arguments for an I/O device, the sort field number, and a filter fun. If no I/O device is defined the standard I/O will be used. So inside the shell the command above will print a table with the accumulated measurings.
+----------------------------------------------------+--------+-----------+-----------+-----------+--------------+
| Name | Count | Min Time | Max Time | Avg Time | Ttl Time |
+----------------------------------------------------+--------+-----------+-----------+-----------+--------------+
| {cellmbtst,small_stress_test} | 1 | 130.35 | 130.35 | 130.35 | 130.35 |
| {cellmb,aac,add} | 200 | 7.26 | 35.59 | 20.51 | 4101.41 |
| {cellmb,arithmetics,add} | 600 | 2.19 | 87.88 | 30.26 | 18157.81 |
| {cellmb,arithmetics,divide} | 200 | 3.92 | 59.86 | 31.08 | 6216.57 |
| {cellmb,arithmetics,foo} | 200 | 5.38 | 52.80 | 28.82 | 5764.41 |
| {cellmb,arithmetics,multiply} | 400 | 3.40 | 63.88 | 20.10 | 8038.74 |
| {cellmb,arithmetics,subtract} | 200 | 3.78 | 70.58 | 35.82 | 7164.60 |
| {cellmb,convert,ints_to_strs} | 400 | 2.25 | 42.59 | 17.23 | 6890.02 |
| {cellmb,produce,failure} | 200 | 6.59 | 28.52 | 17.67 | 3533.31 |
+----------------------------------------------------+--------+-----------+-----------+-----------+--------------+
| All times in milliseconds. |
+----------------------------------------------------------------------------------------------------------------+
CEL Simple Markup Language
