/**
   * Reads latest config from {@link ConfigService} for the given {@link Task} and caches it in that
   * {@link Task}. If config is found but can't be parsed, the {@link Task}'s {@code configured*}
   * fields will include the bad {@link Trigger} expression and a {@link BadConfigTrigger}. If
   * config simply can't be read at all, e.g. network outage, that will just be logged and the
   * {@link Task}'s config will be unchanged.
   *
   * <p>This also handles initialization of the {@link Task's} default {@link Trigger} <em>every
   * time</em>. Which means you can technically change the default and it will be picked up.
   *
   * @param task
   * @return
   * @throws BadTriggerConfigException if the default configuration for the given {@link Task} is
   *     broken. Exceptions during read of latest config from {@link ConfigService} are caught and
   *     handled.
   */
  protected void mergeLatestTriggerConfig(Task task) throws BadTriggerConfigException {

    // Null will mean "have no idea what the latest config would be or
    // if it even exists." Everything else will mean "either found good
    // config, use it, or found bad config and it's up to you what to do
    // with it."
    Pair<String, Trigger> newTriggerConfig = null;
    try {
      newTriggerConfig = readNewTriggerConfig(task.triggerExpressionConfigName);
    } catch (BadTriggerConfigException e) {
      LOGGER.warn(
          "Unable to parse task [{}] trigger config named [{}].",
          new Object[] {task.id, task.triggerExpressionConfigName, e});
      newTriggerConfig = new Pair<String, Trigger>(null, new BadConfigTrigger(e.getConfig(), e));
    } catch (RuntimeException e) {
      // Probably db connection or other systemic issue issue. Will end up
      // leaving this task alone.
      LOGGER.error(
          "Unable to read trigger config named [{}]. This"
              + " was probably a transient and/or systemic issue "
              + " rather than a parse issue.",
          task.triggerExpressionConfigName,
          e);
    }

    if (newTriggerConfig != null && newTriggerConfig.getSecond() == null) {
      // Really a programmer error but let's just quietly normalize to
      // simplify boolean expressions below.
      newTriggerConfig = null;
    }

    if (newTriggerConfig == null) {
      task.configuredTriggerExpression = null;
      task.configuredTrigger = null;
    } else {
      task.configuredTriggerExpression = newTriggerConfig.getFirst();
      task.configuredTrigger = newTriggerConfig.getSecond();
    }

    // Do this every time to avoid weird stuff from mis-use where the
    // expression and trigger don't match.
    task.defaultTrigger = parseTriggerConfig(task.defaultTriggerExpression);
  }