def partitionDocumentStorage(successMessage: SuccessMessage) =
successMessage.message.request match {
case InlineDocumentRequest(_) => 0
case ImportDocumentRequest(_) => 1
case RegisterDocumentRequest(_) => 2
case _ => 3}
val documentStorageSplitter = builder.add(Partition[SuccessMessage](4, partitionDocumentStorage))
val inlineDocumentRequest = builder.add(Flow[SuccessMessage].map {
case successMessage => successMessage.message.request match {
case inlineDoc#InlineDocumentRequest(_) => (inlineDoc, successMessage)
}
})
val inlineDocSource = Source.fromGraph(GraphDSL.create() { implicit builder =>
val to = documentStorageSplitter.out(0) ~>
inlineDocumentRequest ~>
inlineDocumentPartitionTransform
SourceShape(to.outlet)
})
...
I use Partition[T] to split the flow, it compiles well but when i start the service, i have
[error] java.lang.IllegalArgumentException: [Partition.out0] is already connected
[error] at akka.stream.scaladsl.GraphDSL$Builder.addEdge(Graph.scala:1565)
[error] at akka.stream.scaladsl.GraphDSL$Implicits$CombinerBase.$tilde$greater(Graph.scala:1722)
[error] at akka.stream.scaladsl.GraphDSL$Implicits$CombinerBase.$tilde$greater$(Graph.scala:1721)
Someone has the same issue ?
Related
My this piece of code complaining about type mismatch; found: Unit required: scala.concurrent.Future , whereas I am returning a Future . I am very new in Scala not sure what I am missing here .
val records: List[CommittableRecord[Either[Throwable, MyEvent]]] = ???
records.mapAsync(1){ x =>
val res = (x.value match {
case Right(event:MyEvent) =>
val future = getTask(event.get("task").getOrElse(""))
//future => Future[Try[Int]]
val k = future.map {
case Success(value) => value
case Failure(exception) => 0
}
//k => Future[Int]
})
}
Variable assignment returns Unit, just remove val k = or put k at the end
I have this piece of code in the PLAY framework
def ws: WebSocket = WebSocket.acceptOrResult[JsValue, JsValue] { rh =>
implicit val req = Request(rh, AnyContentAsEmpty)
silhouette.SecuredRequestHandler { securedRequest =>
Future.successful(HandlerResult(Ok, Some(securedRequest.identity)))
}.map {
case HandlerResult(_, Some(_)) => wsFutureFlow(rh).map { flow => Right(flow) }
case HandlerResult(r, None) => Left(r)
}
// wsFutureFlow(rh).map { flow =>
// Right(flow)
// }.recover {
// case e: Exception =>
// logger.error("Cannot create websocket", e)
// val jsError = Json.obj("error" -> "Cannot create websocket")
// val result = InternalServerError(jsError)
// Left(result)
// }
}
private def wsFutureFlow(request: RequestHeader): Future[Flow[JsValue, JsValue, NotUsed]] = {
// Use guice assisted injection to instantiate and configure the child actor.
implicit val timeout = Timeout(1.second) // the first run in dev can take a while :-(
val future: Future[Any] = userParentActor ? UserParentActor.Create(request.id.toString)
val futureFlow: Future[Flow[JsValue, JsValue, NotUsed]] = future.mapTo[Flow[JsValue, JsValue, NotUsed]]
futureFlow
}
I'm a beginner to scala and essentially what I am trying to do is authenticate the request to the ws endpoint. If it's authenticated, then I give it a Flow[JsValue, JsValue, None] to act as the WebSocket connection otherwise I need to return a Result. The issue I am having is I can't quite figure out how to design the futures correctly. For context, here is the authenticated endpoint example in the documentation https://www.silhouette.rocks/docs/endpoints.
The line that doesn't compile is the below:
case HandlerResult(_, Some(_)) => wsFutureFlow(rh).map { flow => Right(flow) }
The function I'm passing to WebSocket.acceptOrResult[JsValue, JsValue] needs to return a Future[Either[Result, Flow[In, Out, _]]]. As you can see in the line that doesn't compile I'm trying to Right() the Flow, but it's not quite right. The commented section does compile though. Here is the compile error
[error] /home/julian/IdeaProjects/crypto-bloomberg-app/app-admin/src/main/scala/admin/controllers/HomeController.scala:32:62: type mismatch;
[error] found : scala.concurrent.Future[scala.util.Right[Nothing,akka.stream.scaladsl.Flow[play.api.libs.json.JsValue,play.api.libs.json.JsValue,akka.NotUsed]]]
[error] required: Either[play.api.mvc.Result,akka.stream.scaladsl.Flow[play.api.libs.json.JsValue, play.api.libs.json.JsValue, _]]
[error] case HandlerResult(_, Some(_)) => wsFutureFlow(rh).map { flow => Right(flow) }
[error] ^
[error] one error found
[error] (app-admin/compile:compileIncremental) Compilation failed
[error] Total time: 4 s, completed 21-Mar-2018 4:29:04 PM
Thanks
Use flatMap instead of map:
def ws: WebSocket = WebSocket.acceptOrResult[JsValue, JsValue] { rh =>
implicit val req = Request(rh, AnyContentAsEmpty)
silhouette.SecuredRequestHandler { securedRequest =>
Future.successful(HandlerResult(Ok, Some(securedRequest.identity)))
} flatMap {
case HandlerResult(_, Some(_)) => wsFutureFlow(rh).map(Right(_))
case HandlerResult(r, None) => Future.successful(Left(r))
}
}
Already asked at scala-user, didn't get an answer.
I expect the below to compile:
trait Elems {
trait Dummy
abstract class Elem[A] extends Serializable with Dummy
class BaseElem[A] extends Elem[A]
implicit val BooleanElement: Elem[Boolean] = new BaseElem[Boolean]
implicit val ByteElement: Elem[Byte] = new BaseElem[Byte]
implicit val ShortElement: Elem[Short] = new BaseElem[Short]
implicit val IntElement: Elem[Int] = new BaseElem[Int]
implicit val LongElement: Elem[Long] = new BaseElem[Long]
implicit val FloatElement: Elem[Float] = new BaseElem[Float]
implicit val DoubleElement: Elem[Double] = new BaseElem[Double]
implicit val UnitElement: Elem[Unit] = new BaseElem[Unit]
implicit val StringElement: Elem[String] = new BaseElem[String]
implicit val CharElement: Elem[Char] = new BaseElem[Char]
}
trait GoodMatch { self: Elems =>
private def boxed_class(e: Elem[_]): Class[_] = e match {
case BooleanElement => classOf[java.lang.Boolean]
case ByteElement => classOf[java.lang.Byte]
case ShortElement => classOf[java.lang.Short]
case IntElement => classOf[java.lang.Integer]
case LongElement => classOf[java.lang.Long]
case FloatElement => classOf[java.lang.Float]
case DoubleElement => classOf[java.lang.Double]
case CharElement => classOf[java.lang.Character]
case _ => ???
}
}
abstract class BadMatch[+A <: Elems](scalan: A) {
import scalan._
protected def toLuaValue(x: Any, eX: Elem[_]): String = eX match {
case UnitElement => ""
case _ => ???
}
// should check type before conversion?
protected def fromLuaValue[B](lv: Any, eA: Elem[B]): B = (eA match {
case UnitElement => ()
}).asInstanceOf[B]
}
And GoodMatch does, but BadMatch fails (in Scala 2.11.8):
[error] /tmp/rendererqu0xjasKpX/src/main/scala/test.scala:48: type mismatch;
[error] found : BadMatch.this.scalan.Elem[Unit]
[error] required: BadMatch.this.scalan.Elem[_$3] where type _$3
[error] case UnitElement => ""
[error] ^
[error] /tmp/rendererqu0xjasKpX/src/main/scala/test.scala:63: type mismatch;
[error] found : BadMatch.this.scalan.Elem[Unit]
[error] required: BadMatch.this.scalan.Elem[B]
[error] case UnitElement => ()
[error] ^
Removing with Dummy makes BadMatch compile as well.
Is this a Scala bug? If so, is it a known one?
Yes, it's a Scala compiler bug: https://issues.scala-lang.org/browse/SI-9779.
Hello,
def getMessages(code:String,offset:Option[Int]) = Action.async(parse.json){request =>
val forPC = (request.body \ "forPC").asOpt[Boolean]
Talk.findByCode(code).map(_ match{
case Success(talk) =>
val talkId = talk.id
Message.getMessages(talkId=talkId,offset=offset.getOrElse(0), forPC ).map(_ match {
case Seq(Tables.Messages) => Ok("Cool")
case _ => Ok("No")
})
case Failure(e) =>
Logger.error(e.getMessage)
NotAcceptable(Json.toJson(Map(
"error" -> "failed"
)))
})
And in the Model i have :
// talks by Code
def findByCode(code: String, conferenceid : Int) = {
val query = talks.filter(talk => talk.conferenceId === conferenceid && talk.code === code)
db.run(query.result.head.asTry)
}
def getMessages(talkId:Int ,offset:Int, forPC: Option[Boolean]) = {
val forPCVal = forPC.getOrElse(false)
//ordering by talkId because it's faster than timestamp
val query = messages.filter(msg => msg.talkId === talkId && msg.forpc === forPCVal ).sortBy(_.idmessage.desc).drop(offset).take(10).result
db.run(query)
}
So Play is waiting for Result ( Action ) , and it displays this error :
type mismatch;
found : scala.concurrent.Future[play.api.mvc.Result]
required: play.api.mvc.Result
and this :
Can anyone explain to why this error and give me some hints to solve it ?
Thank you
It seems that your Message.getMessages returns a Future[Something] which in turn make your whole match block attempt to return a Future[Result] in the Success case and a Result in the Failure case.
You should try something like the following (notice the flatMap that makes sure you end up with Future[Result] and not a Future[Future[Result]])
Talk.findByCode(code).flatMap(_ match{
case Success(talk) =>
val talkId = talk.id
Message.getMessages(talkId=talkId,offset=offset.getOrElse(0), forPC ).map(_ match {
case Seq(Tables.Messages) => Ok("Cool")
case _ => Ok("No")
})
case Failure(e) =>
Logger.error(e.getMessage)
Future.successful(NotAcceptable(Json.toJson(Map(
"error" -> "failed"
))))
})
The following code compiles and works as expected...
def find1(selector: JsValue): Future[Seq[String]]
def find2(selector: JsValue): Future[Seq[String]]
find1(Json.obj("name" -> "Joe")) zip
find2(Json.obj("name" -> "Tim")) map { case (result1, result2) =>
val result = result1 ++ result2
...
}
... but if I add recover to handle possible errors like this...
find1(Json.obj("name" -> "Joe")) zip
find2(Json.obj("name" -> "Tim")) map { case (result1, result2) =>
val result = result1 ++ result2
...
}.recover { case e =>
...
}
... I always get the following error:
[error] /home/j3d/test/TestController.scala:558: missing parameter type for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error] find2(Json.obj("name" -> "Tim")) map { case (result1, result2) =>
[error] ^
[error] one error found
I've tried to specify the types of result1 and result2 like this...
find1(Json.obj("name" -> "Joe")) zip
find2(Json.obj("name" -> "Tim")) map { case (result1: Seq[String], result2: Seq[String]) =>
val result = result1 ++ result2
...
}.recover { case e =>
...
}
... but nothing changes, i.e. it only compiles without recover. Am I missing something?
use the operator notation throughout.
find1(Json.obj("name" -> "Joe")) zip
find2(Json.obj("name" -> "Tim")) map { case (result1, result2) =>
val result = result1 ++ result2
...
} recover { case e => // removed the '.'
...
}