{
    "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": 6,
                  "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"
      }
    }
  }
