SOW and Subscribe

Imagine an application that displays real time information about the position and status of a fleet of delivery vans. When the application starts, it should display the current location of each of the vans along with their current status. As vans move around the city and post other status updates, the application should keep its display up to date. Vans upload information to the system by posting messages to the van_location topic, configured with a key of van_id on the AMPS server.

In this application, it is important to not only stay up-to-date on the latest information about each van, but to ensure all of the active vans are displayed as soon as the application starts. Combining a SOW with a subscription to the topic is exactly what is needed, and that is accomplished by the Client.sowAndSubscribe() method, or by executing a sow_and_subscribe command.

sowAndSubscribe()

First, let's look at an example that uses the convenience method:

const reportVanPosition = async client => {
  /**
  * sowAndSubscribe() method to begin receiving information about
  * all of the active delivery vans in the system. All of the vans
  * in the system now are returned as Message objects whose
  * `message.header.command()` method returns `sow`. New messages
  * coming in are returned as Message objects whose
  * `message.header.command()` method returns `p` (publish).
  */
  return client.sowAndSubscribe(

    // Message handler
    message => {
      const cmdName = message.header.command();
      if (cmdName === 'sow' || cmdName === 'p') {
        /**
        * For each of these messages we call addOrUpdateVan(),
        * that presumably adds the van to our application’s
        * display. As vans send updates to the AMPS server,
        * those are also received by the client because of the
        * subscription placed by sowAndSubscribe(). Our
        * application does not need to distinguish between
        * updates and the original set of vans we found via the
        * SOW query, so we use addOrUpdateVan() to display
        * the new position of vans as well.
        */
        addOrUpdateVan(message);
      }
      else if (cmdName === 'oof') {
        removeVan(message);
      }
    },

    'van_location',         // SOW Topic

    '/status = "ACTIVE"',   // Filter

    // Additional parameters
    {
      batchSize: 100,
      options: 'oof'
    }
  );
};

Execute a Command

Now we will look at an example that uses the Command interface with the Client.execute() method:

// Message Handler
const onVanPositionUpdate = message => {
  const cmdName = message.header.command();
  if (cmdName === 'sow' || cmdName === 'p') {
    addOrUpdateVan(message);
  }
  else if (cmdName === 'oof') {
    removeVan(message);
  }
};

const reportVanPosition = async client => {
  // Command object to execute
  const cmd = new Command('sow_and_subscribe');
  cmd.topic('van_location');
  cmd.filter('/status = "ACTIVE"');
  cmd.batchSize(100);
  cmd.options('oof');

  // Execute the command with the above message handler
  return client.execute(cmd, onVanPositionUpdate);
};

Notice that the two forms have the same result.

OOF Messages

In the above examples we specified the oof option to the command. Setting this option causes AMPS to send Out-of-Focus (OOF) messages for the topic. OOF messages are sent when an entry that was sent to us in the past no longer matches our query. This happens when an entry is removed from the SOW cache via a sow_delete operation, when the entry expires (as specified by the expiration time on the message or by the configuration of that topic on the AMPS server), or when the entry no longer matches the content filter specified. In our case, if a van's status changes to something other than ACTIVE, it no longer matches the content filter, and becomes out of focus. When this occurs, a message is sent with Command set to oof. We use OOF messages to remove vans from the display as they become inactive, expire, or are deleted.

Last updated