Agent Relationship

Nstream provides ‘Group’ and ‘Member’ patches that greatly facilitate grouping agents by some common property. This guide demonstrates how to group agents and maintain a join lane downlinking it’s members.

Dependencies

Gradle

implementation 'io.nstream:nstream-adapter-common:4.11.19'

Maven

<dependency>
  <groupId>io.nstream</groupId>
  <artifactId>nstream-adapter-common</artifactId>
  <version>4.11.19</version>
  <type>module</type>
</dependency>

Config

Most cases of grouping agents can be implemented using config only in the server.recon. This involves adding MemberPatch and GroupPatch to the relevant nodes and setting some simple parameters.

Group Patch

The GroupPatch agent contains a JoinValueLane named agents that will downlink the specified lane of its members. Simply define a node that includes the GroupPatch agent:

# server.recon
...
space: @fabric {
  @plane(class:"nstream.adapter.runtime.AppPlane")

  # Domain Agents
  
  # 'Country' group agent that will be used to group 'sites'
  @node {
    pattern: "/country/:country"
    @agent(class: "nstream.adapter.common.patches.GroupPatch")
  }

}

Member Patch

The MemberPatch agent provides functionality to join and leave group agents (GroupPatchs).

Static Groupings

The group a member belongs to will sometimes be constant throughout the lifecycle of the server - for example a stationary site will always be a member of the region/state/country. In this case, we can provide a static groupUri in the config of the MemberPatch.

# server.recon
...

  # Domain Agents
  
  @node {
    uri: "/country/:country"
    @agent(class: "nstream.adapter.common.patches.GroupPatch")
  }
  
  @node {
    pattern: "/site/:id"
    @agent(class: "nstream.adapter.common.patches.LatestValuePatch")
    @agent(class: "nstream.adapter.common.patches.MemberPatch") {
      groupUri: "/country/US"   # Static node URI of the group to join
    }
  }

Dynamic Groupings

Some members will leave and join groups depending on some changing value or state. For this case, we define two properties:

# server.recon
...

  # Domain Agents
  
  @node {
    uri: "/country/:country"
    @agent(class: "nstream.adapter.common.patches.GroupPatch")
  }

  @node {
    pattern: "/site/:id"
    @agent(class: "nstream.adapter.common.patches.LatestValuePatch")
    @agent(class: "nstream.adapter.common.patches.MemberPatch") {
      groupUriPattern: "/country/:country"  # URI pattern of the group
      extractGroup: $country                # Selector to extract the 'country' from an event
    }
  }

Member Patch Config Options

Name Description Required Default Example
memberLane Lane the group’s join lane will downlink true latest status
groupUri Node URI of group node required if not using groupUriPattern   /country/US
groupUriPattern URI pattern of group nodes required if not using groupUri   /country/:country
extractGroup Value selector of group from event required when using groupUriPattern   $country

Common Variations

Complex Group URIs

If the node URI of the group is more complex than applying a single value to a URI pattern then it may be necessary to override and add some custom logic.

// ZoneMemberAgent.java
// import ...

public class ZoneMemberAgent extends MemberPatch { 
    
  @Override
  protected Uri getGroupUriFromEvent(final Value event) {
    return
        groupUriPattern() // From agent properties '/country/:country/zone/:zone'
            .apply(
                event.get("country").stringValue(),
                event.get("zone").stringValue()    
            );
  }  
} 

Remember to update the server.recon to use the new agent just created (instead of the base MemberPatch).


Nstream is licensed under the Redis Source Available License 2.0 (RSALv2).