{
  "Comment": "Bulk Session Ingest Queue Step Function",
  "StartAt": "BeginExecution",
  "States": {
    "BeginExecution": {
      "Type": "Task",
      "Resource": "${begin_execution_lambda_arn}",
      "Parameters": {
        "execution_arn.$": "$$.Execution.Id",
        "bulk_session_id.$": "$.bulk_session_id",
        "bulk_session_ingestion_id.$": "$.bulk_session_ingestion_id",
        "identity_uuid.$": "$.identity_uuid",
        "assets_required.$": "$.assets_required",
        "submit_products.$": "$.submit_products",
        "send_notifications.$": "$.send_notifications",
        "ingestion_status.$": "$.ingestion_status",
        "correlation_id.$": "$.correlation_id",
        "bucket.$": "$.bucket",
        "key.$": "$.key"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "NetworkException",
            "ReadTimeout",
            "States.Timeout",
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "BackoffRate": 2,
          "IntervalSeconds": 60,
          "MaxAttempts": 3,
          "Comment": "Retry 3 times with a backoff rate of 2"
        },
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "BackoffRate": 1,
          "IntervalSeconds": 300,
          "MaxAttempts": 1,
          "Comment": "Retry once on any failure"
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "Next": "SetIngestionStatusFailure",
          "ResultPath": "$.exception",
          "Comment": "Error after retry"
        }
      ],
      "Next": "PrepareBulkMetadata"
    },
    "PrepareBulkMetadata": {
      "Type": "Task",
      "Resource": "${prepare_metadata_lambda_arn}",
      "Retry": [
        {
          "ErrorEquals": [
            "PrepareMetadataException",
            "NetworkException",
            "ReadTimeout",
            "States.Timeout",
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "BackoffRate": 2,
          "IntervalSeconds": 60,
          "MaxAttempts": 3,
          "Comment": "Retry 3 times with a backoff rate of 2"
        },
        {
          "ErrorEquals": [
            "HydrationException"
          ],
          "MaxAttempts": 0,
          "Comment": "Don't retry"
        },
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "BackoffRate": 1,
          "IntervalSeconds": 300,
          "MaxAttempts": 1,
          "Comment": "Retry once on any failure"
        }
      ],
      "Catch": [
        {
          "ErrorEquals": [
            "HydrationException"
          ],
          "Next": "SetIngestionStatusFailure",
          "ResultPath": "$.exception",
          "Comment": "Hydration has failed due to inconsistent data"
        },
        {
          "ErrorEquals": [
            "States.ALL"
          ],
          "Next": "SetIngestionStatusFailure",
          "ResultPath": "$.exception",
          "Comment": "Error after retry"
        }
      ],
      "Next": "ProcessBulkProducts"
    },
    "SetIngestionStatusFailure": {
      "Type": "Pass",
      "Parameters": {
        "bulk_session_id.$": "$.bulk_session_id",
        "bulk_session_ingestion_id.$": "$.bulk_session_ingestion_id",
        "identity_uuid.$": "$.identity_uuid",
        "assets_required.$": "$.assets_required",
        "submit_products.$": "$.submit_products",
        "send_notifications.$": "$.send_notifications",
        "correlation_id.$": "$.correlation_id",
        "ingestion_status": "failure",
        "bucket.$": "$.bucket",
        "key.$": "$.key",
        "exception.$": "$.exception"
      },
      "Next": "FailureBulkState"
    },
    "ProcessBulkProducts": {
      "Type": "Map",
      "Label": "Map",
      "ResultPath": null,
      "Next": "SuccessBulkState",
      "MaxConcurrency": 25,
      "ToleratedFailurePercentage": 100,
      "ItemReader": {
        "ReaderConfig": {
          "InputType": "JSON"
        },
        "Resource": "arn:aws:states:::s3:getObject",
        "Parameters": {
          "Bucket.$": "$.bucket",
          "Key.$": "$.key"
        }
      },
      "ItemSelector": {
        "bulk_session_id.$": "$.bulk_session_id",
        "bulk_session_ingestion_id.$": "$.bulk_session_ingestion_id",
        "identity_uuid.$": "$.identity_uuid",
        "execution_arn.$": "$.execution_arn",
        "assets_required.$": "$.assets_required",
        "submit_products.$": "$.submit_products",
        "send_notifications.$": "$.send_notifications",
        "ingestion_status.$": "$.ingestion_status",
        "correlation_id.$": "$.correlation_id",
        "product_info.$": "$$.Map.Item.Value.product_info"
      },
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "DISTRIBUTED",
          "ExecutionType": "STANDARD"
        },
        "StartAt": "SetParticipants",
        "States": {
          "SetParticipants": {
            "Type": "Task",
            "Resource": "${set_participants_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "RetryException",
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry"
              }
            ],
            "Next": "SetProject"
          },
          "SetProject": {
            "Type": "Task",
            "Resource": "${set_project_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "DuplicateProjectCodeException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 2,
                "Comment": "Race condition when two lambdas try to create the same project"
              },
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry"
              }
            ],
            "Next": "SetProduct"
          },
          "SetProduct": {
            "Type": "Task",
            "Resource": "${set_product_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "CreateProductException"
                ],
                "MaxAttempts": 0,
                "Comment": "Don't retry"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry"
              }
            ],
            "Next": "SetTracks"
          },
          "SetTracks": {
            "Type": "Task",
            "Resource": "${set_tracks_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry"
              }
            ],
            "Next": "SetCarveouts"
          },
          "SetCarveouts": {
            "Type": "Task",
            "Resource": "${set_carveouts_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry"
              }
            ],
            "Next": "SetMainReleaseDate"
          },
          "SetMainReleaseDate": {
            "Type": "Task",
            "Resource": "${set_release_dates_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "InvalidDataException"
                ],
                "MaxAttempts": 0,
                "Comment": "Don't retry"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Error after retry or invalid input"
              }
            ],
            "Next": "HandleMetadataSuccess"
          },
          "HandleMetadataSuccess": {
            "Type": "Task",
            "Resource": "${handle_metadata_success_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              },
              {
                "ErrorEquals": [
                  "InvalidDataException"
                ],
                "MaxAttempts": 0,
                "Comment": "Don't retry"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception"
              }
            ],
            "Next": "EnqueueCopyArtwork"
          },
          "EnqueueCopyArtwork": {
            "Type": "Task",
            "Resource": "${enqueue_copy_artwork_lambda_arn}",
            "Next": "ProcessTrackAssets",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 3,
                "Comment": "Retry 3 times with a backoff rate of 2"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception"
              }
            ]
          },
          "ProcessTrackAssets": {
            "Type": "Parallel",
            "Branches": [
              {
                "StartAt": "PassContextToOutput",
                "States": {
                  "PassContextToOutput": {
                    "Type": "Pass",
                    "End": true
                  }
                }
              },
              {
                "StartAt": "TrackAssetIterator",
                "States": {
                  "TrackAssetIterator": {
                    "Type": "Map",
                    "MaxConcurrency": 1,
                    "ItemsPath": "$.product_info.tracks",
                    "Parameters": {
                      "bulk_session_id.$": "$.bulk_session_id",
                      "bulk_session_ingestion_id.$": "$.bulk_session_ingestion_id",
                      "identity_uuid.$": "$.identity_uuid",
                      "assets_required.$": "$.assets_required",
                      "submit_products.$": "$.submit_products",
                      "ingestion_status.$": "$.ingestion_status",
                      "send_notifications.$": "$.send_notifications",
                      "correlation_id.$": "$.correlation_id",
                      "product_info.$": "$.product_info",
                      "track": {
                        "tuid.$": "$$.Map.Item.Value.tuid",
                        "asset.$": "$$.Map.Item.Value.asset"
                      }
                    },
                    "Iterator": {
                      "StartAt": "EnqueueCopyAudio",
                      "States": {
                        "EnqueueCopyAudio": {
                          "Type": "Task",
                          "Resource": "${enqueue_copy_audio_lambda_arn}",
                          "Retry": [
                            {
                              "ErrorEquals": [
                                "NetworkException",
                                "ReadTimeout",
                                "States.Timeout",
                                "Lambda.ServiceException",
                                "Lambda.AWSLambdaException",
                                "Lambda.SdkClientException",
                                "Lambda.TooManyRequestsException"
                              ],
                              "BackoffRate": 2,
                              "IntervalSeconds": 60,
                              "MaxAttempts": 3,
                              "Comment": "Retry 3 times with a backoff rate of 2"
                            }
                          ],
                          "End": true
                        }
                      }
                    },
                    "End": true
                  }
                }
              }
            ],
            "Next": "SuccessState",
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "HandleProductFailure",
                "ResultPath": "$.exception",
                "Comment": "Track asset processing failed"
              }
            ]
          },
          "HandleProductFailure": {
            "Type": "Task",
            "Resource": "${handle_product_failure_lambda_arn}",
            "Retry": [
              {
                "ErrorEquals": [
                  "NetworkException",
                  "ReadTimeout",
                  "States.Timeout",
                  "Lambda.ServiceException",
                  "Lambda.AWSLambdaException",
                  "Lambda.SdkClientException",
                  "Lambda.TooManyRequestsException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 60,
                "MaxAttempts": 7,
                "Comment": "Retry 7 times with a backoff rate of 2. Total time 2 hours"
              },
              {
                "ErrorEquals": [
                  "HandleProductFailureException"
                ],
                "MaxAttempts": 0,
                "Comment": "Don't retry"
              },
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "BackoffRate": 1,
                "IntervalSeconds": 300,
                "MaxAttempts": 1,
                "Comment": "Retry once on any failure"
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "FailureState",
                "ResultPath": "$.exception",
                "Comment": "Error after retry or invalid input"
              }
            ],
            "ResultPath": "$.result",
            "Next": "formatProductFailure"
          },
          "formatProductFailure": {
            "Type": "Pass",
            "Parameters": {
              "bulk_session_id.$": "$.result.bulk_session_id",
              "bulk_session_ingestion_id.$": "$.result.bulk_session_ingestion_id",
              "identity_uuid.$": "$.result.identity_uuid",
              "assets_required.$": "$.result.assets_required",
              "submit_products.$": "$.result.submit_products",
              "send_notifications.$": "$.result.send_notifications",
              "correlation_id.$": "$.result.correlation_id",
              "product_info.$": "$.result.product_info",
              "exception.$": "$.exception"
            },
            "Next": "FailureState"
          },
          "SuccessState": {
            "Type": "Succeed"
          },
          "FailureState": {
            "Type": "Fail",
            "ErrorPath": "$.exception.Error",
            "CausePath": "States.Format('Error: {}, Cause: {}', $.exception.Error, $.exception.Cause)"
          }
        }
      }
    },
    "SuccessBulkState": {
      "Type": "Succeed"
    },
    "FailureBulkState": {
      "Type": "Fail"
    }
  }
}
