Events

Actions are the methods of a service. Theire call represents a remote procedure call (RPC).

If there are multiple instances of a service, the broker wil load balance the calls among the instances.

image

Call a action

To call a action, u can use the call method of the broker instance. The broker searchs for the service in the internal registry and calls it.

   const prom = broker.call(actionName, parameters, options)

The actionName is a dot seperated string. The first part of the string is the service name while the second part represents the action name.

Available calling options

Name Type Default Description
timeout Integer null Unique identifier for node. Have to be unique in namespace.
retries Integer null Namespace of nodes to segment your nodes on the same network.
nodeId String null If the nodeId is set the broker will call the action on the node direct.
meta Object null Defines the meta data of a call. It get transfered and merged with nested calls as well.
parentContext Object null Parent context instance
requestId String null Request ID or correlation ID. It appears in the metrics events.

Usage

Call action without parameters

    broker.call('posts.list')
        .then(result => console.log('Posts: ' + result))

Call action with parameters

    broker.call('posts.get', { id: 1 })
        .then(result => console.log('Post: ' + result))

Call action with options

    broker.call('posts.get', null, {
        timeout: 500,
        retries: 3
    })
    .then(result => console.log('Post: ' + result))

Direct Call action on a specific node

    broker.call('$node.health', null, {
        nodeId: 'node-1'
    })
    .then(result => console.log('Post: ' + result))

Meta data

Send meta informations to services with meta property. Access it via ctx.meta in action handlers.

    broker.createService({
        name: 'test',
        actions: {
            one (context) {
                return context.call('test.two', null, { meta: {
                    additionalInfo: 'Weave is great!'
                }})
            },
            two (context) {
                this.log.info(context.meta.additionalInfo)
            }
        }
    })

    broker.call('test.one')

Meta data are sent back to the service caller.

todo

    broker.createService({
        name: 'test',
        actions: {
            one (context) {
                await context.call('test.two', null, { meta: {
                    additionalInfo: 'Weave is great!'
                }})
                
            },
            two (context) {
                context.meta.b = 'two'
            }
        }
    })

    broker.call('test.one')

Streaming

Weave supports node.js streams. You can use it to transfer uploaded files from a gateway or encode/decode or compress/decompress streams.

Stream a file to a service

    const fileStream = fs.createReadStream(fileName)

    broker.call('storage.save', stream, { meta: { filename }})

Receive a file from a stream

The stream is passed in the params property of the context

    const fileStream = fs.createWriteStream(fileName);

    broker.createService({
        name: 'storage',
        actions: {
            save (context) {
                const fileStream = fs.createWriteStream(`/temp/${context.meta.filename}`)
                context.params.pipe(fileStream)                
            }
        }
    })

Action visibility

Actions have a visibility property to control the visibility of your action in your service structure.

The action has a visibility property to control the visibility & callability of service actions.

Available values:

  • published or null: public action. It can be called locally, remotely and can be published via API Gateway
  • public: public action, can be called locally & remotely but not published via API GW
  • protected: can be called only locally (from local services)
  • private: can be called only internally (via this.actions.xy() inside service)

The default value of visibility is null (published).

    broker.createService({
        name: 'storage',
        actions: {
            visibility: 'private',
            save: {
                handler (context) {
                const fileStream = fs.createWriteStream(`/temp/${context.meta.filename}`)
                context.params.pipe(fileStream)                
            }
        }
    })

Action hooks

Define action hooks to wrap certain actions coming from mixins. There are before, after and error hooks. Assign it to a specified action or all actions (*) in service. The hook can be a Function or a String. The latter must be a local service method name.

Before hook

    module.exports = {
        name: 'posts',
        hooks: {
            before: {
                // Global hook for all actions.
                // This hook will call the resolveLoggedInUsers method of the service.
                '*': 'resolveLoggedInUsers'
                create: [
                    function isAuthenticated (context) {
                        if (!context.user) {
                            throw new WeaveError('Not authenticated')
                        }
                    }
                ]
            }
        },
        methods: {
            async resolveLoggedInUsers (context) {
                if (context.meta.user) {
                    context.user = await ctx.call("users.get", { id: ctx.meta.user.id })
                }
            }
        }
    }

After hook

Error hook

Don't use [arrow functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions) on an options property or callback, such as `created: () => console.log(this.a)`. Since arrow functions are bound to the parent context, `this` will not be the service scope as you'd expect, often resulting in errors such as `Uncaught TypeError: Cannot read property of undefined` or `Uncaught TypeError: this.myMethod is not a function`.