handleJobStatusChange = async (framework) => {
  // each framework may have multiple state change alerts
  const infos = [];
  logger.info(`Handling job state change of job ${framework.jobName} ...`);
  if (
    framework.notificationAtRunning &&
    !framework.notifiedAtRunning &&
    ["RUNNING", "SUCCEEDED"].includes(framework.state)
  ) {
    infos.push({
      stateToNotify: "RUNNING",
      fieldToUpdate: "notifiedAtRunning",
      valToUpdate: true,
    });
  }
  if (
    framework.notificationAtSucceeded &&
    !framework.notifiedAtSucceeded &&
    framework.state === "SUCCEEDED"
  ) {
    infos.push({
      stateToNotify: "SUCCEEDED",
      fieldToUpdate: "notifiedAtSucceeded",
      valToUpdate: true,
    });
  }
  if (
    framework.notificationAtFailed &&
    !framework.notifiedAtFailed &&
    framework.state === "FAILED"
  ) {
    infos.push({
      stateToNotify: "FAILED",
      fieldToUpdate: "notifiedAtFailed",
      valToUpdate: true,
    });
  }
  if (
    framework.notificationAtStopped &&
    !framework.notifiedAtStopped &&
    framework.state === "STOPPED"
  ) {
    infos.push({
      stateToNotify: "STOPPED",
      fieldToUpdate: "notifiedAtStopped",
      valToUpdate: true,
    });
  }
  if (
    framework.notificationAtRetried &&
    framework.notifiedAtRetried < framework.retries
  ) {
    infos.push({
      stateToNotify: "RETRIED",
      fieldToUpdate: "notifiedAtRetried",
      valToUpdate: framework.retries,
    });
  }

  try {
    // generate & send alerts for one job
    const alerts = infos.map((info) =>
      getJobStatusChangeAlert(
        framework.jobName,
        framework.userName,
        info.stateToNotify,
        framework.retries
      )
    );
    await sendAlerts(alerts);

    // update Framework table for one job
    const updateInfos = {};
    infos.forEach((info) => {
      updateInfos[info.fieldToUpdate] = info.valToUpdate;
    });
    await updateFrameworkTable(framework, updateInfos);
  } catch (error) {
    logger.error(
      `Failed when handle job status change for job ${framework.jobName}:`,
      error
    );
  }
}
Implementation of job-status-change-notification.