Page tree
Skip to end of metadata
Go to start of metadata

Checklist

  • User Stories Documented
  • User Stories Reviewed
  • Design Reviewed
  • APIs reviewed
  • Release priorities assigned
  • Test cases reviewed
  • Blog post

Introduction 

Composite Trigger provides the capability of chaining multiple Triggers together with logical operations AND and OR

Goals

Provide Composite Trigger API and backend support

User Stories 

  • A user wants to trigger pipeline B when pipeline A failed and dataset D has 1 new partition
  • A user wants to trigger workflow A every hour, or when workflow B completes and Pipeline C fails

Design

New Application configuring API will be provided to set trigger for schedule with ProtoTrigger object. New trigger interface SatisfiableTrigger will be created to provide a method to check whether a trigger is satisfied and a method to provide trigger key used to index the schedule. SatisfiableTrigger will be implemented by all existing triggers. Composite triggers AND trigger and OR trigger will be implemented in ProtoTrigger and in classes implementing SatisfiableTrigger.  Every composite trigger is composed of two triggers, which can be composite trigger or other types of triggers.

Please refer to the API changes session see how the new API and composite trigger classes will be used.

API changes

ScheduleBuilder
/**
 * Creates a schedule with a given trigger
 * 
 * @param trigger the trigger to be contained in the schedule
 * @return a {@link ScheduleCreationBuilder} for creating
 *         an immutable {@link co.cask.cdap.internal.schedule.ScheduleCreationSpec}
 */
ScheduleCreationBuilder onTrigger(Trigger trigger);
ProtoTrigger
public abstract static class AbstractCompositeTrigger extends ProtoTrigger {
  protected final Trigger[] triggers;

  public AbstractCompositeTrigger(Type type, Trigger... triggers) {
    super(type);
    this.triggers = triggers;
    validate();
  }

  public Trigger[] getTriggers() {
    return triggers;
  }
 
...
 
  }

  @Override
  public void validate() {
    ProtoTrigger.validateNotNull(getLeftTrigger(), "left trigger");
    ProtoTrigger.validateNotNull(getRightTrigger(), "right trigger");
  }
}

/**
 * Represents an AND trigger in REST requests/responses.
 */
public static class AndTrigger extends AbstractCompositeTrigger {
  public AndTrigger(Trigger... triggers) {
    super(Type.AND, triggers);
  }
}

/**
 * Represents an OR trigger in REST requests/responses.
 */
public static class OrTrigger extends AbstractCompositeTrigger {
  public OrTrigger(Trigger... triggers) {
    super(Type.OR, triggers);
  }
}

 

 

SatisfiableTrigger
/**
 * A Trigger that schedules a ProgramSchedule, when all internal triggers are satisfied.
 */
public class AndTrigger extends AbstractCompositeTrigger implements SatisfiableTrigger {

  public AndTrigger(Trigger... triggers) {
    super(Type.AND, triggers);
  }

  @Override
  public boolean isSatisfied(List<Notification> notifications) {
    for (Trigger trigger : triggers) {
      if (!((SatisfiableTrigger) trigger).isSatisfied(notifications)) {
        return false;
      }
    }
    return true;
  }
}

 

OrTrigger will be almost the same as AndTrigger except as soon as one trigger is satisfied in its triggers, it returns true for isSatisfied(List<Notification> notifications) method

UI Impact or Changes

  • UI need to display Composite trigger as a logical expression composed of non-composite triggers

Test Scenarios

Test IDTest DescriptionExpected Results
1ProgramStatusTrigger AND TimeTriggerLogical expression is evaluated correctly and trigger keys returned include all trigger keys from individual triggers
2(ProgramStatusTrigger AND TimeTrigger) OR (TimeTrigger AND PartitionTrigger)Logical expression is evaluated correctly and trigger keys returned include all trigger keys from individual triggers
3(ProgramStatusTrigger OR TimeTrigger) AND (TimeTrigger OR PartitionTrigger)Logical expression is evaluated correctly and trigger keys returned include all trigger keys from individual triggers
4.StreamSizeTrigger AND (TimeTrigger AND PartitionTrigger)Logical expression is evaluated correctly and trigger keys returned include all trigger keys from individual triggers

Releases

Release 4.3.0

 

 

 

  • No labels

4 Comments

  1. I don't get how this method will be used in conjunction with existing triggers:

    ScheduleCreationBuilder withTrigger(Trigger trigger);

     

    I thought the trigger classes are not exposed to the user, so if they want to trigger by time for example, they would use the method triggerByTime. What would they need to do to be able to use this method?

    1. ProtoTrigger is exposed to users, but currently ProtoTrigger is only used to represent trigger in REST request/response.

  2. Why does the Composite trigger need to expose the following two methods? getLeftTrigger and getRightTrigger? Shouldn't that remain an internal detail, and the composite trigger only expose whether its satisfied or not?

    1. yes, that's true. I can turn them to protected or actually just remove them.