-
Notifications
You must be signed in to change notification settings - Fork 202
Implement DLQ redrive actions #987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
3a9a328
StartMessageMoveTask handling
micossow d5a561e
Merge branch 'master' into message-transfer
micossow a1f4230
add some logging, test cases
micossow c49c57e
implement CancelMessageMoveTask
micossow 508a567
fix missing ApproximateNumberOfMessagesMoved
micossow 6a06804
ListMessageMoveTasksDirectives and error handling
micossow b852f8e
fix scala 2.12 build
micossow 8a8e04d
refactor ListMessageMoveTasksDirectives
micossow 8cef0df
refactor QueueManagerActor
micossow c019784
refactor TaskId => TaskHandle
micossow 3b4b202
make MessageMoveTaskTest support both SDKs
micossow fe29868
fix build
micossow 1bc5257
Merge branch 'refs/heads/master' into message-transfer
micossow c927aed
refactoring
micossow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,32 +1,35 @@ | ||
| package org.elasticmq | ||
| import org.elasticmq.msg.MessageMoveTaskHandle | ||
|
|
||
| trait ElasticMQError { | ||
| sealed trait ElasticMQError { | ||
| val queueName: String | ||
| val code: String | ||
| val code: String // TODO: code should be handled in rest-sqs module | ||
| val message: String | ||
| } | ||
|
|
||
| class QueueAlreadyExists(val queueName: String) extends ElasticMQError { | ||
| final case class QueueAlreadyExists(val queueName: String) extends ElasticMQError { | ||
| val code = "QueueAlreadyExists" | ||
| val message = s"Queue already exists: $queueName" | ||
| } | ||
|
|
||
| case class QueueCreationError(queueName: String, reason: String) extends ElasticMQError { | ||
| val code = "QueueCreationError" | ||
| val message = s"Queue named $queueName could not be created because of $reason" | ||
| } | ||
|
|
||
| case class InvalidParameterValue(queueName: String, reason: String) extends ElasticMQError { | ||
| final case class InvalidParameterValue(queueName: String, reason: String) extends ElasticMQError { | ||
| val code = "InvalidParameterValue" | ||
| val message = reason | ||
| } | ||
|
|
||
| class MessageDoesNotExist(val queueName: String, messageId: MessageId) extends ElasticMQError { | ||
| val code = "MessageDoesNotExist" | ||
| val message = s"Message does not exist: $messageId in queue: $queueName" | ||
| } | ||
|
|
||
| class InvalidReceiptHandle(val queueName: String, receiptHandle: String) extends ElasticMQError { | ||
| final case class InvalidReceiptHandle(val queueName: String, receiptHandle: String) extends ElasticMQError { | ||
| val code = "ReceiptHandleIsInvalid" | ||
| val message = s"""The receipt handle "$receiptHandle" is not valid.""" | ||
| } | ||
|
|
||
| final case class InvalidMessageMoveTaskHandle(val taskHandle: MessageMoveTaskHandle) extends ElasticMQError { | ||
| val code = "ResourceNotFoundException" | ||
| val message = s"""The task handle "$taskHandle" is not valid or does not exist""" | ||
|
|
||
| override val queueName: String = "invalid" | ||
| } | ||
|
|
||
| final case class MessageMoveTaskAlreadyRunning(val queueName: String) extends ElasticMQError { | ||
| val code = "AWS.SimpleQueueService.UnsupportedOperation" | ||
| val message = s"""A message move task is already running on queue "$queueName"""" | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
core/src/main/scala/org/elasticmq/actor/QueueManagerActorStorage.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package org.elasticmq.actor | ||
| import org.apache.pekko.actor.{ActorContext, ActorRef} | ||
| import org.apache.pekko.util.Timeout | ||
| import org.elasticmq.QueueData | ||
|
|
||
| import scala.collection.mutable | ||
| import scala.concurrent.ExecutionContext | ||
| import scala.concurrent.duration.DurationInt | ||
|
|
||
| trait QueueManagerActorStorage { | ||
|
|
||
| def context: ActorContext | ||
|
|
||
| implicit lazy val ec: ExecutionContext = context.dispatcher | ||
| implicit lazy val timeout: Timeout = 5.seconds | ||
|
|
||
| case class ActorWithQueueData(actorRef: ActorRef, queueData: QueueData) | ||
| def queues: mutable.Map[String, ActorWithQueueData] | ||
| } |
92 changes: 92 additions & 0 deletions
92
core/src/main/scala/org/elasticmq/actor/QueueManagerMessageMoveOps.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package org.elasticmq.actor | ||
| import org.apache.pekko.actor.ActorRef | ||
| import org.apache.pekko.util.Timeout | ||
| import org.elasticmq.actor.reply._ | ||
| import org.elasticmq.msg.{CancelMovingMessages, GetQueueData, MessageMoveTaskHandle, StartMovingMessages} | ||
| import org.elasticmq.util.Logging | ||
| import org.elasticmq.{ElasticMQError, InvalidMessageMoveTaskHandle} | ||
|
|
||
| import scala.collection.mutable | ||
| import scala.concurrent.Future | ||
| import scala.util.{Failure, Success} | ||
|
|
||
| trait QueueManagerMessageMoveOps extends Logging { | ||
| this: QueueManagerActorStorage => | ||
|
|
||
| private val messageMoveTasks = mutable.HashMap[MessageMoveTaskHandle, ActorRef]() | ||
|
|
||
| def startMessageMoveTask( | ||
| sourceQueue: ActorRef, | ||
| sourceArn: String, | ||
| destinationQueue: Option[ActorRef], | ||
| destinationArn: Option[String], | ||
| maxNumberOfMessagesPerSecond: Option[Int] | ||
| )(implicit timeout: Timeout): ReplyAction[Either[ElasticMQError, MessageMoveTaskHandle]] = { | ||
| val self = context.self | ||
| val replyTo = context.sender() | ||
| (for { | ||
| destinationQueueActorRef <- destinationQueue | ||
| .map(Future.successful) | ||
| .getOrElse(findDeadLetterQueueSource(sourceQueue)) | ||
| result <- sourceQueue ? StartMovingMessages( | ||
| destinationQueueActorRef, | ||
| destinationArn, | ||
| sourceArn, | ||
| maxNumberOfMessagesPerSecond, | ||
| self | ||
| ) | ||
| } yield (result, destinationQueueActorRef)).onComplete { | ||
| case Success((result, destinationQueueActorRef)) => | ||
| result match { | ||
| case Right(taskHandle) => | ||
| logger.debug("Message move task {} => {} created", sourceQueue, destinationQueueActorRef) | ||
| messageMoveTasks.put(taskHandle, sourceQueue) | ||
| replyTo ! Right(taskHandle) | ||
| case Left(error) => | ||
| logger.error("Failed to start message move task: {}", error) | ||
| replyTo ! Left(error) | ||
| } | ||
| case Failure(ex) => logger.error("Failed to start message move task", ex) | ||
| } | ||
| DoNotReply() | ||
| } | ||
|
|
||
| def onMessageMoveTaskFinished(taskHandle: MessageMoveTaskHandle): ReplyAction[Unit] = { | ||
| logger.debug("Message move task {} finished", taskHandle) | ||
| messageMoveTasks.remove(taskHandle) | ||
| DoNotReply() | ||
| } | ||
|
|
||
| def cancelMessageMoveTask(taskHandle: MessageMoveTaskHandle): ReplyAction[Either[ElasticMQError, Long]] = { | ||
| logger.info("Cancelling message move task {}", taskHandle) | ||
| messageMoveTasks.get(taskHandle) match { | ||
| case Some(sourceQueue) => | ||
| val replyTo = context.sender() | ||
| sourceQueue ? CancelMovingMessages() onComplete { | ||
| case Success(numMessageMoved) => | ||
| logger.debug("Message move task {} cancelled", taskHandle) | ||
| messageMoveTasks.remove(taskHandle) | ||
| replyTo ! Right(numMessageMoved) | ||
| case Failure(ex) => | ||
| logger.error("Failed to cancel message move task", ex) | ||
| replyTo ! Left(ex) | ||
| } | ||
| DoNotReply() | ||
| case None => | ||
| ReplyWith(Left(new InvalidMessageMoveTaskHandle(taskHandle))) | ||
| } | ||
| } | ||
|
|
||
| private def findDeadLetterQueueSource(sourceQueue: ActorRef) = { | ||
| val queueDataF = sourceQueue ? GetQueueData() | ||
| queueDataF.map { queueData => | ||
| queues | ||
| .filter { case (_, data) => | ||
| data.queueData.deadLettersQueue.exists(dlqData => dlqData.name == queueData.name) | ||
| } | ||
| .head | ||
| ._2 | ||
| .actorRef | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.