{
  "Comment": "Start Metadata Consistency Checks for a given product",
  "StartAt": "Get Product Metadata",
  "States": {
    "Get Product Metadata": {
      "Comment": "Get product metadata, produce payload for MCC.",
      "Type": "Task",
      "Resource": "${get_product_metadata_lambda_arn}",
      "ResultSelector": {
        "globals": {
          "product_id.$": "$.product_id",
          "upc.$": "$.upc",
          "retries.$": "$.retries"
        },
        "product_metadata.$": "$.product_metadata"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "States.Timeout",
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException",
            "GraphQLError"
          ],
          "IntervalSeconds": 180,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Next": "Check Consistency"
    },
    "Check Consistency": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "Product Participations Check",
          "States": {
            "Product Participations Check": {
              "Type": "Task",
              "Resource": "${product_participations_check_lambda_arn}",
              "Retry": [
                {
                  "ErrorEquals": [
                    "States.Timeout",
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException",
                    "OperationalError"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 5,
                  "BackoffRate": 2
                }
              ],
              "End": true
            }
          }
        },
        {
          "StartAt": "Track Participations Check",
          "States": {
            "Track Participations Check": {
              "Type": "Task",
              "Resource": "${track_participations_check_lambda_arn}",
              "Retry": [
                {
                  "ErrorEquals": [
                    "States.Timeout",
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException",
                    "OperationalError"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 5,
                  "BackoffRate": 2
                }
              ],
              "End": true
            }
          }
        },
        {
          "StartAt": "Label Sound Recording Check",
          "States": {
            "Label Sound Recording Check": {
              "Type": "Task",
              "Resource": "${label_sound_recording_check_lambda_arn}",
              "Retry": [
                {
                  "ErrorEquals": [
                    "States.Timeout",
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 3,
                  "BackoffRate": 2
                }
              ],
              "End": true
            }
          }
        }
      ],
      "Next": "Inconsistencies Found?",
      "ResultSelector": {
        "possible_report_types": [
          "BAD_PRODUCT_PARTICIPATIONS",
          "BAD_TRACK_PARTICIPATIONS",
          "BAD_LABEL_SOUND_RECORDINGS"
        ],
        "found_inconsistency_types.$": "$[*].report.inconsistency_type",
        "reports.$": "$[*].report[?(@.inconsistency_type)]"
      },
      "ResultPath": "$.consistency_reports"
    },
    "Inconsistencies Found?": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.consistency_reports.found_inconsistency_types[0]",
          "IsPresent": true,
          "Next": "Check Retries"
        }
      ],
      "Default": "DDEX Check"
    },
    "DDEX Check": {
      "Type": "Task",
      "Resource": "${ddex_check_lambda_arn}",
      "Parameters": {
        "upc.$": "$.globals.upc"
      },
      "ResultSelector": {
        "success.$": "$"
      },
      "ResultPath": "$.DDEX_check",
      "Retry": [
        {
          "ErrorEquals": [
            "States.Timeout",
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException",
            "DDEXCheckUnknown"
          ],
          "IntervalSeconds": 60,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Next": "Success"
    },
    "Success": {
      "Type": "Pass",
      "End": true
    },
    "Check Retries": {
      "Type": "Task",
      "Resource": "${handle_retry_lambda_arn}",
      "Parameters": {
        "retries.$": "$.globals.retries"
      },
      "ResultSelector": {
        "updated_retry_count.$": "$.retries",
        "backoff_time_s.$": "$.backoff_time_s"
      },
      "ResultPath": "$.to_retry",
      "Next": "Prepare report payload"
    },
    "Prepare report payload": {
      "Type": "Pass",
      "Comment": "Prepares reports output and keeps global fields.",
      "Parameters": {
        "globals": {
          "retries.$": "$.to_retry.updated_retry_count",
          "backoff_time_s.$": "$.to_retry.backoff_time_s",
          "product_id.$": "$.globals.product_id",
          "upc.$": "$.globals.upc"
        },
        "consistency_reports": {
          "found_inconsistency_types": {
            "BAD_PRODUCT_PARTICIPATIONS.$": "States.ArrayContains($.consistency_reports.found_inconsistency_types, $.consistency_reports.possible_report_types[0])",
            "BAD_TRACK_PARTICIPATIONS.$": "States.ArrayContains($.consistency_reports.found_inconsistency_types, $.consistency_reports.possible_report_types[1])",
            "BAD_LABEL_SOUND_RECORDINGS.$": "States.ArrayContains($.consistency_reports.found_inconsistency_types, $.consistency_reports.possible_report_types[2])"
          },
          "reports.$": "$.consistency_reports.reports"
        }
      },
      "Next": "Fetch AR entities"
    },
    "Fetch AR entities": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "Any BAD_PRODUCT_PARTICIPATIONS?",
          "States": {
            "Any BAD_PRODUCT_PARTICIPATIONS?": {
              "Type": "Choice",
              "Default": "No incorrect product participations",
              "Choices": [
                {
                  "Variable": "$.consistency_reports.found_inconsistency_types.BAD_PRODUCT_PARTICIPATIONS",
                  "BooleanEquals": true,
                  "Next": "fetch-product-participations"
                }
              ]
            },
            "fetch-product-participations": {
              "Type": "Task",
              "Resource": "${fetch_product_participations_lambda_arn}",
              "InputPath": "$.consistency_reports",
              "ResultSelector": {
                "Records.$": "$.Records"
              },
              "ResultPath": "$.recordToSync",
              "Retry": [
                {
                  "ErrorEquals": [
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException",
                    "OperationalError"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 5,
                  "BackoffRate": 2
                }
              ],
              "End": true
            },
            "No incorrect product participations": {
              "Type": "Pass",
              "Parameters": {
                "globals.$": "$.globals",
                "recordToSync": {}
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "Any BAD_TRACK_PARTICIPATIONS?",
          "States": {
            "Any BAD_TRACK_PARTICIPATIONS?": {
              "Type": "Choice",
              "Default": "No incorrect track participations",
              "Choices": [
                {
                  "Variable": "$.consistency_reports.found_inconsistency_types.BAD_TRACK_PARTICIPATIONS",
                  "BooleanEquals": true,
                  "Next": "fetch-track-participations"
                }
              ]
            },
            "fetch-track-participations": {
              "Type": "Task",
              "Resource": "${fetch_track_participations_lambda_arn}",
              "InputPath": "$.consistency_reports",
              "ResultSelector": {
                "Records.$": "$.Records"
              },
              "ResultPath": "$.recordToSync",
              "Retry": [
                {
                  "ErrorEquals": [
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException",
                    "OperationalError"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 5,
                  "BackoffRate": 2
                }
              ],
              "End": true
            },
            "No incorrect track participations": {
              "Type": "Pass",
              "Parameters": {
                "globals.$": "$.globals",
                "recordToSync": {}
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "Any BAD_LABEL_SOUND_RECORDINGS?",
          "States": {
            "Any BAD_LABEL_SOUND_RECORDINGS?": {
              "Type": "Choice",
              "Default": "No incorrect label sound recordings",
              "Choices": [
                {
                  "Variable": "$.consistency_reports.found_inconsistency_types.BAD_LABEL_SOUND_RECORDINGS",
                  "BooleanEquals": true,
                  "Next": "fetch-track"
                }
              ]
            },
            "fetch-track": {
              "Type": "Task",
              "Resource": "${fetch_track_lambda_arn}",
              "InputPath": "$.consistency_reports",
              "ResultSelector": {
                "Records.$": "$.Records"
              },
              "ResultPath": "$.recordToSync",
              "Retry": [
                {
                  "ErrorEquals": [
                    "Lambda.ServiceException",
                    "Lambda.AWSLambdaException",
                    "Lambda.SdkClientException",
                    "Lambda.TooManyRequestsException",
                    "OperationalError"
                  ],
                  "IntervalSeconds": 30,
                  "MaxAttempts": 5,
                  "BackoffRate": 2
                }
              ],
              "End": true
            },
            "No incorrect label sound recordings": {
              "Type": "Pass",
              "Parameters": {
                "globals.$": "$.globals",
                "recordToSync": {}
              },
              "End": true
            }
          }
        }
      ],
      "ResultSelector": {
        "globals.$": "$[0].globals",
        "sync_step.$": "$[*].recordToSync[?(@.Records)]"
      },
      "Next": "Send for Resync"
    },
    "Send for Resync": {
      "Comment": "Trigger lambda-kinesis-to-neo4j for each batch of resync Records.",
      "Type": "Map",
      "MaxConcurrency": 1,
      "ItemsPath": "$.sync_step",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "kinesis-to-neo4j",
        "States": {
          "kinesis-to-neo4j": {
            "Type": "Task",
            "Resource": "${lambda_kinesis_to_neo4j_arn}",
            "ResultPath": "$.sync_result",
            "Retry": [
              {
                "ErrorEquals": [
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException",
                  "TransientError"
                ],
                "IntervalSeconds": 60,
                "MaxAttempts": 4,
                "BackoffRate": 2
              }
            ],
            "End": true
          }
        }
      },
      "ResultSelector": {
        "sync_lambda_statuses.$": "$[*].sync_result.status"
      },
      "ResultPath": "$.sync_step",
      "Next": "Backoff Wait"
    },
    "Backoff Wait": {
      "Type": "Wait",
      "SecondsPath": "$.globals.backoff_time_s",
      "Next": "Prepare new run"
    },
    "Prepare new run": {
      "Type": "Pass",
      "Parameters": {
        "product_id.$": "$.globals.product_id",
        "retries.$": "$.globals.retries"
      },
      "Next": "Get Product Metadata"
    }
  }
}
