I want to rewrite console IO application (sum counting) to messenger-bot. The StdIn.readLine() let me get the next input number in recursion.
object HelloCountBot extends TelegramBot with Polling with Commands {
def go(number: Long, chatId: Long): IO[Long] =
for {
input <- ??? /*here I need get the next number*/
acc <- input.toLong match {
case 0L => sendMessageMethodIO(chatId, "The sum is:") *> IO(0L)
case _ => go(number + 1, chatId)
}
acc <- IO(acc + input.toLong)
} yield acc
/*input point for every new message*/
override def onMessage(message: Message) = message.text match {
case Some(text) if text == "start" => go(1, message.chat.id)
.unsafeRunSync
}
def main(args: Array[String]): Unit = HelloCountBot.run()
}
How to organize code to get the next message inside recursion from method onMessage with Unit return.
I didn't find in https://github.com/bot4s/telegram any methods for receiving messages in the way that you want. So I think the best option is to create stateful bot as shown in this example: https://github.com/bot4s/telegram/blob/master/examples/src/StatefulBot.scala.
So if I understand your code correctly, it can be reorganized in the following way (trait PerChatState is taken from the link above):
object HelloCountBot
extends TelegramBot
with Polling
with Commands
with PerChatState[Long] {
override def onMessage(message: Message): Future[Unit] = {
implicit val msg = message
message.text match {
case Some(text) if text == "start" =>
Future {
setChatState(0L)
}
case Some(value) if value == "0" =>
withChatState {
sum =>
reply(s"The sum is ${sum.getOrElse(0L)}")
.map(_ => clearChatState)
}
case Some(value) =>
withChatState {
mayBeSum =>
Future {
mayBeSum.foreach(
sum => setChatState(sum + value.toLong)
)
}
}
}
}
def main(args: Array[String]): Unit = HelloCountBot.run()
}
It uses Futures, but you can rewrite it to IO, if you prefer.
Related
object test {
def multBylarge(input: Array[Int]): Int = {
var result=0
var lst: List[Int]=List()
if(input.length == 0) result+=1
else
for(elements <- input) {
lst = lst :+ elements
}
var newlst = lst.sortWith(_ > _)
result += newlst(0) * newlst(1)
result
}
def check2(input: Array[_]) = input.foreach {
case _:Int => multBylarge(_)
case _:Double => "this is a double array"
case _:Float => "this is a float array"
case _=> "this is not a value"
}
def main(args: Array[String]): Unit = {
println(check2(Array(1,3,5,1,3,4)))
}
}
this is my code, I just have no idea. It will be appreciated if anyone can help me with it. And I am not familiar with scala code, so if there has any other problem, please let me know.
Scaladoc is your friend. foreach has return type of scala.Unit (see also) which has only one value - ():
def foreach[U](f: (T) => U): Unit
Apply f to each element for its side effects.
So actual signature of your method is def check2(input: Array[_]): Unit
You can do the following:
Update check2 match on input rather then foreach (since multBylarge requires a array input anyway, foreach wouldn't work here since it iterates over every item in the array then tries to apply it to multBylarge)
Wrap result in a Either (You can think if it as Left = Failure and Right = Successful result)
Then match on the result in the main function to pretty print the result/error
object test {
def multBylarge(input: Array[Int]): Int = {
var result=0
var lst: List[Int]=List()
if(input.length == 0) result+=1
else
for(elements <- input) {
lst = lst :+ elements
}
var newlst = lst.sortWith(_ > _)
result += newlst(0) * newlst(1)
result
}
def check2(input: Array[_]): Either[String, Int] = input match {
case ints: Array[Int] => Right(multBylarge(ints))
case _: Array[Double] => Left("this is a double array")
case _: Array[Float] => Left("this is a float array")
case _. => Left("this is not a value")
}
def main(args: Array[String]): Unit = {
check2(Array(1,3,5,1,3,4)) match {
case Right(result) => println(s"Result is $result")
case Left(error) => println(s"Failed with $error")
}
}
}
An exercise on forComprehension, doesn't compile since returns Unit instead of Future[User]
(the task is to read using DAO and create new user using 2 parents)
I'm trying to return Future[User] from onComplete but fails (returns Unit).
def unbornUsingForComp(fatherId: String, motherId: String): Future[User] = {
val fatherUser: Future[Option[User]] = usersDao.read(fatherId)
val motherUser: Future[Option[User]] = usersDao.read(motherId)
val combinedLastName = for {
r1 <- fatherUser
r2 <- motherUser
} yield (r1, r2)
combinedLastName.onComplete {
case Success(x) => {
(x._1, x._2) match {
case (Some(u1), Some(u2)) => usersDao.create(User("JustRandomId", "JustRandomFirstName", u1.lastName + " - " +u2.lastName))
case _ => throw new Exception("One or more of the parents not Found")
}
}
case Failure(_) => {
throw new Exception("Exception raised inside the for comp.")
}
}
}
onComplete by design returns Unit which executes a side-effect and then discards
// Note that the returned value of `f` will be discarded.
def onComplete[U](f: Try[T] => U)(implicit executor: ExecutionContext): Unit
You are likely after something like
combinedLastName
.map { x => // do stuff with x }
.recover { case e => // handle exception }
Suppose I have the following code:
val futureInt1 = getIntAsync1();
val futureInt2 = getIntAsync2();
val futureSum = for {
int1 <- futureInt1
int2 <- futureInt2
} yield (int1 + int2)
val sum = Await.result(futureSum, 60 seconds)
Now suppose one of getIntAsync1 or getIntAsync2 takes a very long time, and it leads to Await.result throwing exception:
Caused by: java.util.concurrent.TimeoutException: Futures timed out after [60 seconds]
How am I supposed to know which one of getIntAsync1 or getIntAsync2 was still pending and actually lead to the timeout?
Note that here I'm merging 2 futures with zip, and this is a simple example for the question, but in my app I have this kind of code at different level (ie getIntAsync1 itself can use Future.zip or Future.sequence, map/flatMap/applicative)
Somehow what I'd like is to be able to log the pending concurrent operation stacktraces when a timeout occur on my main thread, so that I can know where are the bottlenexts on my system.
I have an existing legacy API backend which is not fully reactive yet and won't be so soon. I'm trying to increase response times by using concurrency. But since using this kind of code, It's become way more painful to understand why something takes a lot of time in my app. I would appreciate any tip you can provide to help me debugging such issues.
The key is realizing is that a the Future doesn't time out in your example—it's your calling thread which pauses for at most X time.
So, if you want to model time in your Futures you should use zipWith on each branch and zip with a Future which will contain a value within a certain amount of time. If you use Akka then you can use akka.pattern.after for this, together with Future.firstCompletedOf.
Now, even if you do, how do you figure out why any of your futures weren't completed in time, perhaps they depended on other futures which didn't complete.
The question boils down to: Are you trying to do some root-cause analysis on throughput? Then you should monitor your ExecutionContext, not your Futures. Futures are only values.
The proposed solution wraps each future from for block into TimelyFuture which requires timeout and name. Internally it uses Await to detect individual timeouts.
Please bear in mind this style of using futures is not intended for production code as it uses blocking. It is for diagnostics only to find out which futures take time to complete.
package xxx
import java.util.concurrent.TimeoutException
import scala.concurrent.{Future, _}
import scala.concurrent.duration.Duration
import scala.util._
import scala.concurrent.duration._
class TimelyFuture[T](f: Future[T], name: String, duration: Duration) extends Future[T] {
override def onComplete[U](ff: (Try[T]) => U)(implicit executor: ExecutionContext): Unit = f.onComplete(x => ff(x))
override def isCompleted: Boolean = f.isCompleted
override def value: Option[Try[T]] = f.value
#scala.throws[InterruptedException](classOf[InterruptedException])
#scala.throws[TimeoutException](classOf[TimeoutException])
override def ready(atMost: Duration)(implicit permit: CanAwait): TimelyFuture.this.type = {
Try(f.ready(atMost)(permit)) match {
case Success(v) => this
case Failure(e) => this
}
}
#scala.throws[Exception](classOf[Exception])
override def result(atMost: Duration)(implicit permit: CanAwait): T = {
f.result(atMost)
}
override def transform[S](ff: (Try[T]) => Try[S])(implicit executor: ExecutionContext): Future[S] = {
val p = Promise[S]()
Try(Await.result(f, duration)) match {
case s#Success(_) => ff(s) match {
case Success(v) => p.success(v)
case Failure(e) => p.failure(e)
}
case Failure(e) => e match {
case e: TimeoutException => p.failure(new RuntimeException(s"future ${name} has timed out after ${duration}"))
case _ => p.failure(e)
}
}
p.future
}
override def transformWith[S](ff: (Try[T]) => Future[S])(implicit executor: ExecutionContext): Future[S] = {
val p = Promise[S]()
Try(Await.result(f, duration)) match {
case s#Success(_) => ff(s).onComplete({
case Success(v) => p.success(v)
case Failure(e) => p.failure(e)
})
case Failure(e) => e match {
case e: TimeoutException => p.failure(new RuntimeException(s"future ${name} has timed out after ${duration}"))
case _ => p.failure(e)
}
}
p.future
}
}
object Main {
import scala.concurrent.ExecutionContext.Implicits.global
def main(args: Array[String]): Unit = {
val f = Future {
Thread.sleep(5);
1
}
val g = Future {
Thread.sleep(2000);
2
}
val result: Future[(Int, Int)] = for {
v1 <- new TimelyFuture(f, "f", 10 milliseconds)
v2 <- new TimelyFuture(g, "g", 10 milliseconds)
} yield (v1, v2)
val sum = Await.result(result, 1 seconds) // as expected, this throws exception : "RuntimeException: future g has timed out after 10 milliseconds"
}
}
If you are merely looking for informational metrics on which individual future was taking a long time (or in combination with others), your best bet is to use a wrapper when creating the futures to log the metrics:
object InstrumentedFuture {
def now() = System.currentTimeMillis()
def apply[T](name: String)(code: => T): Future[T] = {
val start = now()
val f = Future {
code
}
f.onComplete {
case _ => println(s"Future ${name} took ${now() - start} ms")
}
f
}
}
val future1 = InstrumentedFuture("Calculator") { /*...code...*/ }
val future2 = InstrumentedFuture("Differentiator") { /*...code...*/ }
You can check if a future has completed by calling its isComplete method
if (futureInt1.isComplete) { /*futureInt2 must be the culprit */ }
if (futureInt2.isComplete) { /*futureInt1 must be the culprit */ }
As a first approach i would suggest to lift your Future[Int] into Future[Try[Int]]. Something like that:
object impl {
def checkException[T](in: Future[T]): Future[Try[T]] =
in.map(Success(_)).recover {
case e: Throwable => {
Failure(new Exception("Error in future: " + in))
}
}
implicit class FutureCheck(s: Future[Int]) {
def check = checkException(s)
}
}
Then a small function to combine the results, something like that:
object test {
import impl._
val futureInt1 = Future{ 1 }
val futureInt2 = Future{ 2 }
def combine(a: Try[Int], b: Try[Int])(f: (Int, Int) => (Int)) : Try[Int] = {
if(a.isSuccess && b.isSuccess) {
Success(f(a.get, b.get))
}
else
Failure(new Exception("Error adding results"))
}
val futureSum = for {
int1 <- futureInt1.check
int2 <- futureInt2.check
} yield combine(int1, int2)(_ + _)
}
In futureSum you will have a Try[Int] with the integer or a Failure with the exception corresponding with the possible error.
Maybe this can be useful
val futureInt1 = getIntAsync1();
val futureInt2 = getIntAsync2();
val futureSum = for {
int1 <- futureInt1
int2 <- futureInt2
} yield (int1 + int2)
Try(Await.result(futureSum, 60 seconds)) match {
case Success(sum) => println(sum)
case Failure(e) => println("we got timeout. the unfinished futures are: " + List(futureInt1, futureInt2).filter(!_.isCompleted)
}
Let's say I have several receives and use become() unbecome() to switch between them. And all receives have some common message handling. Like this:
class Test extends Actor {
override def receive: Receive = first
def first: Receive = {
case "common" => // how to share?
println("common stuff")
case "second" =>
println("move to second")
context.become(second)
}
def second: Receive = {
case "common" => // how to share?
println("common stuff")
case "first" =>
println("move to first")
context.become(first)
}
}
Right now I see two ways:
Duplicate pattern match on "common" and
handle it in some function like handleCommon()
Merge receives like
this, but it doesn't seem right to me.
Here is an example of the second one:
class Test extends Actor {
override def receive: Receive = merge(common, first)
def common: Receive = {
case "common" =>
println("common stuff")
}
def first: Receive = {
case "second" =>
println("move to second")
context.become(merge(common, second))
}
def second: Receive = {
case "first" =>
println("move to first")
context.become(merge(common, first))
}
private def merge(functions: Receive*): Receive = {
case any =>
val fOpt = functions find (_.isDefinedAt(any))
if (fOpt.isDefined) {
fOpt foreach (f => f(any))
} else {
unhandled(any)
}
}
}
I'm sure there have to be a better way to do this. Is there?
You can use orElse:
def common: Receive = {
case "common" =>
println("common stuff")
}
def first: Receive = ({
case "second" =>
println("move to second")
context.become(second)
}: Receive) orElse common
def second: Receive = ({
case "first" =>
println("move to first")
context.become(first)
}: Receive) orElse common
Note that you have to explicitly annotate the type at the end of the expression because otherwise scala will infer Function1 and not Receive.
Here is the problem, I have a library which has a blocking method return Try[T]. But since it's a blocking one, I would like to make it non-blocking using Future[T]. In the future block, I also would like to compute something that's depend on the origin blocking method's return value.
But if I use something like below, then my nonBlocking will return Future[Try[T]] which is less convince since Future[T] could represent Failure[U] already, I would rather prefer propagate the exception to Future[T] is self.
def blockMethod(x: Int): Try[Int] = Try {
// Some long operation to get an Int from network or IO
throw new Exception("Network Exception") }
}
def nonBlocking(x: Int): Future[Try[Int]] = future {
blockMethod(x).map(_ * 2)
}
Here is what I tried, I just use .get method in future {} block, but I'm not sure if this is the best way to do that.
def blockMethod(x: Int): Try[Int] = Try {
// Some long operation to get an Int from network or IO
throw new Exception("Network Exception") }
}
def nonBlocking(x: Int): Future[Int] = future {
blockMethod(x).get * 2
}
Is this correct way to do that? Or there is a more scala idiomatic way to convert t Try[T] to Future[T]?
Here's an example that doesn't block, note that you probably want to use your own execution context and not scala's global context:
import scala.util._
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
object Main extends App {
def blockMethod(x: Int): Try[Int] = Try {
// Some long operation to get an Int from network or IO
Thread.sleep(10000)
100
}
def tryToFuture[A](t: => Try[A]): Future[A] = {
future {
t
}.flatMap {
case Success(s) => Future.successful(s)
case Failure(fail) => Future.failed(fail)
}
}
// Initiate long operation
val f = tryToFuture(blockMethod(1))
println("Waiting... 10 seconds to complete")
// Should return before 20 seconds...
val res = Await.result(f, 20 seconds)
println(res) // prints 100
}
In my opinion: Try & Future is a monadic construction and idiomatic way to is monadic composition (for-comprehension):
That you need to define monad transformer for Future[Try[_]] (code for your library):
case class FutureT[R](run : Future[Try[R]])(implicit e: ExecutionContext) {
def map[B](f : R => B): FutureT[B] = FutureT(run map { _ map f })
def flatMap[B](f : R => FutureT[B]): FutureT[B] = {
val p = Promise[Try[B]]()
run onComplete {
case Failure(e) => p failure e
case Success(Failure(e)) => p failure e
case Success(Success(v)) => f(v).run onComplete {
case Failure(e) => p failure e
case Success(s) => p success s
}
}
FutureT(p.future)
}
}
object FutureT {
def futureTry[R](run : => Try[R])(implicit e: ExecutionContext) =
new FutureT(future { run })
implicit def toFutureT[R](run : Future[Try[R]]) = FutureT(run)
implicit def fromFutureT[R](futureT : FutureT[R]) = futureT.run
}
and usage example:
def blockMethod(x: Int): Try[Int] = Try {
Thread.sleep(5000)
if(x < 10) throw new IllegalArgumentException
else x + 1
}
import FutureT._
// idiomatic way :)
val async = for {
x <- futureTry { blockMethod(15) }
y <- futureTry { blockMethod(25) }
} yield (x + y) * 2 // possible due to using modan transformer
println("Waiting... 10 seconds to complete")
val res = Await.result(async, 20 seconds)
println(res)
// example with Exception
val asyncWithError = for {
x <- futureTry { blockMethod(5) }
y <- futureTry { blockMethod(25) }
} yield (x + y) * 2 // possible due to using modan transformer
// Can't use Await because will get exception
// when extract value from FutureT(Failure(java.lang.IllegalArgumentException))
// no difference between Failure produced by Future or Try
asyncWithError onComplete {
case Failure(e) => println(s"Got exception: $e.msg")
case Success(res) => println(res)
}
// Output:
// Got exception: java.lang.IllegalArgumentException.msg