Actions
The actions are the callable/public methods of the service. The action calling represents a remote-procedure-call (RPC). It has request parameters & returns response, like a HTTP request.
If you have multiple instances of services, the broker will load balance the request among instances.

Call services
To call a service use the broker.call method. The broker looks for the service (and a node) which has the given action and call it. The function returns a Promise.
Syntax
const res = await broker.call(actionName, params, opts);
The actionName is a dot-separated string. The first part of it is the service name, while the second part of it represents the action name. So if you have a posts service with a create action, you can call it as posts.create.
The params is an object which is passed to the action as a part of the Context. The service can access it via ctx.params. It is optional. If you don't define, it will be {}.
The opts is an object to set/override some request parameters, e.g.: timeout, retryCount. It is optional.
Available calling options:
| Name | Type | Default | Description |
|---|---|---|---|
timeout | Number | null | Timeout of request in milliseconds. If the request is timed out and you don't define fallbackResponse, broker will throw a RequestTimeout error. To disable set 0. If it's not defined, the requestTimeout value from broker options will be used. |
retries | Number | null | Count of retry of request. If the request is timed out, broker will try to call again. To disable set 0. If it's not defined, the retryPolicy.retries value from broker options will be used. |
fallbackResponse | Any | null | Returns it, if the request has failed. |
nodeID | String | null | Target nodeID. If set, it will make a direct call to the specified node. |
meta | Object | {} | Metadata of request. Access it via ctx.meta in actions handlers. It will be transferred & merged at nested calls, as well. |
parentCtx | Context | null | Parent Context instance. Use it to chain the calls. |
requestID | String | null | Request ID or Correlation ID. Use it for tracing. |
Usages
Call without params
const res = await broker.call("user.list");
Call with params
const res = await broker.call("user.get", { id: 3 });
Call with calling options
const res = await broker.call("user.recommendation", { limit: 5 }, {
timeout: 500,
retries: 3,
fallbackResponse: defaultRecommendation
});
Call with promise error handling
broker.call("posts.update", { id: 2, title: "Modified post title" })
.then(res => console.log("Post updated!"))
.catch(err => console.error("Unable to update Post!", err));
Direct call: get health info from the "node-21" node
const res = await broker.call("$node.health", null, { nodeID: "node-21" })
Metadata
Send meta information to services with meta property. Access it via ctx.meta in action handlers. Please note that in nested calls the meta is merged.
When writing REST APIs, you can obtain the current user session from ctx.meta.user. If you want to access ctx.meta.user within the action being called, you need to manually pass it in.
const res = await this.broker.call('objectql.find',
{
objectName: 'accounts',
query: {
fields: ['name', 'owner'],
filters: ['owner', '=', ctx.meta.user.userId],
sort: 'name desc'
},
},
{
meta:{
user: ctx.meta.user
}
}
);
Streaming
Moleculer supports Node.js streams as request params and as response. Use it to transfer an incoming file from a gateway, encode/decode or compress/decompress streams.
Examples
Send a file to a service as a stream
const stream = fs.createReadStream(fileName);
broker.call("storage.save", stream, { meta: { filename: "avatar-123.jpg" }});
Please note, the params should be a stream, you cannot add any additional variables to the params. Use the meta property to transfer additional data.
Receiving a stream in a service
module.exports = {
name: "storage",
actions: {
save(ctx) {
// Save the received stream to a file
const s = fs.createWriteStream(`/tmp/${ctx.meta.filename}`);
ctx.params.pipe(s);
}
}
};
Return a stream as response in a service
module.exports = {
name: "storage",
actions: {
get: {
params: {
filename: "string"
},
handler(ctx) {
return fs.createReadStream(`/tmp/${ctx.params.filename}`);
}
}
}
};
Process received stream on the caller side
const filename = "avatar-123.jpg";
broker.call("storage.get", { filename })
.then(stream => {
const s = fs.createWriteStream(`./${filename}`);
stream.pipe(s);
s.on("close", () => broker.logger.info("File has been received"));
})
AES encode/decode example service
const crypto = require("crypto");
const password = "moleculer";
module.exports = {
name: "aes",
actions: {
encrypt(ctx) {
const encrypt = crypto.createCipher("aes-256-ctr", password);
return ctx.params.pipe(encrypt);
},
decrypt(ctx) {
const decrypt = crypto.createDecipher("aes-256-ctr", password);
return ctx.params.pipe(decrypt);
}
}
};
