Deep-Dive-of-Glee,-The-AsyncAPI-Framework

Deep Dive Into Glee, the AsyncAPI Framework

Posted in

Glee, the AsyncAPI framework that will make you smile again, is a framework designed to create server-side applications through the AsyncAPI specification.

Being specification-first, Glee allows for creating server-side applications that follow a specification that defines the form and function. That’s the great hope of Glee, but how well does it do this?

Below, we’ll see how to get up and running with Glee, explore the structure of Glee, and how it supports AsyncAPI-driven development.

Glee: Making Development Easy (And Sensible)

Clearly, the developers behind Glee had a specific idea in mind while developing this implementation. Glee is designed to be robust and sensible at the beginning, with enough variables and configuration options to turn it into your particular desire.

Right off the bat, starting with Glee is quite simple. Glee can be created by using the AsyncAPI CLI with the following command:

asyncapi new glee

Deceptively simple. But Glee gets most of its usability in its specific application structure and the configuration that underpins it all.

The Glee Superstructure

Glee has a handful of required and optional files and folders that can be generated when first using it. First, let’s look at the required elements.

Required Items

Functions

The functions directory is exactly what you would think — a collection of all the functions that Glee executes when receiving a message. Functions are the backbone of Glee, and all of its functionality depends on these functions and their attributes. When Glee receives an event, a function is triggered, resulting in an exported async Node.js function. This event has a payload, a header, the channel, and the broker serverName.

As described in the documentation:

Attribute Description
payload The payload/body of the received event.
headers The headers/metadata of the received event.
channel The name of the channel/topic from which the event was read.
serverName The name of the server/broker from which the event was received.

From here, functions could return an object to instruct Glee as to the next steps, including how to send and reply.

asyncapi.yaml

This file, which is also required, is used to guide this object-driven instruction. Put simply, there are a set of public operations defined within this file that set the specific function bound to a given operation. More broadly, this file can be seen as a sort of guidebook for interaction between the functions and the Glee framework.

package.json

Another required file, this is the package definition file.

Optional Items

There are three optional elements, each of which delivers additional features to Glee.

lifecycle

The first of these optional items is the lifecycle directory. This directory contains all the possible lifecycle functions that can be executed given a set of events. What makes this powerful is that the lifecycle directory allows for proactive messaging as opposed to responsive messaging.

While event-driven architectures are designed to respond to an event rather than trigger one, there are times when the internal system has to send a message or do a certain thing in response to a current state. Glee accomplishes that through a handful of potential events, including:

onConnect
onReconnect
onDisconnect
onServerReady
onServerConnectionOpen
onServerConnectionClose

Any of these events can trigger a specific action across the entire system. Additionally, Glee provides a lifecycle restriction constant both for servers and channels, ensuring that only events with a specific origination are handled through this process.

.env

The .env file offers a set of environment variables that allow customization. These variables will enable you to:

  • Load a specific set of servers on startup through the GLEE_SERVER_NAMES variable,
  • Denote what certificates are to be used when establishing connections through GLEE_SERVER_CERTS, and
  • Denote the specific values that are used for each server variable with GLEE_SERVER_VARIABLES.

This provides an additional layer of customization that allows for a very specific environmental set to be reflected in the Glee instance. While this is not required as Glee works right out of the box, this environmental variable system enables more complex server constructs to be accurately represented.

glee.config.js

This configuration file is where a lot of Glee’s potential is held. Glee allows substantial configuration to change how it behaves, allowing for more complex data flows and superstructures than the default instance.

There are a handful of basic configuration options which allow the developer to set a Glee directory, set the lifecycle event path, and so forth. There’s additionally an optional toggle for documentation and a path specification for said documentation. All of this is to be expected and is much more a custom pathing option than anything else.

Where Glee starts getting a bit more interesting is in the provision of groups of configurations for custom or external systems. Firstly, Glee provides a few optional methods for connecting to Websocket Servers. More to the point, these options allow for connection to a set of adapters and a custom adapter setting for in-house options. The same applies to the Cluster options, the MQTT system, and the Kafka configuration collection.

In essence, this bundle of configuration options allows Glee to be more extensible for specific builds and instances than it otherwise would be. Too often, these kinds of solutions are built for a particular use case, so it’s great that Glee offers a good amount of customization to represent more complex builds and instances.

Example Implementations

Glee helpfully provides some example builds to represent what it can do. Perhaps the most notable example is the ShrekApp build based upon an AsyncAPI post about WebSocket use cases. In this build, a chatbot has been trained to respond as if it were Shrek — and that’s precisely what it does.

/* eslint-disable no-undef */

import fetch from 'node-fetch'

export default async function (event) {
  const chatMessage = event.payload
  const messageToShrek = chatMessage ? encodeURIComponent(chatMessage) : ''
  const defaultAnswer = 'Shrek is out sorry. He \'s busy rescuing the princess.'
  let shrekAnswer = defaultAnswer
  let botAnswer

  try {
    botAnswer = await fetch(`https://api.wit.ai/message?q=${messageToShrek}`, {
      headers: { Authorization: `Bearer ${process.env.CHATBOT_TOKEN}` }
    })
  } catch (e) {
    throw new Error(`Having issues communicating with the bot: ${e}`)
  }

  if (botAnswer) {
    const wrongQuestionAnswer = 'Is it you Donkey!? Ask a better question!'
    const answerObject = await botAnswer.json()
    if (answerObject.error) {
      throw new Error(answerObject.error)
    }
    let firstTraitValue

    for (const [, v] of Object.entries(answerObject.traits)) {
      firstTraitValue = v[0].value
      break
    }

    shrekAnswer = firstTraitValue ? firstTraitValue : wrongQuestionAnswer
  }
  console.log(`Answered with: ${shrekAnswer}`)
  
  return {
    reply: [
      {
        payload: shrekAnswer
      }
    ]
  }
}

This build uses a handful of set functions to accomplish a flow based on the state of the question. Based upon the question and the server state, a response could respond with the fact that Shrek is busy, or, in the case of a bad question, a question as to whether or not the user is, in fact, Donkey.

A more interesting real-life use case is the Flight Management example. This example is designed to store data through a backend JSON server built in Glee. This server contains the flights that have been loaded into the server as well as the relevant data for each one. From here, a Board renders the list of flights for a specific airport using an airport code format, allowing users to find and monitor particular flights. There is also an Admin Front-End that allows for the editing of flight info.

Notably, this example utilizes some graphical elements and formatting to present a real-life test case for a user-facing system. While the Shrek example is funny, the flight management example is more practical and could be replicated for other use cases. It could be used to drive any number of event-driven update boards, including calendar schedules, patient status for medical practices, and much more.

Conclusion

Glee is a powerful tool for building event-driven, server-side applications, but its extensibility and support for configuration make it a powerful tool for many paradigms. While Glee will obviously benefit from additional time for development, iteration, and adoption, it is currently a powerful and effective option for anyone using AsyncAPI as a development paradigm.

What do you think of Glee? Let us know in the comments below!