Skip to content

cocodrino/futureEitherFinatra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#FUTURE EITHER MONAD FOR FINATRA SCALA

this is a small example about how compose futures and either monads in finatra/scala enabling a nice syntax sugar and terse error handling

this includes its own syntax for future either monad and some implementations of http error codes

for instance

Left(Unauthorized("you can't access here")) will return a 401 code with the text you can't access

also extend Futures with orFLeft (check the notZero method)

WHY TE UGLY ARROWS >>>

Because I love back to the future and it looks a bit like the arrow in the movie...and you know..back to the FUTURE...FUTURE monad...

![movie-title] (https://upload.wikimedia.org/wikipedia/id/7/71/Back_to_the_Future_logo.png)

object Cases {
   
   case class User(name: String, lang: String)	

   //return an User or some http error
   def getUser(name: String): >>>[User] = Future {
      //simulating retrieving from async db
      if (name == "donald")
         Left(Unauthorized("you can't access here"))
      else
         Right(User(name, "scala,clojure,js"))
   }

   //return an Int or some http error
   def getFriendsCountFromExternalServer(name: String): >>>[Int] = Future {
      //simulating contact external server 20% fails
      if (shuffle(1 to 5).head == 5)
         Left(Unavailable())
      else Right(shuffle(0 to 3).head)
   }

   def notImplementedTest: >>>[String] = Future {
      //just for fun  10% fails
      if (shuffle(1 to 10).head == 10) Left(NotImplemented()) else Right("OK")
   }


   //this extends the Future object...can be cool in some cases!!
   def notZero(v: Int): >>>[Int] = Future {
      //util for wrap when futures can fail....
      10 / v
   }.orFLeft(BadRequest("not friends?"))
}


class PingController extends Controller {

   import Cases._

   get("/blah") { r: Request =>
      //if some step fails return the http error for that step!!...just monad love!!!....
      (for {
         v <- <<<(getUser(r.getParam("name")))
         _ <- <<<(notZero(r.getIntParam("number")))

         _ <- <<<(notImplementedTest)
         n <- <<<(getFriendsCountFromExternalServer(v.name))

      } yield v).build(response) { r => response.ok.json(Map("user" -> r)) }

   }


}

About

a syntax sugar for future either for finatra

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages