call_end

    • chevron_right

      Erlang Solutions: MongooseIM 6.5: Open for Integration

      news.movim.eu / PlanetJabber • Yesterday - 12:04 • 6 minutes

    MongooseIM 6.5: Open for Integration is now available. This release focuses on easier integration with your applications while continuing to deliver a scalable and reliable XMPP-based messaging server.

    For such integration, you can use the Admin or User GraphQL API. Another example is the interaction of MongooseIM with a database. A relational DB such as PostgreSQL, MySQL or CockroachDB can be used to store user accounts, message archives, multi-user chatrooms, publish-subscribe nodes, cluster nodes and much more. Other supported databases and storage services include Cassandra or Elastic Search for message archive, Redis for user sessions and LDAP for authentication.

    You can see the complete list in our documentation.
    There is another important way to let MongooseIM interact with your distributed system: event pushing . The core of this functionality is the event pusher module, which can push selected events to services like Amazon SNS , RabbitMQ or MongoosePush . In the most recent release 6.5.0, we have improved the event pushing mechanism, focusing on better integration with RabbitMQ.

    Event pushing in MongooseIM 6.5.0

    The diagram below explains the event pushing architecture in the latest version of MongooseIM:

    MongooseIM 6.5:


    Events utilize the concept of hooks and handlers . Currently, events are triggered for a few selected hooks, e.g. when a user logs in/out or sends/receives a message. There are almost 140 different hooks defined in MongooseIM though, so there is much room for adding custom events. A module called mod_event_pusher_hook_translator handles the selected hooks, creating events and passing them to the main event pusher API function, mod_event_pusher:push_event/2 .

    Then, a hook called push_event is triggered, leveraging the hooks-and-handlers mechanism for the second time. This hook is handled by configurable service-specific backend modules, such as:

    • sns – for sending notifications to Amazon SNS,
    • rabbit – for sending notifications to RabbitMQ or CloudAMQP,
    • http – for sending notifications to a custom service,
    • push – for sending push notifications to mobile devices with the help of MongoosePush.

    These modules act as interfaces to the corresponding external services. A key feature of this design is its extensibility. For example, one can easily add a kafka backend module that would deliver the events to Apache Kafka as shown on the diagram above.

    Push notifications

    Let’s focus on the push module as it is a bit more complex. In general, it uses hooks and handlers once again – the push_notifications hook in particular. In order to actually deliver push notifications to a mobile device, a module called mod_push_service_mongoosepush handles that hook by sending the notifications to a separate service called MongoosePush . Finally, MongoosePush will dispatch the notification request and send the notifications to configured services such as APNs or Google FCM .


    Each stage of this process is configurable and extensible. Firstly, we have assumed that a virtual pubsub host is used, but there is also an option to use a separate pubsub node for push notifications as described in XEP-0357: Push Notifications , adding another step before running the push_notifications hook. Speaking about that hook, you can implement your own module handling it by calling your own service instead of MongoosePush. Additionally, if you need to extend the notification logic with additional filtering and processing, you can implement a plugin module to mod_event_pusher_push .

    Pushing events to RabbitMQ

    As the RabbitMQ backend module was improved and made production-ready in version 6.5.0, let’s use it as an example of how you can easily configure MongooseIM to push events to RabbitMQ. The simplest way to demonstrate this is with Docker containers. Firstly, we need a container for RabbitMQ:

    docker network create example
    docker run --rm -d --network example --name rabbit rabbitmq:management
    

    The management tag is used because we will need the rabbitmqadmin command. The default port 5672 will be used by MongooseIM. The connection is unencrypted for simplicity, but it is recommended to use TLS in a production environment.


    As the next step, let’s obtain the default mongooseim.toml configuration file from the MongooseIM 6.5.0 image:

    docker create --name mongooseim erlangsolutions/mongooseim:6.5.0
    docker cp mongooseim:/usr/lib/mongooseim/etc/mongooseim.toml .
    docker rm mongooseim
    

    This default configuration file uses the Mnesia internal database. Although we recommend using CETS and a relational database instead of Mnesia, in this example we will try to keep it as simple as possible – so you only need to add the following to mongooseim.toml :

    [outgoing_pools.rabbit.event_pusher]
      connection.host = "rabbit"
    
    [modules.mod_event_pusher.rabbit]
      chat_msg_exchange = {}
    
    

    The first section configures a pool of connections to RabbitMQ with the default settings , while the second one enables the event pusher module with the rabbit backend, and includes chat_msg_exchange in order to enable the exchange for one-to-one chat messages (called chat_msg by default – see all options ). If you are wondering where to add these lines to mongooseim.toml – you can put them anywhere, but it is recommended to group them by section (e.g. outgoing_pools, modules etc.) for readability.

    Having the configuration file ready, we can start the MongooseIM container:

    docker run --rm -d --network example -e JOIN_CLUSTER=false \
      -v ./mongooseim.toml:/usr/lib/mongooseim/etc/mongooseim.toml \
      --name mongooseim erlangsolutions/mongooseim:6.5.0
    

    After it starts, the chat_msg exchange should be automatically created in RabbitMQ. In order to see its messages, we need to bind a queue to it.

    docker exec -it rabbit rabbitmqadmin declare queue --name recv
    docker exec -it rabbit rabbitmqadmin declare binding --source chat_msg --destination recv --destination-type queue --routing-key "*.chat_msg_recv"
    
    

    The routing key *.chat_msg_recv means that only the events for received messages will be routed – in this example we skip all events for sent messages. Now let’s create two user accounts in MongooseIM:



    docker exec -it mongooseim mongooseimctl account registerUser --username alice --domain localhost --password secret
    docker exec -it mongooseim mongooseimctl account registerUser --username bob --domain localhost --password secret
    

    You should get the “User … successfully registered” message for each of them. Next, send the message from alice to bob – we could do that with an XMPP client , but the simplest way here is to use the admin CLI:

    docker exec -it mongooseim mongooseimctl stanza sendMessage --from alice@localhost --to bob@localhost --body hello
    

    Now we can check if the message event was sent to our RabbitMQ queue:


    docker exec -it rabbit rabbitmqadmin get messages --queue recv
    

    The payload should be:

    {"to_user_id": "bob@localhost", "from_user_id": "alice@localhost", "message": "hello"}
    

    This simple example shows how easy it is to extend the functionality of MongooseIM beyond XMPP – as soon as you have the events in a message queue like RabbitMQ, you can perform various actions on them such as calculating statistics for billing purposes, performing analytics or storing them in an external database separate from MongooseIM.

    Summary

    The most important improvement in MongooseIM 6.5.0 is the production-ready integration with RabbitMQ, allowing external services to process the events from the server. It is worth noting that the mechanism is highly extensible – you can craft such extensions yourself, but of course don’t hesitate to contact us if you are considering using it in your business – we will be happy to help you install, configure, maintain, and – if necessary – customise it to fit your particular needs. For more information about the latest improvements, see the release notes .

    The post MongooseIM 6.5: Open for Integration appeared first on Erlang Solutions .