All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nstream.adapter.common.patches.MemberPatch Maven / Gradle / Ivy

There is a newer version: 4.14.22
Show newest version
// Copyright 2015-2024 Nstream, inc.
//
// Licensed under the Redis Source Available License 2.0 (RSALv2) Agreement;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://redis.com/legal/rsalv2-agreement/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package nstream.adapter.common.patches;

import nstream.adapter.common.NstreamAgent;
import swim.api.SwimLane;
import swim.api.lane.CommandLane;
import swim.structure.Record;
import swim.structure.Selector;
import swim.structure.Value;
import swim.uri.Uri;
import swim.uri.UriPattern;

public class MemberPatch extends NstreamAgent {

  protected static final Uri JOIN_GROUP_LANE_URI = Uri.parse("joinGroup");
  protected static final Uri LEAVE_GROUP_LANE_URI = Uri.parse("leaveGroup");

  protected Uri currentGroupUri;

  public MemberPatch() {
  }

  /**
   * Get the value for 'memberLane' set in the agent properties.
   * This is the lane URI for the {@link GroupPatch} agents to downlink.
   * Default to 'latest'
   *
   * @return 'memberLane' from agent properties
   */
  protected String memberLane() {
    return getProp("memberLane").stringValue("latest");
  }

  /**
   * Get the value for 'groupUri' set in the agent properties.
   * This is the static node URI of the {@link GroupPatch} agent.
   *
   * @return 'groupUri' from agent properties
   */
  protected Uri groupUri() {
    final String uri = getProp("groupUri").stringValue(null);
    if (uri == null) {
      return null;
    }
    return Uri.parse(uri);
  }

  /**
   * Get the value for 'groupUriPattern' set in the agent properties.
   * This is the node URI pattern for the {@link GroupPatch} agents.
   *
   * @return 'groupUriPattern' from agent properties
   */
  protected UriPattern groupUriPattern() {
    final String uriPattern = getProp("groupUriPattern").stringValue(null);
    if (uriPattern == null) {
      return null;
    }
    return UriPattern.parse(uriPattern);
  }

  /**
   * Get the value for 'extractGroup' set in the agent properties.
   * This is the selector of the group from an event, to be used with {@link MemberPatch#groupUriPattern}.
   *
   * @return 'extractGroup' from agent properties
   */
  protected Value extractGroup() {
    final Value extractDef = getProp("extractGroup");
    if (extractDef.isDistinct() && extractDef instanceof Selector) {
      return extractDef;
    } else {
      return null;
    }
  }

  @SwimLane("addEvent")
  protected CommandLane addEvent = this.commandLane()
          .onCommand(v -> {
            trace("(MemberPatch) " + nodeUri()
                    + ".addEvent#onCommand(): value=" + v);
          });

  protected void handleEvent(final Value event) {
    final Uri newGroupUri = getGroupUriFromEvent(event);

    if (newGroupUri == null || !newGroupUri.equals(this.currentGroupUri)) {
      final Value payload = createGroupPatchPayload();
      leaveGroup(this.currentGroupUri, payload);
      joinGroup(newGroupUri, payload);
      this.currentGroupUri = newGroupUri;
    }
  }

  protected Uri getGroupUriFromEvent(final Value event) {
    final UriPattern groupUriPattern = groupUriPattern();
    if (groupUriPattern == null) {
      return null;
    }
    final Value extractDef = extractGroup();
    if (extractDef == null) {
      return null;
    }
    final String group = extractDef.evaluate(event).stringValue(null);
    if (group == null) {
      return null;
    }
    return groupUriPattern.apply(group);
  }

  protected Value createGroupPatchPayload() {
    return Record.create(2)
            .slot("uri", Uri.form().mold(nodeUri()).toValue())
            .slot("memberLane", memberLane());
  }

  protected void joinGroup(final Uri groupUri, final Value value) {
    if (groupUri != null) {
      command(groupUri, JOIN_GROUP_LANE_URI, value);
    }
  }

  protected void leaveGroup(final Uri groupUri, final Value value) {
    if (groupUri != null) {
      command(groupUri, LEAVE_GROUP_LANE_URI, value);
    }
  }

  @Override
  public void didStart() {
    info("(MemberPatch) " + nodeUri() + ": didStart");
    init();
  }

  protected void init() {
    if (groupUri() != null) {
      initStaticMember();
    } else if (groupUriPattern() != null && extractGroup() != null) {
      initDynamicMember();
    }
  }

  protected void initStaticMember() {
    joinGroup(groupUri(), createGroupPatchPayload());
  }

  protected void initDynamicMember() {
    this.addEvent.onCommand(this::handleEvent);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy