public async Task RunScheduledQueryExample(bool skipDeletion, Dictionary <string, string> resourcesCreated)
        {
            try
            {
                resourcesCreated = await CreateResourcesForScheduledQuery(resourcesCreated);

                //Scheduled Query Activities

                /* Switch between Valid and Invalid Query to test Happy-case and Failure scenarios */
                string scheduledQueryArn = await CreateValidScheduledQuery(
                    resourcesCreated[ScheduledQueryConstants.TopicArn],
                    resourcesCreated[ScheduledQueryConstants.RoleArn], ScheduledQueryConstants.SqDatabaseName,
                    ScheduledQueryConstants.SqTableName, resourcesCreated[AwsResourceConstant.BucketName]);

                resourcesCreated.Add(ScheduledQueryConstants.ScheduledQueryArn, scheduledQueryArn);

                // string scheduledQueryArn = await CreateInvalidScheduledQuery(
                //     resourcesCreated[ScheduledQueryConstants.TopicArn],
                //     resourcesCreated[ScheduledQueryConstants.RoleArn], ScheduledQueryConstants.SqDatabaseName,
                //     ScheduledQueryConstants.SqTableName, resourcesCreated[ScheduledQueryConstants.BucketName]);

                await ListScheduledQueries();
                await DescribeScheduledQuery(scheduledQueryArn);

                // Sleep for 65 seconds to let ScheduledQuery run
                Console.WriteLine("Waiting 65 seconds for automatic ScheduledQuery runs & notifications");
                Thread.Sleep(65000);

                await ProcessScheduledQueryNotifications(scheduledQueryArn);

                await UpdateScheduledQuery(scheduledQueryArn, ScheduledQueryState.DISABLED);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Failed to run Scheduled Query example: {e}");
            }
            finally
            {
                if (skipDeletion)
                {
                    Console.WriteLine("The following resources created as part of sample application will have to be deleted manually");
                    foreach (KeyValuePair <string, string> kvp in resourcesCreated)
                    {
                        Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value);
                    }
                }
                else
                {
                    await CleanupResources();
                }
            }

            async Task ProcessScheduledQueryNotifications(string scheduledQueryArn)
            {
                var didQuerySucceedManually     = false;
                var wasQueryTriggeredAsExpected = false;
                var queryFailed = false;

                // Reading up to 10 messages in the SQS queue
                for (int i = 0; i < 10; i++)
                {
                    ReceiveMessageResponse response =
                        await _timestreamDependencyHelper.GetMessage(sqsClient,
                                                                     resourcesCreated[ScheduledQueryConstants.QueueUrl]);

                    if (!response.Messages.Any())
                    {
                        continue;
                    }

                    Console.WriteLine($"\nMessage body of {response.Messages[0].MessageId}:");
                    string messageBody = response.Messages[0].Body;
                    Console.WriteLine($"{messageBody}");

                    if (messageBody == null)
                    {
                        continue;
                    }

                    JObject sqsMessage = JObject.Parse(messageBody);
                    JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore
                    };
                    string notificationType =
                        sqsMessage["MessageAttributes"][AwsResourceConstant.NotificationType]["Value"].Value <string>();

                    switch (notificationType)
                    {
                    case "SCHEDULED_QUERY_CREATING":
                        // Scheduled Query is still pending to run.
                        Console.WriteLine("SCHEDULED_QUERY_CREATING notification is received");
                        break;

                    case "SCHEDULED_QUERY_CREATED":
                        // Scheduled Query is still pending to run.
                        Console.WriteLine("SCHEDULED_QUERY_CREATED notification is received");
                        break;

                    case "MANUAL_TRIGGER_SUCCESS":
                        Console.WriteLine("Manual run of Scheduled Query succeeded");
                        didQuerySucceedManually = true;
                        break;

                    case "AUTO_TRIGGER_SUCCESS":
                        Console.WriteLine(
                            "Scheduled Query was triggered as expected. Now triggering another run manually");
                        wasQueryTriggeredAsExpected = true;
                        ExecutionNotificationMessage successExecutionNotificationMessage =
                            JsonConvert.DeserializeObject <ExecutionNotificationMessage>(sqsMessage["Message"]
                                                                                         .Value <string>(), jsonSerializerSettings);
                        DateTimeOffset dateTimeOffset =
                            DateTimeOffset.FromUnixTimeSeconds(successExecutionNotificationMessage
                                                               .NextInvocationEpochSecond);
                        await ExecuteScheduledQuery(scheduledQueryArn, dateTimeOffset.DateTime);

                        break;

                    case "AUTO_TRIGGER_FAILURE":
                    // Fall-through
                    case "MANUAL_TRIGGER_FAILURE":
                        queryFailed = true;
                        ExecutionNotificationMessage failureExecutionNotificationMessage =
                            JsonConvert.DeserializeObject <ExecutionNotificationMessage>(
                                sqsMessage["Message"].Value <string>(), jsonSerializerSettings);
                        string failureReason = failureExecutionNotificationMessage.ScheduledQueryRunSummary
                                               .FailureReason;

                        Console.WriteLine($"Failure Reason from SQS Notification:: {failureReason}");

                        ErrorReportLocation errorReportLocation = failureExecutionNotificationMessage
                                                                  .ScheduledQueryRunSummary.ErrorReportLocation;

                        if (errorReportLocation != null)
                        {
                            // Error Notification has Error report associated with it. We can parse it.
                            string s3ObjectKey = errorReportLocation.S3ReportLocation.ObjectKey;
                            await ParseS3ErrorReport(resourcesCreated[AwsResourceConstant.BucketName],
                                                     s3ObjectKey);
                        }

                        break;

                    case "SCHEDULED_QUERY_DELETED":
                        // Fall-through
                        Console.WriteLine("SCHEDULED_QUERY_DELETED notification is received");
                        break;

                    case "SCHEDULED_QUERY_UPDATED":
                        // Fall-through
                        Console.WriteLine("SCHEDULED_QUERY_UPDATED notification is received");
                        break;

                    default:
                        Console.WriteLine("Received an unexpected message:: " + sqsMessage);
                        break;
                    }

                    // Since its a FIFO queue, we need to delete the message to be able to receive further messages
                    await _timestreamDependencyHelper.DeleteMessage(sqsClient, response.Messages[0],
                                                                    resourcesCreated[ScheduledQueryConstants.QueueUrl]);

                    if ((didQuerySucceedManually && wasQueryTriggeredAsExpected) || queryFailed)
                    {
                        break;
                    }
                }

                if (wasQueryTriggeredAsExpected || didQuerySucceedManually)
                {
                    Console.WriteLine("Fetching Scheduled Query run results");
                    await _queryRunner.RunQueryAsync("SELECT * FROM " + ScheduledQueryConstants.SqDatabaseName + "." +
                                                     ScheduledQueryConstants.SqTableName);
                }
            }

            async Task CleanupResources()
            {
                //Clean up for scheduled query
                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.ScheduledQueryArn))
                {
                    await DeleteScheduledQuery(resourcesCreated[ScheduledQueryConstants.ScheduledQueryArn]);
                }

                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.PolicyArn))
                {
                    await _timestreamDependencyHelper.DetachIamRolePolicy(iamClient,
                                                                          ScheduledQueryConstants.IamRoleName,
                                                                          resourcesCreated[ScheduledQueryConstants.PolicyArn]);

                    await _timestreamDependencyHelper.DeleteIamPolicy(iamClient,
                                                                      resourcesCreated[ScheduledQueryConstants.PolicyArn]);
                }

                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.RoleName))
                {
                    await _timestreamDependencyHelper.DeleteIamRole(iamClient, ScheduledQueryConstants.IamRoleName);
                }

                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.SubscriptionArn))
                {
                    await _timestreamDependencyHelper.UnsubscribeFromSnsTopic(snsClient,
                                                                              resourcesCreated[ScheduledQueryConstants.SubscriptionArn]);
                }

                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.QueueUrl))
                {
                    await _timestreamDependencyHelper.DeleteQueue(sqsClient, ScheduledQueryConstants.FifoQueueName);
                }

                if (resourcesCreated.ContainsKey(ScheduledQueryConstants.TopicArn))
                {
                    await _timestreamDependencyHelper.DeleteSnsTopic(snsClient,
                                                                     resourcesCreated[ScheduledQueryConstants.TopicArn]);
                }

                if (resourcesCreated.ContainsKey(AwsResourceConstant.BucketName))
                {
                    await _timestreamDependencyHelper.DeleteS3Bucket(s3Client,
                                                                     resourcesCreated[AwsResourceConstant.BucketName]);
                }

                await _timestreamCrudHelper.DeleteTable(_amazonTimestreamWrite, ScheduledQueryConstants.SqDatabaseName,
                                                        ScheduledQueryConstants.SqTableName);

                await _timestreamCrudHelper.DeleteDatabase(_amazonTimestreamWrite,
                                                           ScheduledQueryConstants.SqDatabaseName);
            }
        }
        static async Task MainAsync(string kmsKeyId, string csvFilePath, string region, bool skipDeletion)
        {
            // Recommended Timestream write client SDK configuration:
            // - Set SDK retry count to 10
            // - Set RequestTimeout to 100 seconds
            var writeClientConfig = new AmazonTimestreamWriteConfig
            {
                RegionEndpoint = RegionEndpoint.GetBySystemName(region),
                Timeout        = TimeSpan.FromSeconds(100),
                MaxErrorRetry  = 10
            };

            var writeClient = new AmazonTimestreamWriteClient(writeClientConfig);
            var crudHelper  = new TimestreamCrudHelper();
            var timestreamDependencyHelper    = new TimestreamDependencyHelper();
            var crudAndSimpleIngestionExample = new CrudAndSimpleIngestionExample(writeClient, crudHelper);
            var csvIngestionExample           = new CsvIngestionExample(writeClient);
            var multiValueIngestionExample    = new MultiValueAttributesExample(writeClient);
            var s3Client = new AmazonS3Client(RegionEndpoint.GetBySystemName(region));

            var queryClientConfig = new AmazonTimestreamQueryConfig
            {
                RegionEndpoint = RegionEndpoint.GetBySystemName(region)
            };
            var queryClient  = new AmazonTimestreamQueryClient(queryClientConfig);
            var queryExample = new QueryExample(queryClient);

            await crudAndSimpleIngestionExample.CreateDatabase();

            await crudAndSimpleIngestionExample.DescribeDatabase();

            await crudAndSimpleIngestionExample.ListDatabases();

            if (kmsKeyId != null)
            {
                await crudAndSimpleIngestionExample.UpdateDatabase("TestFakeKey");
            }

            Dictionary <string, string> resourcesCreated = new Dictionary <string, string>();
            var s3ErrorReportBucketName = AwsResourceConstant.ErrorConfigurationS3BucketNamePrefix +
                                          Guid.NewGuid().ToString("n").Substring(0, 8);
            await timestreamDependencyHelper.CreateS3Bucket(s3Client, s3ErrorReportBucketName);

            resourcesCreated.Add(AwsResourceConstant.BucketName, s3ErrorReportBucketName);

            await crudAndSimpleIngestionExample.CreateTable(s3ErrorReportBucketName);

            await crudAndSimpleIngestionExample.DescribeTable();

            await crudAndSimpleIngestionExample.ListTables();

            await crudAndSimpleIngestionExample.UpdateTable();

            // Simple records ingestion
            await crudAndSimpleIngestionExample.WriteRecordsMultiMeasure();

            await crudAndSimpleIngestionExample.WriteRecordsWithCommonAttributes();

            // upsert records
            await crudAndSimpleIngestionExample.WriteRecordsWithUpsert();

            // write multi value records
            await crudHelper.CreateDatabase(writeClient, MultiMeasureValueConstants.MultiMeasureValueSampleDb);

            await crudHelper.CreateTable(writeClient, MultiMeasureValueConstants.MultiMeasureValueSampleDb,
                                         MultiMeasureValueConstants.MultiMeasureValueSampleTable, s3ErrorReportBucketName);

            await multiValueIngestionExample.WriteRecordsMultiMeasureValueSingleRecord();

            await multiValueIngestionExample.WriteRecordsMultiMeasureValueMultipleRecords();

            if (csvFilePath != null)
            {
                // Bulk record ingestion for bootstrapping a table with fresh data
                await csvIngestionExample.BulkWriteRecordsMultiMeasure(csvFilePath);

                await queryExample.RunAllQueries();

                // Try cancelling query
                await queryExample.CancelQuery();

                // Run query with multiple pages
                await queryExample.RunQueryWithMultiplePages(20000);

                // Run Scheduled Query examples only if CSV was provided
                var scheduledQueryExample = new ScheduledQueryExample(writeClient, queryClient,
                                                                      timestreamDependencyHelper,
                                                                      crudHelper, queryExample, region, s3Client);
                await scheduledQueryExample.RunScheduledQueryExample(skipDeletion, resourcesCreated);
            }
            else
            {
                Console.WriteLine("Running the SELECT ALL query");
                await queryExample.RunQueryAsync(QueryExample.SELECT_ALL_QUERY + " LIMIT 10");
            }

            if (!skipDeletion)
            {
                await crudAndSimpleIngestionExample.DeleteTable();

                await crudAndSimpleIngestionExample.DeleteDatabase();
            }
        }