View a markdown version of this page

EventBridge 使用调度器示例 Amazon SDK for .NET - Amazon SDK for .NET (V3)
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

Amazon SDK for .NET V3 已结束支持。

我们建议您迁移到 Amazon SDK for .NET V4。有关如何迁移的更多详细信息和信息,请参阅我们的终止支持公告

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

EventBridge 使用调度器示例 Amazon SDK for .NET

以下代码示例向您展示了如何使用 with S EventBridge cheduler 来执行操作和实现常见场景。 Amazon SDK for .NET

操作是大型程序的代码摘录,必须在上下文中运行。您可以通过操作了解如何调用单个服务函数,还可以通过函数相关场景的上下文查看操作。

场景是向您演示如何通过在一个服务中调用多个函数或与其他 Amazon Web Services 服务结合来完成特定任务的代码示例。

每个示例都包含一个指向完整源代码的链接,您可以从中找到有关如何在上下文中设置和运行代码的说明。

开始使用

以下代码示例显示了如何开始使用 EventBridge 调度器。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

public static class HelloScheduler { static async Task Main(string[] args) { // Use the AWS .NET Core Setup package to set up dependency injection for the EventBridge Scheduler service. // Use your AWS profile name, or leave it blank to use the default profile. using var host = Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddAWSService<IAmazonScheduler>() ).Build(); // Now the client is available for injection. var schedulerClient = host.Services.GetRequiredService<IAmazonScheduler>(); // You can use await and any of the async methods to get a response, or a paginator to list schedules or groups. var results = new List<ScheduleSummary>(); var paginateSchedules = schedulerClient.Paginators.ListSchedules( new ListSchedulesRequest()); Console.WriteLine( $"Hello AWS Scheduler! Let's list schedules in your account."); // Get the entire list using the paginator. await foreach (var schedule in paginateSchedules.Schedules) { results.Add(schedule); } Console.WriteLine($"\tTotal of {results.Count} schedule(s) available."); results.ForEach(s => Console.WriteLine($"\tSchedule: {s.Name}")); } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NET API 参考ListSchedules中的。

操作

以下代码示例演示了如何使用 CreateSchedule

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Creates a new schedule in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule.</param> /// <param name="scheduleExpression">The schedule expression that defines when the schedule should run.</param> /// <param name="scheduleGroupName">The name of the schedule group to which the schedule should be added.</param> /// <param name="deleteAfterCompletion">Indicates whether to delete the schedule after completion.</param> /// <param name="useFlexibleTimeWindow">Indicates whether to use a flexible time window for the schedule.</param> /// <param name="targetArn">ARN of the event target.</param> /// <param name="roleArn">Execution Role ARN.</param> /// <returns>True if the schedule was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleAsync( string name, string scheduleExpression, string scheduleGroupName, string targetArn, string roleArn, string input, bool deleteAfterCompletion = false, bool useFlexibleTimeWindow = false) { try { int hoursToRun = 1; int flexibleTimeWindowMinutes = 10; var request = new CreateScheduleRequest { Name = name, ScheduleExpression = scheduleExpression, GroupName = scheduleGroupName, Target = new Target { Arn = targetArn, RoleArn = roleArn, Input = input }, ActionAfterCompletion = deleteAfterCompletion ? ActionAfterCompletion.DELETE : ActionAfterCompletion.NONE, StartDate = DateTime.UtcNow, // Ignored for one-time schedules. EndDate = DateTime.UtcNow .AddHours(hoursToRun) // Ignored for one-time schedules. }; // Allow a flexible time window if the caller specifies it. request.FlexibleTimeWindow = new FlexibleTimeWindow { Mode = useFlexibleTimeWindow ? FlexibleTimeWindowMode.FLEXIBLE : FlexibleTimeWindowMode.OFF, MaximumWindowInMinutes = useFlexibleTimeWindow ? flexibleTimeWindowMinutes : null }; var response = await _amazonScheduler.CreateScheduleAsync(request); Console.WriteLine($"Successfully created schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {response.ScheduleArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"An error occurred while creating schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {ex.Message}"); return false; } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NET API 参考CreateSchedule中的。

以下代码示例演示了如何使用 CreateScheduleGroup

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Creates a new schedule group in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group.</param> /// <returns>True if the schedule group was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleGroupAsync(string name) { try { var request = new CreateScheduleGroupRequest { Name = name }; var response = await _amazonScheduler.CreateScheduleGroupAsync(request); Console.WriteLine($"Successfully created schedule group '{name}': {response.ScheduleGroupArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule group '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError( $"An error occurred while creating schedule group '{name}': {ex.Message}"); return false; } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NET API 参考CreateScheduleGroup中的。

以下代码示例演示了如何使用 DeleteSchedule

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Deletes an existing schedule from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule to delete.</param> /// <param name="groupName">The group name of the schedule to delete.</param> /// <returns>True if the schedule was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleAsync(string name, string groupName) { try { var request = new DeleteScheduleRequest { Name = name, GroupName = groupName }; await _amazonScheduler.DeleteScheduleAsync(request); Console.WriteLine($"Successfully deleted schedule with name '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule with ID '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule with ID '{name}': {ex.Message}"); return false; } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NET API 参考DeleteSchedule中的。

以下代码示例演示了如何使用 DeleteScheduleGroup

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Deletes an existing schedule group from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group to delete.</param> /// <returns>True if the schedule group was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleGroupAsync(string name) { try { var request = new DeleteScheduleGroupRequest { Name = name }; await _amazonScheduler.DeleteScheduleGroupAsync(request); Console.WriteLine($"Successfully deleted schedule group '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule group '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule group '{name}': {ex.Message}"); return false; } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NET API 参考DeleteScheduleGroup中的。

场景

以下代码示例展示了如何:

  • 部署包含所需资源的 Amazon CloudFormation 堆栈。

  • 创建 EventBridge 日程安排组。

  • 创建具有灵活时间 EventBridge 范围的一次性日程安排。

  • 创建具有指定速率的定期 EventBridge 日程安排。

  • 删除 “ EventBridge 日程安排器” 和 “日程组”。

  • 清理资源和删除堆栈。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

运行场景。

using System.Text.RegularExpressions; using Amazon.CloudFormation; using Amazon.CloudFormation.Model; using Amazon.Scheduler; using Amazon.Scheduler.Model; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Debug; using SchedulerActions; using Exception = System.Exception; namespace SchedulerScenario; public class SchedulerWorkflow { /* Before running this .NET code example, set up your development environment, including your credentials. This .NET code example performs the following tasks for the Amazon EventBridge Scheduler workflow: 1. Prepare the Application: - Prompt the user for an email address to use for the subscription for the SNS topic subscription. - Prompt the user for a name for the Cloud Formation stack. - Deploy the Cloud Formation template in resources/cfn_template.yaml for resource creation. - Store the outputs of the stack into variables for use in the scenario. - Create a schedule group for all schedules. 2. Create one-time Schedule: - Create a one-time schedule to send an initial event. - Use a Flexible Time Window and set the schedule to delete after completion. - Wait for the user to receive the event email from SNS. 3. Create a time-based schedule: - Prompt the user for how many X times per Y hours a recurring event should be scheduled. - Create the scheduled event for X times per hour for Y hours. - Wait for the user to receive the event email from SNS. - Delete the schedule when the user is finished. 4. Clean up: - Prompt the user for y/n answer if they want to destroy the stack and clean up all resources. - Delete the schedule group. - Destroy the Cloud Formation stack and wait until the stack has been removed. */ public static ILogger<SchedulerWorkflow> _logger = null!; public static SchedulerWrapper _schedulerWrapper = null!; public static IAmazonCloudFormation _amazonCloudFormation = null!; private static string _roleArn = null!; private static string _snsTopicArn = null!; public static bool _interactive = true; private static string _stackName = "default-scheduler-scenario-stack-name"; private static string _scheduleGroupName = "scenario-schedules-group"; private static string _stackResourcePath = "../../../../../../scenarios/features/eventbridge_scheduler/resources/cfn_template.yaml"; public static async Task Main(string[] args) { using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Debug) .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddAWSService<IAmazonScheduler>() .AddAWSService<IAmazonCloudFormation>() .AddTransient<SchedulerWrapper>() ) .Build(); if (_interactive) { _logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) .CreateLogger<SchedulerWorkflow>(); _schedulerWrapper = host.Services.GetRequiredService<SchedulerWrapper>(); _amazonCloudFormation = host.Services.GetRequiredService<IAmazonCloudFormation>(); } Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the Amazon EventBridge Scheduler Scenario."); Console.WriteLine(new string('-', 80)); try { Console.WriteLine(new string('-', 80)); var prepareSuccess = await PrepareApplication(); Console.WriteLine(new string('-', 80)); if (prepareSuccess) { Console.WriteLine(new string('-', 80)); await CreateOneTimeSchedule(); Console.WriteLine(new string('-', 80)); Console.WriteLine(new string('-', 80)); await CreateRecurringSchedule(); Console.WriteLine(new string('-', 80)); } Console.WriteLine(new string('-', 80)); await Cleanup(); Console.WriteLine(new string('-', 80)); } catch (Exception ex) { _logger.LogError(ex, "There was a problem with the scenario, initiating cleanup..."); _interactive = false; await Cleanup(); } Console.WriteLine("Amazon EventBridge Scheduler scenario completed."); } /// <summary> /// Prepares the application by creating the necessary resources. /// </summary> /// <returns>True if the application was prepared successfully.</returns> public static async Task<bool> PrepareApplication() { Console.WriteLine("Preparing the application..."); try { // Prompt the user for an email address to use for the subscription. Console.WriteLine("\nThis example creates resources in a CloudFormation stack, including an SNS topic" + "\nthat will be subscribed to the EventBridge Scheduler events. " + "\n\nYou will need to confirm the subscription in order to receive event emails. "); var emailAddress = PromptUserForEmail(); // Prompt the user for a name for the CloudFormation stack _stackName = PromptUserForStackName(); // Deploy the CloudFormation stack var deploySuccess = await DeployCloudFormationStack(_stackName, emailAddress); if (deploySuccess) { // Create a schedule group for all schedules await _schedulerWrapper.CreateScheduleGroupAsync(_scheduleGroupName); Console.WriteLine("Application preparation complete."); return true; } } catch (Exception ex) { _logger.LogError(ex, "An error occurred while preparing the application."); } Console.WriteLine("Application preparation failed."); return false; } /// <summary> /// Deploys the CloudFormation stack with the necessary resources. /// </summary> /// <param name="stackName">The name of the CloudFormation stack.</param> /// <param name="email">The email to use for the subscription.</param> /// <returns>True if the stack was deployed successfully.</returns> private static async Task<bool> DeployCloudFormationStack(string stackName, string email) { Console.WriteLine($"\nDeploying CloudFormation stack: {stackName}"); try { var request = new CreateStackRequest { StackName = stackName, TemplateBody = await File.ReadAllTextAsync(_stackResourcePath), Capabilities = { Capability.CAPABILITY_NAMED_IAM } }; // If an email is provided, set the parameter. if (!string.IsNullOrWhiteSpace(email)) { request.Parameters = new List<Parameter>() { new() { ParameterKey = "email", ParameterValue = email } }; } var response = await _amazonCloudFormation.CreateStackAsync(request); if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) { Console.WriteLine($"CloudFormation stack creation started: {stackName}"); // Wait for the stack to be in CREATE_COMPLETE state bool stackCreated = await WaitForStackCompletion(response.StackId); if (stackCreated) { // Retrieve the output values var success = await GetStackOutputs(response.StackId); return success; } else { _logger.LogError($"CloudFormation stack creation failed: {stackName}"); return false; } } else { _logger.LogError($"Failed to create CloudFormation stack: {stackName}"); return false; } } catch (AlreadyExistsException) { _logger.LogWarning($"CloudFormation stack '{stackName}' already exists. Please provide a unique name."); var newStackName = PromptUserForStackName(); return await DeployCloudFormationStack(newStackName, email); } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while deploying the CloudFormation stack: {stackName}"); return false; } } /// <summary> /// Waits for the CloudFormation stack to be in the CREATE_COMPLETE state. /// </summary> /// <param name="client">The CloudFormation client.</param> /// <param name="stackId">The ID of the CloudFormation stack.</param> /// <returns>True if the stack was created successfully.</returns> private static async Task<bool> WaitForStackCompletion(string stackId) { int retryCount = 0; const int maxRetries = 10; const int retryDelay = 30000; // 30 seconds. while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackId }; var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count > 0) { if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_COMPLETE) { Console.WriteLine("CloudFormation stack creation complete."); return true; } if (describeStacksResponse.Stacks[0].StackStatus == StackStatus.CREATE_FAILED || describeStacksResponse.Stacks[0].StackStatus == StackStatus.ROLLBACK_COMPLETE) { Console.WriteLine("CloudFormation stack creation failed."); return false; } } Console.WriteLine("Waiting for CloudFormation stack creation to complete..."); await Task.Delay(retryDelay); retryCount++; } _logger.LogError("Timed out waiting for CloudFormation stack creation to complete."); return false; } /// <summary> /// Retrieves the output values from the CloudFormation stack. /// </summary> /// <param name="stackId">The ID of the CloudFormation stack.</param> private static async Task<bool> GetStackOutputs(string stackId) { try { var describeStacksRequest = new DescribeStacksRequest { StackName = stackId }; var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count > 0) { var stack = describeStacksResponse.Stacks[0]; _roleArn = GetStackOutputValue(stack, "RoleARN"); _snsTopicArn = GetStackOutputValue(stack, "SNStopicARN"); return true; } else { _logger.LogError($"No stack found for stack outputs: {stackId}"); return false; } } catch (Exception ex) { _logger.LogError( ex, $"Failed to retrieve CloudFormation stack outputs: {stackId}"); return false; } } /// <summary> /// Get an output value by key from a CloudFormation stack. /// </summary> /// <param name="stack">The CloudFormation stack.</param> /// <param name="outputKey">The key of the output.</param> /// <returns>The value as a string.</returns> private static string GetStackOutputValue(Stack stack, string outputKey) { var output = stack.Outputs.First(o => o.OutputKey == outputKey); var outputValue = output.OutputValue; Console.WriteLine($"Stack output {outputKey}: {outputValue}"); return outputValue; } /// <summary> /// Creates a one-time schedule to send an initial event. /// </summary> /// <returns>True if the one-time schedule was created successfully.</returns> public static async Task<bool> CreateOneTimeSchedule() { var scheduleName = PromptUserForResourceName("Enter a name for the one-time schedule:"); Console.WriteLine($"Creating a one-time schedule named '{scheduleName}' " + $"\nto send an initial event in 1 minute with a flexible time window..."); try { // Create a one-time schedule with a flexible time // window set to delete after completion. // You may also set a timezone instead of using UTC. var scheduledTime = DateTime.UtcNow.AddMinutes(1).ToString("s"); var createSuccess = await _schedulerWrapper.CreateScheduleAsync( scheduleName, $"at({scheduledTime})", _scheduleGroupName, _snsTopicArn, _roleArn, $"One time scheduled event test from schedule {scheduleName}.", true, useFlexibleTimeWindow: true); Console.WriteLine($"Subscription email will receive an email from this event."); Console.WriteLine($"You must confirm your subscription to receive event emails."); Console.WriteLine($"One-time schedule '{scheduleName}' created successfully."); return createSuccess; } catch (ResourceNotFoundException ex) { _logger.LogError(ex, $"The target with ARN '{_snsTopicArn}' was not found."); return false; } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while creating the one-time schedule '{scheduleName}'."); return false; } } /// <summary> /// Create a recurring schedule to send events at a specified rate in minutes. /// </summary> /// <returns>True if the recurring schedule was created successfully.</returns> public static async Task<bool> CreateRecurringSchedule() { Console.WriteLine("Creating a recurring schedule to send events for one hour..."); try { // Prompt the user for a schedule name. var scheduleName = PromptUserForResourceName("Enter a name for the recurring schedule: "); // Prompt the user for the schedule rate (in minutes). var scheduleRateInMinutes = PromptUserForInteger("Enter the desired schedule rate (in minutes): "); // Create the recurring schedule. var createSuccess = await _schedulerWrapper.CreateScheduleAsync( scheduleName, $"rate({scheduleRateInMinutes} minutes)", _scheduleGroupName, _snsTopicArn, _roleArn, $"Recurrent event test from schedule {scheduleName}."); Console.WriteLine($"Subscription email will receive an email from this event."); Console.WriteLine($"You must confirm your subscription to receive event emails."); // Delete the schedule when the user is finished. if (!_interactive || GetYesNoResponse($"Are you ready to delete the '{scheduleName}' schedule? (y/n)")) { await _schedulerWrapper.DeleteScheduleAsync(scheduleName, _scheduleGroupName); } return createSuccess; } catch (ResourceNotFoundException ex) { _logger.LogError(ex, $"The target with ARN '{_snsTopicArn}' was not found."); return false; } catch (Exception ex) { _logger.LogError(ex, "An error occurred while creating the recurring schedule."); return false; } } /// <summary> /// Cleans up the resources created during the scenario. /// </summary> /// <returns>True if the cleanup was successful.</returns> public static async Task<bool> Cleanup() { // Prompt the user to confirm cleanup. var cleanup = !_interactive || GetYesNoResponse( "Do you want to delete all resources created by this scenario? (y/n) "); if (cleanup) { try { // Delete the schedule group. var groupDeleteSuccess = await _schedulerWrapper.DeleteScheduleGroupAsync(_scheduleGroupName); // Destroy the CloudFormation stack and wait for it to be removed. var stackDeleteSuccess = await DeleteCloudFormationStack(_stackName, false); return groupDeleteSuccess && stackDeleteSuccess; } catch (Exception ex) { _logger.LogError(ex, "An error occurred while cleaning up the resources."); return false; } } _logger.LogInformation("EventBridge Scheduler scenario is complete."); return true; } /// <summary> /// Delete the resources in the stack and wait for confirmation. /// </summary> /// <param name="stackName">The name of the stack.</param> /// <param name="forceDelete">True to force delete the stack.</param> /// <returns>True if successful.</returns> private static async Task<bool> DeleteCloudFormationStack(string stackName, bool forceDelete) { var request = new DeleteStackRequest { StackName = stackName, }; if (forceDelete) { request.DeletionMode = DeletionMode.FORCE_DELETE_STACK; } await _amazonCloudFormation.DeleteStackAsync(request); Console.WriteLine($"CloudFormation stack '{_stackName}' is being deleted. This may take a few minutes."); bool stackDeleted = await WaitForStackDeletion(_stackName, forceDelete); if (stackDeleted) { Console.WriteLine($"CloudFormation stack '{_stackName}' has been deleted."); return true; } else { _logger.LogError($"Failed to delete CloudFormation stack '{_stackName}'."); return false; } } /// <summary> /// Wait for the stack to be deleted. /// </summary> /// <param name="stackName">The name of the stack.</param> /// <param name="forceDelete">True to force delete the stack.</param> /// <returns>True if successful.</returns> private static async Task<bool> WaitForStackDeletion(string stackName, bool forceDelete) { int retryCount = 0; const int maxRetries = 10; const int retryDelay = 30000; // 30 seconds while (retryCount < maxRetries) { var describeStacksRequest = new DescribeStacksRequest { StackName = stackName }; try { var describeStacksResponse = await _amazonCloudFormation.DescribeStacksAsync(describeStacksRequest); if (describeStacksResponse.Stacks.Count == 0 || describeStacksResponse.Stacks[0].StackStatus == StackStatus.DELETE_COMPLETE) { return true; } if (!forceDelete && describeStacksResponse.Stacks[0].StackStatus == StackStatus.DELETE_FAILED) { // Try one time to force delete. return await DeleteCloudFormationStack(stackName, true); } } catch (AmazonCloudFormationException ex) when (ex.ErrorCode == "ValidationError") { // Stack does not exist, so it has been successfully deleted. return true; } Console.WriteLine($"Waiting for CloudFormation stack '{stackName}' to be deleted..."); await Task.Delay(retryDelay); retryCount++; } _logger.LogError($"Timed out waiting for CloudFormation stack '{stackName}' to be deleted."); return false; } /// <summary> /// Helper method to get a yes or no response from the user. /// </summary> /// <param name="question">The question string to print on the console.</param> /// <returns>True if the user responds with a yes.</returns> private static bool GetYesNoResponse(string question) { Console.WriteLine(question); var ynResponse = Console.ReadLine(); var response = ynResponse != null && ynResponse.Equals("y", StringComparison.InvariantCultureIgnoreCase); return response; } /// <summary> /// Prompt the user for a valid email address. /// </summary> /// <returns>The valid email address.</returns> private static string PromptUserForEmail() { if (_interactive) { Console.WriteLine("Enter an email address to use for event subscriptions: "); string email = Console.ReadLine()!; if (!IsValidEmail(email)) { Console.WriteLine("Invalid email address. Please try again."); return PromptUserForEmail(); } return email; } // Used when running without user prompts. return ""; } /// <summary> /// Prompt the user for a non-empty stack name. /// </summary> /// <returns>The valid stack name</returns> private static string PromptUserForStackName() { Console.WriteLine("Enter a name for the AWS Cloud Formation Stack: "); if (_interactive) { string stackName = Console.ReadLine()!; var regex = "[a-zA-Z][-a-zA-Z0-9]|arn:[-a-zA-Z0-9:/._+]"; if (!Regex.IsMatch(stackName, regex)) { Console.WriteLine( $"Invalid stack name. Please use a name that matches the pattern {regex}."); return PromptUserForStackName(); } return stackName; } // Used when running without user prompts. return _stackName; } /// <summary> /// Prompt the user for a non-empty resource name. /// </summary> /// <returns>The valid stack name</returns> private static string PromptUserForResourceName(string prompt) { if (_interactive) { Console.WriteLine(prompt); string resourceName = Console.ReadLine()!; var regex = "[0-9a-zA-Z-_.]+"; if (!Regex.IsMatch(resourceName, regex)) { Console.WriteLine($"Invalid resource name. Please use a name that matches the pattern {regex}."); return PromptUserForResourceName(prompt); } return resourceName!; } // Used when running without user prompts. return "resource-" + Guid.NewGuid(); } /// <summary> /// Prompt the user for a non-empty resource name. /// </summary> /// <returns>The valid stack name</returns> private static int PromptUserForInteger(string prompt) { if (_interactive) { Console.WriteLine(prompt); string stringResponse = Console.ReadLine()!; if (string.IsNullOrWhiteSpace(stringResponse) || !Int32.TryParse(stringResponse, out var intResponse)) { Console.WriteLine($"Invalid integer. "); return PromptUserForInteger(prompt); } return intResponse!; } // Used when running without user prompts. return 1; } /// <summary> /// Use System Mail to check for a valid email address. /// </summary> /// <param name="email">The string to verify.</param> /// <returns>True if a valid email address.</returns> private static bool IsValidEmail(string email) { try { var mailAddress = new System.Net.Mail.MailAddress(email); return mailAddress.Address == email; } catch { // Invalid emails will cause an exception, return false. return false; } } }

适用于服务操作的包装器。

using Amazon.Scheduler; using Amazon.Scheduler.Model; using Microsoft.Extensions.Logging; namespace SchedulerActions; /// <summary> /// Wrapper class for Amazon EventBridge Scheduler operations. /// </summary> public class SchedulerWrapper { private readonly IAmazonScheduler _amazonScheduler; private readonly ILogger<SchedulerWrapper> _logger; /// <summary> /// Constructor for the SchedulerWrapper class. /// </summary> /// <param name="amazonScheduler">The injected EventBridge Scheduler client.</param> /// <param name="logger">The injected logger.</param> public SchedulerWrapper(IAmazonScheduler amazonScheduler, ILogger<SchedulerWrapper> logger) { _amazonScheduler = amazonScheduler; _logger = logger; } /// <summary> /// Creates a new schedule in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule.</param> /// <param name="scheduleExpression">The schedule expression that defines when the schedule should run.</param> /// <param name="scheduleGroupName">The name of the schedule group to which the schedule should be added.</param> /// <param name="deleteAfterCompletion">Indicates whether to delete the schedule after completion.</param> /// <param name="useFlexibleTimeWindow">Indicates whether to use a flexible time window for the schedule.</param> /// <param name="targetArn">ARN of the event target.</param> /// <param name="roleArn">Execution Role ARN.</param> /// <returns>True if the schedule was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleAsync( string name, string scheduleExpression, string scheduleGroupName, string targetArn, string roleArn, string input, bool deleteAfterCompletion = false, bool useFlexibleTimeWindow = false) { try { int hoursToRun = 1; int flexibleTimeWindowMinutes = 10; var request = new CreateScheduleRequest { Name = name, ScheduleExpression = scheduleExpression, GroupName = scheduleGroupName, Target = new Target { Arn = targetArn, RoleArn = roleArn, Input = input }, ActionAfterCompletion = deleteAfterCompletion ? ActionAfterCompletion.DELETE : ActionAfterCompletion.NONE, StartDate = DateTime.UtcNow, // Ignored for one-time schedules. EndDate = DateTime.UtcNow .AddHours(hoursToRun) // Ignored for one-time schedules. }; // Allow a flexible time window if the caller specifies it. request.FlexibleTimeWindow = new FlexibleTimeWindow { Mode = useFlexibleTimeWindow ? FlexibleTimeWindowMode.FLEXIBLE : FlexibleTimeWindowMode.OFF, MaximumWindowInMinutes = useFlexibleTimeWindow ? flexibleTimeWindowMinutes : null }; var response = await _amazonScheduler.CreateScheduleAsync(request); Console.WriteLine($"Successfully created schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {response.ScheduleArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError($"An error occurred while creating schedule '{name}' " + $"in schedule group '{scheduleGroupName}': {ex.Message}"); return false; } } /// <summary> /// Creates a new schedule group in Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group.</param> /// <returns>True if the schedule group was created successfully, false otherwise.</returns> public async Task<bool> CreateScheduleGroupAsync(string name) { try { var request = new CreateScheduleGroupRequest { Name = name }; var response = await _amazonScheduler.CreateScheduleGroupAsync(request); Console.WriteLine($"Successfully created schedule group '{name}': {response.ScheduleGroupArn}."); return true; } catch (ConflictException ex) { // If the name is not unique, a ConflictException will be thrown. _logger.LogError($"Failed to create schedule group '{name}' due to a conflict. {ex.Message}"); return false; } catch (Exception ex) { _logger.LogError( $"An error occurred while creating schedule group '{name}': {ex.Message}"); return false; } } /// <summary> /// Deletes an existing schedule from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule to delete.</param> /// <param name="groupName">The group name of the schedule to delete.</param> /// <returns>True if the schedule was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleAsync(string name, string groupName) { try { var request = new DeleteScheduleRequest { Name = name, GroupName = groupName }; await _amazonScheduler.DeleteScheduleAsync(request); Console.WriteLine($"Successfully deleted schedule with name '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule with ID '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule with ID '{name}': {ex.Message}"); return false; } } /// <summary> /// Deletes an existing schedule group from Amazon EventBridge Scheduler. /// </summary> /// <param name="name">The name of the schedule group to delete.</param> /// <returns>True if the schedule group was deleted successfully, false otherwise.</returns> public async Task<bool> DeleteScheduleGroupAsync(string name) { try { var request = new DeleteScheduleGroupRequest { Name = name }; await _amazonScheduler.DeleteScheduleGroupAsync(request); Console.WriteLine($"Successfully deleted schedule group '{name}'."); return true; } catch (ResourceNotFoundException ex) { _logger.LogError( $"Failed to delete schedule group '{name}' because the resource was not found: {ex.Message}"); return true; } catch (Exception ex) { _logger.LogError( $"An error occurred while deleting schedule group '{name}': {ex.Message}"); return false; } } }