Take Flight - Using Fly with the Play Framework
-
Upload
asher-glynn -
Category
Technology
-
view
521 -
download
0
description
Transcript of Take Flight - Using Fly with the Play Framework
![Page 2: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/2.jpg)
Themes
• Spaces
• Fly Object Space
• Flight
• Fly and Play Demo
• Roundup
https://github.com/fly-object-space google : Fly
Object Space
![Page 3: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/3.jpg)
Spaces
Tuple Spaces – Linda - a co-ordination language
Presents a boundary for signals between …Threads - Processes – Machines - Systems
Minimal Interface 3 Essential Operations
Timely – Lease basedImmutable Only
![Page 4: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/4.jpg)
Fly
Operations
op write(entry, lease ): leaseop read(template, lease): Option[entry]op take(template, lease): Option[entry]
Query By Template Template Entry
Car(Some("Red"), None) == Car(Some("Red"), Some(5))
Car(None, Some(7)) != Car(Some("Red"), Some(5))
Car(None, None) == Car(Some("Red"), Some(2))
![Page 5: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/5.jpg)
def write(entry: AnyRef, lease: Long) : Long
Write Op
![Page 6: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/6.jpg)
def read[T<: AnyRef](template: T, lease: Long): Option[T]
Read Op
![Page 7: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/7.jpg)
def take[T<: AnyRef](template: T, lease: Long): Option[T]
Take Op
![Page 8: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/8.jpg)
Time Passes
Leases Expire
![Page 9: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/9.jpg)
Design Diamond
Minimise Interface
Minimise Uses
Complexity
![Page 10: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/10.jpg)
![Page 11: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/11.jpg)
![Page 12: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/12.jpg)
Flight
Idea : Advances in core Scala libraries can be applied to Fly
FuturesOps are time constrained Ops may succeed or fail
FiniteDurations Express only finite leases in nanos (prev
millis)
Make a JVM local ( inter-thread ) version that has the new features as a test bed.
![Page 13: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/13.jpg)
Flight
Image : Experimental Aircarft - Woolf Sverak – www.redbubble.com
Experimental
![Page 14: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/14.jpg)
Flight
write[T <: AnyRef](entry: T, lease: FiniteDuration) : Future[FiniteDuration] = …
read[T <: AnyRef](template: T, lease: FiniteDuration) :Future[T] = …
take[T <: AnyRef](template: T, lease: FiniteDuration) :Future[T] = …
![Page 15: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/15.jpg)
Flight – Example
import scala.concurrent.ExecutionContext.Implicits.globalimport scala.concurrent._import scala.concurrent.duration._import scala.language.postfixOps
import com.zink.fly.{ Flight => flt }
import com.zink.fly.examples.Price
//case class Price(symbol: Option[String], value: Option[Int])
![Page 16: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/16.jpg)
Flight – Example
val offer = Price(Some("ARM"),Some(123))
flt.write(offer, 100 seconds) onSuccess { case lease => println(s"Offer written for $lease")
}
"Offer written for 100 seconds"
![Page 17: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/17.jpg)
Flight – Example
val tmpl = Price(Some("ARM"), None)
flt.read(tmpl, 10 seconds) onComplete { case Success(entry) => println(entry) case Failure(t) => println("Sorry: " + t.getMessage) }
flt.take(tmpl, 10 seconds) onSuccess { case ent => println(s"Take matched $ent")
}
![Page 18: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/18.jpg)
Flight – Prop
val tmplArm = Price(Some("ARM"),Some(123))val tmplWlf = Price(Some("WLF"),Some(321))
val lse = 10 seconds
val futArm = flt.read(tmplArm, lse) val futWlf = flt.read(tmplWlf, lse)
(futArm zip futWlf) onComplete { case Success(e) => println("Deal") case Failure(t) => println("No Deal")}
![Page 19: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/19.jpg)
Fly – Demo
![Page 20: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/20.jpg)
Fly – Summary
• Timely Distributed Computing
• Core Scala Library only
• Work with everything else
• Flight (Experimental) Interface
• FiniteDurations
• Futures
https://github.com/fly-object-space google : Fly
Object Space
![Page 21: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/21.jpg)
Thanks
www.flyobjectspace.comwww.twitter.com/flyobjectspace
>
<----
--------->
<----
>
![Page 23: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/23.jpg)
Overview Used Play 2.0 framework last year for startup Simple as possible – database and app servers Adapted to leverage Fly
![Page 24: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/24.jpg)
Starting out with play My journey
Copy an example Write logic in Action handlers Write DAO layer Discover you need an API Rewrite with quite a lot of swearing
![Page 25: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/25.jpg)
Abstracting the logic def Story[Request, Response](request: Request)
(logic: Connection => Response)
(implicit
validators: Seq[Request => Connection =>
Option[StoryError]],
reactors: Request => Response =>
Seq[Notification]) : Either[StoryError, Response] = {
… // Handle transaction
}
![Page 26: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/26.jpg)
Notes on Story abstraction Use request/response to (potentially) allow for
Akka distribution Handles overall transaction Validators execute sequentially prior to logic Reactor executes afterwards and
asynchronously writes notifications (if any) outside transaction context
Might have gone too far with implicits
![Page 27: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/27.jpg)
Notifications – with DB Put an adapter in but never did anything with
them Inserting into DB easy Querying reasonably painful NoSQL + Message Bus non trivial + complex
in fast moving startup Eventually disabled clients
![Page 28: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/28.jpg)
Notifications - With Fly Easy filters Get notifications without polling with
notifyWrite Can listen for interesting notifications out Trivial to implement via writeMany
![Page 29: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/29.jpg)
Closing auctions Auction system needs once only transaction Late auction is a bad one (unlikely to replay in
case of long outage) Only winning bids translate to transactions All nodes capable of closing transaction (for
redundancy)
![Page 30: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/30.jpg)
Closing auction - database Various options – easiest holding write lock
through a select for update
def pin(auctionId: UUID) = SQL ("Select * from TA_LOCKS where LOCKABLE = 'CLOSER' FOR UPDATE").execute
Locks out other nodes Could be finer grained Needs to have extra timeout code setup to
execute predictably Only once by virtue of changed state in DB (need
to check)
![Page 31: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/31.jpg)
Closing auction - Fly Contrast in Fly
fly.take(new models.auction.Auction(id = auctionId), 1000L)
Timeouts “for free” Only once by virtue of getting the take
![Page 32: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/32.jpg)
Integrating Fly Upgrade to current version of Play Add fly-java lib to /lib folder Add to dependencies in Build.sbt"com.flyobjectspace" %% "flyscala" % "2.1.0-SNAPSHOT”
And you are away
![Page 33: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/33.jpg)
Modifications for Fly Modify constructor of class for null fieldscase class Auction (
id : UUID = null,
accountId : UUID = null,
Add trait to indicate well formednesstrait WellFormed {
def isWellFormed : Boolean
}
![Page 34: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/34.jpg)
Modifications for Fly And add check for WellFormedness to each
story Add to validation chain Add to main part of story
Use notifications to invalidate cache
Write auctions to Fly, use take for once only
![Page 35: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/35.jpg)
Mistakes integrating with Fly Going nuts with Akka Messing up lease times and objects
disappearing Lease time too short Adding 2PC complexity to thinking rather than
working within the Fly idiom
![Page 36: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/36.jpg)
Running out of talent… Use either presence of object in Space to
indicate lock – or absence! For Auction – absence of auction object For Account modifications – presence of object
What if there are two What if the owner disappears What if the ownership changes on an edge (split
brain)
![Page 37: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/37.jpg)
Longer term modifications Modify Story abstraction to work with Futures Modify to work cleanly with account balances Keep database but redesign to work nicely
with Fly Keep notifications out of database Flatten notification structure
![Page 38: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/38.jpg)
Final note on notifications Currently using a deep classcase class Notice( id: UUID,
originatorId: UUID,
timestamp: Long,
attributes: Map[String, String],
to: Seq[UUID],
system: Boolean)
Will flatten to help leverage Fly filterscase class Notice (subject: String = null,
_predicate: String = null,
_object = String)
And correlate on receivers
![Page 39: Take Flight - Using Fly with the Play Framework](https://reader035.fdocuments.net/reader035/viewer/2022070303/54919fc7b47959f2248b5732/html5/thumbnails/39.jpg)
Thanks