SDK for Swift를 사용한 Amazon SQS 예제 - AWS SDK 코드 예제

Doc AWS SDK 예제 GitHub 리포지토리에서 더 많은 SDK 예제를 사용할 수 있습니다. AWS

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

SDK for Swift를 사용한 Amazon SQS 예제

다음 코드 예제에서는 Amazon SQS와 함께 AWS SDK for Swift를 사용하여 작업을 수행하고 일반적인 시나리오를 구현하는 방법을 보여줍니다.

작업은 대규모 프로그램에서 발췌한 코드이며 컨텍스트에 맞춰 실행해야 합니다. 작업은 관련 시나리오의 컨텍스트에 따라 표시되며, 개별 서비스 함수를 직접적으로 호출하는 방법을 보여줍니다.

시나리오는 동일한 서비스 내에서 또는 다른 AWS 서비스와 결합된 상태에서 여러 함수를 호출하여 특정 태스크를 수행하는 방법을 보여주는 코드 예제입니다.

각 예시에는 전체 소스 코드에 대한 링크가 포함되어 있으며, 여기에서 컨텍스트에 맞춰 코드를 설정하고 실행하는 방법에 대한 지침을 찾을 수 있습니다.

시작

다음 코드 예는 Amazon SQS를 시작하는 방법을 보여줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

Package.swift 파일입니다.

import PackageDescription let package = Package( name: "sqs-basics", // Let Xcode know the minimum Apple platforms supported. platforms: [ .macOS(.v13), .iOS(.v15) ], dependencies: [ // Dependencies declare other packages that this package depends on. .package( url: "https://github.com/awslabs/aws-sdk-swift", from: "1.0.0"), .package( url: "https://github.com/apple/swift-argument-parser.git", branch: "main" ) ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products // from dependencies. .executableTarget( name: "sqs-basics", dependencies: [ .product(name: "AWSSQS", package: "aws-sdk-swift"), .product(name: "ArgumentParser", package: "swift-argument-parser") ], path: "Sources") ] )

Swift 소스 코드 entry.swift.

import ArgumentParser import AWSClientRuntime import AWSSQS import Foundation struct ExampleCommand: ParsableCommand { @Argument(help: "The URL of the Amazon SQS queue to delete") var queueUrl: String @Option(help: "Name of the Amazon Region to use (default: us-east-1)") var region = "us-east-1" static var configuration = CommandConfiguration( commandName: "deletequeue", abstract: """ This example shows how to delete an Amazon SQS queue. """, discussion: """ """ ) /// Called by ``main()`` to run the bulk of the example. func runAsync() async throws { let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) do { _ = try await sqsClient.deleteQueue( input: DeleteQueueInput( queueUrl: queueUrl ) ) } catch _ as AWSSQS.QueueDoesNotExist { print("Error: The specified queue doesn't exist.") return } } } /// The program's asynchronous entry point. @main struct Main { static func main() async { let args = Array(CommandLine.arguments.dropFirst()) do { let command = try ExampleCommand.parse(args) try await command.runAsync() } catch { ExampleCommand.exit(withError: error) } } }
  • API 세부 정보는 SDK for Swift API 참조의 ListQueues를 참조하세요. AWS

작업

다음 코드 예시는 CreateQueue의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) let output = try await sqsClient.createQueue( input: CreateQueueInput( queueName: queueName ) ) guard let queueUrl = output.queueUrl else { print("No queue URL returned.") return }
  • API 세부 정보는 SDK for Swift API 참조의 CreateQueue를 참조하세요. AWS

다음 코드 예시는 DeleteMessageBatch의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) // Create the list of message entries. var entries: [SQSClientTypes.DeleteMessageBatchRequestEntry] = [] var messageNumber = 1 for handle in handles { let entry = SQSClientTypes.DeleteMessageBatchRequestEntry( id: "\(messageNumber)", receiptHandle: handle ) entries.append(entry) messageNumber += 1 } // Delete the messages. let output = try await sqsClient.deleteMessageBatch( input: DeleteMessageBatchInput( entries: entries, queueUrl: queue ) ) // Get the lists of failed and successful deletions from the output. guard let failedEntries = output.failed else { print("Failed deletion list is missing!") return } guard let successfulEntries = output.successful else { print("Successful deletion list is missing!") return } // Display a list of the failed deletions along with their // corresponding explanation messages. if failedEntries.count != 0 { print("Failed deletions:") for entry in failedEntries { print("Message #\(entry.id ?? "<unknown>") failed: \(entry.message ?? "<unknown>")") } } else { print("No failed deletions.") } // Output a list of the message numbers that were successfully deleted. if successfulEntries.count != 0 { var successes = "" for entry in successfulEntries { if successes.count == 0 { successes = entry.id ?? "<unknown>" } else { successes = "\(successes), \(entry.id ?? "<unknown>")" } } print("Succeeded: ", successes) } else { print("No successful deletions.") }
  • API 세부 정보는 SDK for Swift API 참조의 DeleteMessageBatch를 참조하세요. AWS

다음 코드 예시는 DeleteQueue의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) do { _ = try await sqsClient.deleteQueue( input: DeleteQueueInput( queueUrl: queueUrl ) ) } catch _ as AWSSQS.QueueDoesNotExist { print("Error: The specified queue doesn't exist.") return }
  • API 세부 정보는 SDK for Swift API 참조의 DeleteQueue를 참조하세요. AWS

다음 코드 예시는 GetQueueAttributes의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) let output = try await sqsClient.getQueueAttributes( input: GetQueueAttributesInput( attributeNames: [ .approximatenumberofmessages, .maximummessagesize ], queueUrl: url ) ) guard let attributes = output.attributes else { print("No queue attributes returned.") return } for (attr, value) in attributes { switch(attr) { case "ApproximateNumberOfMessages": print("Approximate message count: \(value)") case "MaximumMessageSize": print("Maximum message size: \(value)kB") default: continue } }
  • API 세부 정보는 SDK for Swift API 참조의 GetQueueAttributes를 참조하세요. AWS

다음 코드 예시는 ListQueues의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) var queues: [String] = [] let outputPages = sqsClient.listQueuesPaginated( input: ListQueuesInput() ) // Each time a page of results arrives, process its contents. for try await output in outputPages { guard let urls = output.queueUrls else { print("No queues found.") return } // Iterate over the queue URLs listed on this page, adding them // to the `queues` array. for queueUrl in urls { queues.append(queueUrl) } }
  • API 세부 정보는 SDK for Swift API 참조의 ListQueues를 참조하세요. AWS

다음 코드 예시는 ReceiveMessage의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) let output = try await sqsClient.receiveMessage( input: ReceiveMessageInput( maxNumberOfMessages: maxMessages, queueUrl: url ) ) guard let messages = output.messages else { print("No messages received.") return } for message in messages { print("Message ID: \(message.messageId ?? "<unknown>")") print("Receipt handle: \(message.receiptHandle ?? "<unknown>")") print(message.body ?? "<body missing>") print("---") }
  • API 세부 정보는 SDK for Swift API 참조의 ReceiveMessage를 참조하세요. AWS

다음 코드 예시는 SetQueueAttributes의 사용 방법을 보여 줍니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import AWSSQS let config = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: config) do { _ = try await sqsClient.setQueueAttributes( input: SetQueueAttributesInput( attributes: [ "MaximumMessageSize": "\(maxSize)" ], queueUrl: url ) ) } catch _ as AWSSQS.InvalidAttributeValue { print("Invalid maximum message size: \(maxSize) kB.") }
  • API 세부 정보는 SDK for Swift API 참조의 SetQueueAttributes를 참조하세요. AWS

시나리오

다음 코드 예제에서는 다음과 같은 작업을 수행하는 방법을 보여줍니다.

  • 주제(FIFO 또는 비 FIFO)를 생성합니다.

  • 필터 적용 옵션을 사용하여 여러 개의 대기열로 주제를 구독합니다.

  • 주제에 메시지를 게시합니다.

  • 대기열에서 받은 메시지를 폴링합니다.

SDK for Swift
참고

GitHub에 더 많은 내용이 있습니다. AWS 코드 예 리포지토리에서 전체 예를 찾고 설정 및 실행하는 방법을 배워보세요.

import ArgumentParser import AWSClientRuntime import AWSSNS import AWSSQS import Foundation struct ExampleCommand: ParsableCommand { @Option(help: "Name of the Amazon Region to use") var region = "us-east-1" static var configuration = CommandConfiguration( commandName: "queue-scenario", abstract: """ This example interactively demonstrates how to use Amazon Simple Notification Service (Amazon SNS) and Amazon Simple Queue Service (Amazon SQS) together to publish and receive messages using queues. """, discussion: """ Supports filtering using a "tone" attribute. """ ) /// Prompt for an input string. Only non-empty strings are allowed. /// /// - Parameter prompt: The prompt to display. /// /// - Returns: The string input by the user. func stringRequest(prompt: String) -> String { var str: String? while str == nil { print(prompt, terminator: "") str = readLine() if str != nil && str?.count == 0 { str = nil } } return str! } /// Ask a yes/no question. /// /// - Parameter prompt: A prompt string to print. /// /// - Returns: `true` if the user answered "Y", otherwise `false`. func yesNoRequest(prompt: String) -> Bool { while true { let answer = stringRequest(prompt: prompt).lowercased() if answer == "y" || answer == "n" { return answer == "y" } } } /// Display a menu of options then request a selection. /// /// - Parameters: /// - prompt: A prompt string to display before the menu. /// - options: An array of strings giving the menu options. /// /// - Returns: The index number of the selected option or 0 if no item was /// selected. func menuRequest(prompt: String, options: [String]) -> Int { let numOptions = options.count if numOptions == 0 { return 0 } print(prompt) for (index, value) in options.enumerated() { print("(\(index)) \(value)") } repeat { print("Enter your selection (0 - \(numOptions-1)): ", terminator: "") if let answer = readLine() { guard let answer = Int(answer) else { print("Please enter the number matching your selection.") continue } if answer >= 0 && answer < numOptions { return answer } else { print("Please enter the number matching your selection.") } } } while true } /// Ask the user too press RETURN. Accepts any input but ignores it. /// /// - Parameter prompt: The text prompt to display. func returnRequest(prompt: String) { print(prompt, terminator: "") _ = readLine() } var attrValues = [ "<none>", "cheerful", "funny", "serious", "sincere" ] /// Ask the user to choose one of the attribute values to use as a filter. /// /// - Parameters: /// - message: A message to display before the menu of values. /// - attrValues: An array of strings giving the values to choose from. /// /// - Returns: The string corresponding to the selected option. func askForFilter(message: String, attrValues: [String]) -> String? { print(message) for (index, value) in attrValues.enumerated() { print(" [\(index)] \(value)") } var answer: Int? repeat { answer = Int(stringRequest(prompt: "Select an value for the 'tone' attribute or 0 to end: ")) } while answer == nil || answer! < 0 || answer! > attrValues.count + 1 if answer == 0 { return nil } return attrValues[answer!] } /// Prompts the user for filter terms and constructs the attribute /// record that specifies them. /// /// - Returns: A mapping of "FilterPolicy" to a JSON string representing /// the user-defined filter. func buildFilterAttributes() -> [String:String] { var attr: [String:String] = [:] var filterString = "" var first = true while let ans = askForFilter(message: "Choose a value to apply to the 'tone' attribute.", attrValues: attrValues) { if !first { filterString += "," } first = false filterString += "\"\(ans)\"" } let filterJSON = "{ \"tone\": [\(filterString)]}" attr["FilterPolicy"] = filterJSON return attr } /// Create a queue, returning its URL string. /// /// - Parameters: /// - prompt: A prompt to ask for the queue name. /// - isFIFO: Whether or not to create a FIFO queue. /// /// - Returns: The URL of the queue. func createQueue(prompt: String, sqsClient: SQSClient, isFIFO: Bool) async throws -> String? { repeat { var queueName = stringRequest(prompt: prompt) var attributes: [String: String] = [:] if isFIFO { queueName += ".fifo" attributes["FifoQueue"] = "true" } do { let output = try await sqsClient.createQueue( input: CreateQueueInput( attributes: attributes, queueName: queueName ) ) guard let url = output.queueUrl else { return nil } return url } catch _ as QueueDeletedRecently { print("You need to use a different queue name. A queue by that name was recently deleted.") continue } } while true } /// Return the ARN of a queue given its URL. /// /// - Parameter queueUrl: The URL of the queue for which to return the /// ARN. /// /// - Returns: The ARN of the specified queue. func getQueueARN(sqsClient: SQSClient, queueUrl: String) async throws -> String? { let output = try await sqsClient.getQueueAttributes( input: GetQueueAttributesInput( attributeNames: [.queuearn], queueUrl: queueUrl ) ) guard let attributes = output.attributes else { return nil } return attributes["QueueArn"] } /// Applies the needed policy to the specified queue. /// /// - Parameters: /// - sqsClient: The Amazon SQS client to use. /// - queueUrl: The queue to apply the policy to. /// - queueArn: The ARN of the queue to apply the policy to. /// - topicArn: The topic that should have access via the policy. /// /// - Throws: Errors from the SQS `SetQueueAttributes` action. func setQueuePolicy(sqsClient: SQSClient, queueUrl: String, queueArn: String, topicArn: String) async throws { _ = try await sqsClient.setQueueAttributes( input: SetQueueAttributesInput( attributes: [ "Policy": """ { "Statement": [ { "Effect": "Allow", "Principal": { "Service": "sns.amazonaws.com" }, "Action": "sqs:SendMessage", "Resource": "\(queueArn)", "Condition": { "ArnEquals": { "aws:SourceArn": "\(topicArn)" } } } ] } """ ], queueUrl: queueUrl ) ) } /// Receive the available messages on a queue, outputting them to the /// screen. Returns a dictionary you pass to DeleteMessageBatch to delete /// all the received messages. /// /// - Parameters: /// - sqsClient: The Amazon SQS client to use. /// - queueUrl: The SQS queue on which to receive messages. /// /// - Throws: Errors from `SQSClient.receiveMessage()` /// /// - Returns: An array of SQSClientTypes.DeleteMessageBatchRequestEntry /// items, each describing one received message in the format needed to /// delete it. func receiveAndListMessages(sqsClient: SQSClient, queueUrl: String) async throws -> [SQSClientTypes.DeleteMessageBatchRequestEntry] { let output = try await sqsClient.receiveMessage( input: ReceiveMessageInput( maxNumberOfMessages: 10, queueUrl: queueUrl ) ) guard let messages = output.messages else { print("No messages received.") return [] } var deleteList: [SQSClientTypes.DeleteMessageBatchRequestEntry] = [] // Print out all the messages that were received, including their // attributes, if any. for message in messages { print("Message ID: \(message.messageId ?? "<unknown>")") print("Receipt handle: \(message.receiptHandle ?? "<unknown>")") print("Message JSON: \(message.body ?? "<body missing>")") if message.receiptHandle != nil { deleteList.append( SQSClientTypes.DeleteMessageBatchRequestEntry( id: message.messageId, receiptHandle: message.receiptHandle ) ) } } return deleteList } /// Delete all the messages in the specified list. /// /// - Parameters: /// - sqsClient: The Amazon SQS client to use. /// - queueUrl: The SQS queue to delete messages from. /// - deleteList: A list of `DeleteMessageBatchRequestEntry` objects /// describing the messages to delete. /// /// - Throws: Errors from `SQSClient.deleteMessageBatch()`. func deleteMessageList(sqsClient: SQSClient, queueUrl: String, deleteList: [SQSClientTypes.DeleteMessageBatchRequestEntry]) async throws { let output = try await sqsClient.deleteMessageBatch( input: DeleteMessageBatchInput(entries: deleteList, queueUrl: queueUrl) ) if let failed = output.failed { print("\(failed.count) errors occurred deleting messages from the queue.") for message in failed { print("---> Failed to delete message \(message.id ?? "<unknown ID>") with error: \(message.code ?? "<unknown>") (\(message.message ?? "..."))") } } } /// Called by ``main()`` to run the bulk of the example. func runAsync() async throws { let rowOfStars = String(repeating: "*", count: 75) print(""" \(rowOfStars) Welcome to the cross-service messaging with topics and queues example. In this workflow, you'll create an SNS topic, then create two SQS queues which will be subscribed to that topic. You can specify several options for configuring the topic, as well as the queue subscriptions. You can then post messages to the topic and receive the results on the queues. \(rowOfStars)\n """ ) // 0. Create SNS and SQS clients. let snsConfig = try await SNSClient.SNSClientConfiguration(region: region) let snsClient = SNSClient(config: snsConfig) let sqsConfig = try await SQSClient.SQSClientConfiguration(region: region) let sqsClient = SQSClient(config: sqsConfig) // 1. Ask the user whether to create a FIFO topic. If so, ask whether // to use content-based deduplication instead of requiring a // deduplication ID. let isFIFO = yesNoRequest(prompt: "Do you want to create a FIFO topic (Y/N)? ") var isContentBasedDeduplication = false if isFIFO { print(""" \(rowOfStars) Because you've chosen to create a FIFO topic, deduplication is supported. Deduplication IDs are either set in the message or are automatically generated from the content using a hash function. If a message is successfully published to an SNS FIFO topic, any message published and found to have the same deduplication ID (within a five-minute deduplication interval), is accepted but not delivered. For more information about deduplication, see: https://docs.aws.amazon.com/sns/latest/dg/fifo-message-dedup.html. """ ) isContentBasedDeduplication = yesNoRequest( prompt: "Use content-based deduplication instead of entering a deduplication ID (Y/N)? ") print(rowOfStars) } var topicName = stringRequest(prompt: "Enter the name of the topic to create: ") // 2. Create the topic. Append ".fifo" to the name if FIFO was // requested, and set the "FifoTopic" attribute to "true" if so as // well. Set the "ContentBasedDeduplication" attribute to "true" if // content-based deduplication was requested. if isFIFO { topicName += ".fifo" } print("Topic name: \(topicName)") var attributes = [ "FifoTopic": (isFIFO ? "true" : "false") ] // If it's a FIFO topic with content-based deduplication, set the // "ContentBasedDeduplication" attribute. if isContentBasedDeduplication { attributes["ContentBasedDeduplication"] = "true" } // Create the topic and retrieve the ARN. let output = try await snsClient.createTopic( input: CreateTopicInput( attributes: attributes, name: topicName ) ) guard let topicArn = output.topicArn else { print("No topic ARN returned!") return } print(""" Topic '\(topicName) has been created with the topic ARN \(topicArn)." """ ) print(rowOfStars) // 3. Create an SQS queue. Append ".fifo" to the name if one of the // FIFO topic configurations was chosen, and set "FifoQueue" to // "true" if the topic is FIFO. print(""" Next, you will create two SQS queues that will be subscribed to the topic you just created.\n """ ) let q1Url = try await createQueue(prompt: "Enter the name of the first queue: ", sqsClient: sqsClient, isFIFO: isFIFO) guard let q1Url else { print("Unable to create queue 1!") return } // 4. Get the SQS queue's ARN attribute using `GetQueueAttributes`. let q1Arn = try await getQueueARN(sqsClient: sqsClient, queueUrl: q1Url) guard let q1Arn else { print("Unable to get ARN of queue 1!") return } print("Got queue 1 ARN: \(q1Arn)") // 5. Attach an AWS IAM policy to the queue using // `SetQueueAttributes`. try await setQueuePolicy(sqsClient: sqsClient, queueUrl: q1Url, queueArn: q1Arn, topicArn: topicArn) // 6. Subscribe the SQS queue to the SNS topic. Set the topic ARN in // the request. Set the protocol to "sqs". Set the queue ARN to the // ARN just received in step 5. For FIFO topics, give the option to // apply a filter. A filter allows only matching messages to enter // the queue. var q1Attributes: [String:String]? = nil if isFIFO { print( """ If you add a filter to this subscription, then only the filtered messages will be received in the queue. For information about message filtering, see https://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html For this example, you can filter messages by a 'tone' attribute. """ ) let subPrompt = """ Would you like to filter messages for the first queue's subscription to the topic \(topicName) (Y/N)? """ if (yesNoRequest(prompt: subPrompt)) { q1Attributes = buildFilterAttributes() } } let sub1Output = try await snsClient.subscribe( input: SubscribeInput( attributes: q1Attributes, endpoint: q1Arn, protocol: "sqs", topicArn: topicArn ) ) guard let q1SubscriptionArn = sub1Output.subscriptionArn else { print("Invalid subscription ARN returned for queue 1!") return } // 7. Repeat steps 3-6 for the second queue. let q2Url = try await createQueue(prompt: "Enter the name of the second queue: ", sqsClient: sqsClient, isFIFO: isFIFO) guard let q2Url else { print("Unable to create queue 2!") return } let q2Arn = try await getQueueARN(sqsClient: sqsClient, queueUrl: q2Url) guard let q2Arn else { print("Unable to get ARN of queue 2!") return } print("Got queue 2 ARN: \(q2Arn)") try await setQueuePolicy(sqsClient: sqsClient, queueUrl: q2Url, queueArn: q2Arn, topicArn: topicArn) var q2Attributes: [String:String]? = nil if isFIFO { let subPrompt = """ Would you like to filter messages for the second queue's subscription to the topic \(topicName) (Y/N)? """ if (yesNoRequest(prompt: subPrompt)) { q2Attributes = buildFilterAttributes() } } let sub2Output = try await snsClient.subscribe( input: SubscribeInput( attributes: q2Attributes, endpoint: q2Arn, protocol: "sqs", topicArn: topicArn ) ) guard let q2SubscriptionArn = sub2Output.subscriptionArn else { print("Invalid subscription ARN returned for queue 1!") return } // 8. Let the user publish messages to the topic, asking for a message // body for each message. Handle the types of topic correctly (SEE // MVP INFORMATION AND FIX THESE COMMENTS!!! print("\n\(rowOfStars)\n") var first = true repeat { var publishInput = PublishInput( topicArn: topicArn ) publishInput.message = stringRequest(prompt: "Enter message text to publish: ") // If using a FIFO topic, a message group ID must be set on the // message. if isFIFO { if first { print(""" Because you're using a FIFO topic, you must set a message group ID. All messages within the same group will be received in the same order in which they were published.\n """ ) } publishInput.messageGroupId = stringRequest(prompt: "Enter a message group ID for this message: ") if !isContentBasedDeduplication { if first { print(""" Because you're not using content-based deduplication, you must enter a deduplication ID. If other messages with the same deduplication ID are published within the same deduplication interval, they will not be delivered. """ ) } publishInput.messageDeduplicationId = stringRequest(prompt: "Enter a deduplication ID for this message: ") } } // Allow the user to add a value for the "tone" attribute if they // wish to do so. var messageAttributes: [String:SNSClientTypes.MessageAttributeValue] = [:] let attrValSelection = menuRequest(prompt: "Choose a tone to apply to this message.", options: attrValues) if attrValSelection != 0 { let val = SNSClientTypes.MessageAttributeValue(dataType: "String", stringValue: attrValues[attrValSelection]) messageAttributes["tone"] = val } publishInput.messageAttributes = messageAttributes // Publish the message and display its ID. let publishOutput = try await snsClient.publish(input: publishInput) guard let messageID = publishOutput.messageId else { print("Unable to get the published message's ID!") return } print("Message published with ID \(messageID).") first = false // 9. Repeat step 8 until the user says they don't want to post // another. } while (yesNoRequest(prompt: "Post another message (Y/N)? ")) // 10. Display a list of the messages in each queue by using // `ReceiveMessage`. Show at least the body and the attributes. print(rowOfStars) print("Contents of queue 1:") let q1DeleteList = try await receiveAndListMessages(sqsClient: sqsClient, queueUrl: q1Url) print("\n\nContents of queue 2:") let q2DeleteList = try await receiveAndListMessages(sqsClient: sqsClient, queueUrl: q2Url) print(rowOfStars) returnRequest(prompt: "\nPress return to clean up: ") // 11. Delete the received messages using `DeleteMessageBatch`. print("Deleting the messages from queue 1...") try await deleteMessageList(sqsClient: sqsClient, queueUrl: q1Url, deleteList: q1DeleteList) print("\nDeleting the messages from queue 2...") try await deleteMessageList(sqsClient: sqsClient, queueUrl: q2Url, deleteList: q2DeleteList) // 12. Unsubscribe and delete both queues. print("\nUnsubscribing from queue 1...") _ = try await snsClient.unsubscribe( input: UnsubscribeInput(subscriptionArn: q1SubscriptionArn) ) print("Unsubscribing from queue 2...") _ = try await snsClient.unsubscribe( input: UnsubscribeInput(subscriptionArn: q2SubscriptionArn) ) print("Deleting queue 1...") _ = try await sqsClient.deleteQueue( input: DeleteQueueInput(queueUrl: q1Url) ) print("Deleting queue 2...") _ = try await sqsClient.deleteQueue( input: DeleteQueueInput(queueUrl: q2Url) ) // 13. Delete the topic. print("Deleting the SNS topic...") _ = try await snsClient.deleteTopic( input: DeleteTopicInput(topicArn: topicArn) ) } } /// The program's asynchronous entry point. @main struct Main { static func main() async { let args = Array(CommandLine.arguments.dropFirst()) do { let command = try ExampleCommand.parse(args) try await command.runAsync() } catch { ExampleCommand.exit(withError: error) } } }