This document serves as an upgrade guide from the older, private @cel/io
/
celio
library. The @cisl/io
library features a large rewrite of the
original codebase, and improving on certain things, and making it overall
a bit more consistent on usage.
Through this document, when giving code examples for migration, we will use
celio
to refer to an instantiated usage of @cel/io
and cislio
to refer
to an instantiated usage of @cisl/io
.
The biggest thing is that outside of the core functionality,
everything else is a "plugin", and accessed via its own key off the primary
object. @cisl/io
comes with three built-in plugins:
- RabbitMQ (accessed through
io.rabbit
) README.md#rabbitmq - Redis (accessed through
io.redis
) README.md#redis - MongoDB (accessed through
io.mongo
) README.md#mongo
Adding additional plugins is as easy as installing them through npm
and then
loading them. See the README.md#registering-plugins
section on additional details. You will then need to consult the
plugin's README on usage details.
For the following sections, the available content types and what they translate to are:
application/json - json
text/string - string
text/number - number
application/octet-stream - buffer
For configuring @cisl/io
, it utilizes similar options as the @cel/io
however,
you will need to rename the key in the cog.json
file from mq
to rabbit
.
@cisl/io
will recognize the older mq
key, but it is suggested to change it. See
the README for full instructions on configuration values.
topic
is a string for the name of the queue to subscribe to and is the same
in both cases.
The oldHandler
was a callback which had the signature: (content: Buffer, headers: object)
where the first argument is the payload and the second is information about the
message (which is a fusion of its fields and properties).
The newHandler
callback looks like (message: {content: Buffer|json|string|number, fields: object, properties: object})
.
The content
field will be returned based on the set content-type
of the
caller. When receiving content from celio
then, the content-type
will not
be set and content
will be of type Buffer
. When coming from cislio
, the
content-type
is set automatically and so then content
will correspond to
what to send into rabbit via the publishTopic
method. You can use the middle
optional [options]
argument to set a content-type
to force, which allows
for interopability between @cel/io
and @cisl/io
. Once you are certain that
all incoming information is from something that utilizes content-type
field, then
you can remove the optional options
argument and use just (topic, newHandler)
.
The fields
and properties
elements correspond to stuff you would find in
the headers
parameter originally.
Translation would then therefore be something like this:
celio.onTopic('example-queue', (content) => {
const msg = JSON.parse(content.toString());
});
// translates to
cislio.rabbit.onTopic('example-queue', {contentType: 'application/json'}, (msg) => {
const msg = message.content;
});
celio.publishTopic(topic, oldContent[, options]) -> cislio.rabbit.publishTopic(topic, newContent[, options])
For both, topic
is the string name of the queue you wish to use. For
oldContent
, this had to be either a Buffer object or a string, with any
other value being invalid and would cause an error. newContent
by
contrast can Buffer, string, number, or JSON object. It will automatically use
the type of newContent
to automatically set the contentType
option which is
then used downstream. The optional options argument in both cases is the same,
and it can be viewed at amqplib.channel.publish.
Similar to the onTopic
method, you can force a content-type to be used for
@cisl/io
library, but should not be necessary for normal usage.
Translation would then therefore be something like this:
celio.publishTopic('example-queue', JSON.stringify(obj));
// translate to:
celio.publishTopic('example-queue', obj);
celio.doCall(queue, oldHandler[, noAck = true[, exclusive = true]]) -> cislio.rabbit.onRpc(queue, [options,] newHandler)
Where queue
is a string and the same in both instances. noAck
and
exclusive
are now properties of the options
object, which is optional, and you
can leave out, which uses the signature of cislio.rabbit.onRpc(queue, newHandler)
.
The oldHandler
method had a signature of ({content, headers}, reply, ackFunc)
where
content
is a Buffer, reply
is a unary function, and ackFunc
is a unary function only
defined if the noAck
value is false
. The reply
function can only accept a
Buffer or string. The newHandler
has the signature of
({content, fields, properties}, reply, ackFunc)
where it has similar
information as the handler in onTopic
. Similar to onTopic
, the content
field in the newReply
utilizes the content-type
of the sender to determine
how it looks. For example, if the content-type
is application/json
, then
content
will be parsed as a JSON object. You can force a particular parsing
by setting the contentType
in the options object. Similar to onTopic
, you
will want to set the content-type
for maximum interopability.
Translation would then be something like:
celio.doCall('rpc-queue', (message) => {
const msg = JSON.parse(message.content.toString());
});
// translates to:
cislio.rabbit.onRpc('rpc-queue', {contentType: 'application/json'} (message) => {
const msg = message.content;
})
celio.call(queue, content[, options]): oldPromise -> cislio.rabbit.publishRpc(queue, content[, options]): newPromise
Where queue
is a string that designates the name of the RPC queue. Content is
the payload where for celio
it must be a Buffer or string and for cislio
it can be a Buffer, string, number, or JSON stringifiable object. Options in
both cases is the same and correspond to
amqplib.channel.publish.
The most important one here is options.expiration
which defaults to 10 seconds,
and designates how long to wait before timing out for the function. Both functions
return a promise which is resolved when the callee of the RPC queue replies using
their reply
function. oldPromise
resolves with {content, headers}
where
content
is a Buffer and newPromise
resolves with {content, properties, fields}
where content
is based off if the caller sets an appropriate content-type
.
Similar to the other methods, you can force a content-type by setting one in
the options
method, which insures interopability with @cel/io
.
The translation would be:
celio.call('rpc-queue', JSON.stringify(obj)).then((message) => {
const msg = JSON.parse(message.content.toString());
});
// translates to
cislio.rabbit.publishRpc('rpc-queue', obj, {contentType: 'application-json'}).then((msg) => {
const msg = message.content;
});
@cel/io
and @cisl/io
differ greatly in their interface to Redis. The former
utilized the node-redis
client which offered only a callback based interface
to redis functions, and so @cel/io
surfaced a number of custom functions
that called down to the redis functions and then returns a promise instead of
a callback. @cisl/io
on the other hand utilizes the ioredis
library which
natively offers promises, and so acts as a much shallower wrapper over the
redis client. What this means in practice then is that @cel/io
will utilize
these custom functions which do not use the redis name while @cisl/io
you do.
This then allow looking up a particular redis function as easy as looking at
the Redis commands documentation.
Access to the respective modules is celio.store
vs cislio.redis
.
Translation though then ends up fairly straight forward. All methods return a promise, and that promise should be the same in either case.
For configuring @cisl/io
, it utilizes similar options as the @cel/io
however,
you will need to rename the key in the cog.json
file from store
to redis
.
@cisl/io
will recognize the older store
key, but it is suggested to change it. See
the README for full instructions on configuration values.
The speaker-worker
plugin is now in a separate plugin that is installable from
@cisl/io-speaker
. After installing it via npm, you would then add to your header:
require('@cisl/io-speaker');
and then usage remains the same through io.speaker
namespace. See
@cisl/io-speaker for more details.
The transcript-worker
plugin is now in a separate plugin that is installable from
@cisl/io-celio-transcript
. After installing it via npm, you would then add to your header:
require('@cisl/io-celio-transcript');
and then usage remains the same through cisl.transcript
namespace. See
@cisl/io-celio-transcript for more details.
NOTE: Probably not ready until moving to bishopcais/display-worker.
The display-worker
plugin is now a separate plugin that is installable from
@cisl/io-display
. After installing it via npm, you would then add to your header:
require('@cisl/io-display');
and then usage remains the same through io.display
namespace. See
@cisl/io-display for more details.