
org.elasticmq.rest.sqs.CreateQueueDirectives.scala Maven / Gradle / Ivy
package org.elasticmq.rest.sqs
import org.elasticmq._
import org.elasticmq.actor.reply._
import org.elasticmq.msg.{LookupQueue, CreateQueue => CreateQueueMsg}
import org.elasticmq.rest.sqs.Action.CreateQueue
import org.elasticmq.rest.sqs.Constants._
import org.elasticmq.rest.sqs.ParametersUtil._
import org.elasticmq.rest.sqs.SQSException.ElasticMQErrorOps
import org.elasticmq.rest.sqs.directives.ElasticMQDirectives
import org.elasticmq.rest.sqs.model.RedrivePolicy.BackwardCompatibleRedrivePolicy
import org.elasticmq.rest.sqs.model.RequestPayload
import spray.json.DefaultJsonProtocol._
import spray.json.JsonParser.ParsingException
import spray.json._
import java.time.Duration
import scala.async.Async._
import scala.concurrent.Future
import scala.xml.Elem
trait CreateQueueDirectives {
this: ElasticMQDirectives with QueueURLModule with SQSLimitsModule with ResponseMarshaller =>
def createQueue(p: RequestPayload)(implicit marshallerDependencies: MarshallerDependencies) = {
p.action(CreateQueue) {
rootPath {
val requestParams = p.as[CreateQueueActionRequest]
val attributes = requestParams.Attributes.getOrElse(Map.empty)
val redrivePolicy =
try {
import org.elasticmq.rest.sqs.model.RedrivePolicyJson._
attributes
.get(RedrivePolicyParameter)
.map(_.parseJson.convertTo[BackwardCompatibleRedrivePolicy])
} catch {
case e: DeserializationException =>
logger.warn("Cannot deserialize the redrive policy attribute", e)
throw SQSException.invalidAttributeValue()
case e: ParsingException =>
logger.warn("Cannot parse the redrive policy attribute", e)
throw SQSException.invalidAttributeValue()
}
async {
redrivePolicy match {
case Some(rd) =>
if (await(queueManagerActor ? LookupQueue(rd.queueName)).isEmpty) {
throw SQSException.nonExistentQueue
}
if (rd.maxReceiveCount < 1 || rd.maxReceiveCount > 1000) {
throw SQSException.invalidAttributeValue()
}
case None =>
}
val secondsVisibilityTimeoutOpt = attributes.parseOptionalLong(VisibilityTimeoutParameter)
val secondsDelayOpt = attributes.parseOptionalLong(DelaySecondsAttribute)
val secondsReceiveMessageWaitTimeOpt = attributes.parseOptionalLong(ReceiveMessageWaitTimeSecondsAttribute)
val isFifo = attributes.get("FifoQueue").contains("true")
val hasContentBasedDeduplication = attributes.get("ContentBasedDeduplication").contains("true")
val newQueueData = CreateQueueData(
requestParams.QueueName,
secondsVisibilityTimeoutOpt.map(sec => MillisVisibilityTimeout.fromSeconds(sec)),
secondsDelayOpt.map(sec => Duration.ofSeconds(sec)),
secondsReceiveMessageWaitTimeOpt.map(sec => Duration.ofSeconds(sec)),
None,
None,
redrivePolicy.map(rd => DeadLettersQueueData(rd.queueName, rd.maxReceiveCount)),
isFifo,
hasContentBasedDeduplication,
tags = requestParams.tags.getOrElse(Map.empty)
)
secondsReceiveMessageWaitTimeOpt.foreach(messageWaitTime =>
Limits
.verifyMessageWaitTime(messageWaitTime, sqsLimits)
.fold(
_ =>
throw SQSException
.invalidParameter(messageWaitTime.toString, ReceiveMessageWaitTimeSecondsAttribute),
identity
)
)
await(lookupOrCreateQueue(newQueueData))
queueURL(requestParams.QueueName) { url => complete(CreateQueueResponse(url)) }
}
}
}
}
private def lookupOrCreateQueue[T](newQueueData: CreateQueueData): Future[Unit] = {
async {
val createResult = await(queueManagerActor ? CreateQueueMsg(newQueueData))
createResult match {
case Left(e: ElasticMQError) =>
throw e.toSQSException
case Right(_) =>
}
}
}
}
case class CreateQueueActionRequest(
QueueName: String,
Attributes: Option[Map[String, String]],
tags: Option[Map[String, String]]
)
object CreateQueueActionRequest {
implicit val requestJsonFormat: RootJsonFormat[CreateQueueActionRequest] = jsonFormat3(CreateQueueActionRequest.apply)
implicit val requestParamReader: FlatParamsReader[CreateQueueActionRequest] =
new FlatParamsReader[CreateQueueActionRequest] {
override def read(params: Map[String, String]): CreateQueueActionRequest = {
val attributes = AttributesModule.attributeNameAndValuesReader.read(params)
val tags = TagsModule.tagNameAndValuesReader.read(params)
val queueName = requiredParameter(params)(QueueNameParameter)
CreateQueueActionRequest(queueName, Some(attributes), Some(tags))
}
}
}
case class CreateQueueResponse(QueueUrl: String)
object CreateQueueResponse {
implicit val format: RootJsonFormat[CreateQueueResponse] = jsonFormat1(CreateQueueResponse.apply)
implicit val xmlSerializer: XmlSerializer[CreateQueueResponse] = new XmlSerializer[CreateQueueResponse] {
override def toXml(t: CreateQueueResponse): Elem =
{t.QueueUrl}
{EmptyRequestId}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy