node.jssocket.iomoleculer

Getting `undefined` value even after attaching socket to `ctx` in `beforeCall()` hook in moleculer.io


I am using moleculerjs to handle microservices on the backend, and with one of the front-end applications I am handling the communication over sockets. To do that I am using moleculer.io. The problem I'm running into is that, even though I am attaching the socket to ctx in the onBeforeCall() hook, the socket is not there when I console.log ctx in the controller function.

My gateway looks like this (notice the socket is being added to the ctx object in the onBeforeCall() hook:

const SocketIOService = require("moleculer-io");

module.exports = {
  name: 'oas',
  mixins: [SocketIOService],

  settings: {
    port: 5000,
    io: {
      namespaces: {
        '/': {
          events: {
            'call': {
              aliases: {
                'auth.register': 'oas.controllers.auth.register'
              },
              whitelist: [
                '**',
              ],
              onBeforeCall: async function(ctx, socket, action, params, callOptions) { // before hook
                console.log('socket: ', socket); // This exists here
                ctx.socket = socket; // Here I attach the socket to the ctx object
              },
              onAfterCall: async function(ctx, socket, res) { // after hook
                // console.log('after hook', res)
                // res: The response data.
              }
            }
          }
        }
      }
    },

    events: {},

    actions: {}
  }
};

And my auth.service looks like this - notice the register() function that tries to access ctx.socket:

"use strict";

/**
 * @typedef {import('moleculer').Context} Context Moleculer's Context
 */

module.exports = {
    name: "oas.controllers.auth",

    /**
     * Settings
     */
    settings: {

    },

    /**
     * Dependencies
     */
    dependencies: [],

    /**
     * Actions
     */
    actions: {
    async register(ctx) {
      console.log('ctx.socket: ', ctx.socket); // This is undefined

      // Other code...
    },

    /**
     * Events
     */
    events: {

    },

    /**
     * Methods
     */
    methods: {

    },

    /**
     * Service created lifecycle event handler
     */
    created() {

    },

    /**
     * Service started lifecycle event handler
     */
    async started() {

    },

    /**
     * Service stopped lifecycle event handler
     */
    async stopped() {

    }
};

Here in the register() function that gets called, ctx.socket is undefined. What am I missing here? I assume that onBeforeCall() is designed to be used for exactly this kind of purpose, but perhaps I'm misunderstanding something.

Is there a different way I should or could approach this to ensure the socket is available in the called function? And just to clarify, the socket is available in the onBeforeCall() hook. I need to figure out how to make it available down the line.


Solution

  • In the end I found a way to do this. Instead of attaching the socket to ctx directly, which as @Icebob pointed out, you can't do, I was able to attach it ctx.meta, like so:

    onBeforeCall: async function(ctx, socket, action, params, callOptions) { // before hook
      ctx.meta.socket = socket;
    },
    

    By doing this I was able to successfully access the socket in my register() function.