A presentation given to the Melbourne Scala User Group in August 2013 talking about how PlayUp is using scala, akka, spray and neo4j to drive it's next generation of mobile sports applications.
Exploring the Future Potential of AI-Enabled Smartphone Processors
A Slice of Scala
1. A Slice of
Scala
August 2013
Kevin O’Neill
CTO PlayUp
@kevinoneill
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
2. Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
3. Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
4. Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
5. Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
6. A little History
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
7. Engage & Entertain
Around Live Sport
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
58. 5 Seconds
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
59. 10 Times too Long*
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
60. Aiming Around 200ms
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
61. Time to Change
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
62. If you hear a voice
within you say 'you
cannot paint,' then by
all means paint, and
that voice will be
silenced.
– Vincent Van Gogh
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
63. Scala
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
89. Problem : How do you
isolate environment
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
90. Lambda: The Ultimate
Dependency Injection
Framework
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
91. Did my Head in
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
92. So what if …
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
93. Environment Readers
type
Settings
=
Set[EnvironmentSetting[_]]
!
type
EnvironmentReader[+A]
=
scalaz.Reader[Settings,
A]
object
EnvironmentReader
{
def
apply[A](f:
Settings
=>
A):EnvironmentReader[A]
=
scalaz.Reader(f)
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
94. Writing an Identity
protected
def
writeResourcePointer(identity:
ResourceIdentity)
:
EnvironmentReader[JObject]
=
for
{
!
href
<-‐
urlForIdentity(identity)
contentType
=
identity.documentType
representations
<-‐
writeRepresentations(identity)
views
<-‐
viewsForIdentity(identity)
!
}
yield
(":href"
-‐>
href)
~
(":type"
-‐>
contentType)
~
(":uri"
-‐>
identity.uri)
~
representations
~
(":views"
-‐>
views)
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
95. urlForIdentity
protected
def
urlForIdentity(identity:ResourceIdentity)
:
EnvironmentReader[JValue]
=
for
{
!
r
<-‐
URLResolverSetting.resolve(identity)
href
<-‐
mapOrJNothing(r)
{
ref
:
String
=>
pure(JString(ref))
}
!
}
yield
href
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
96. URLResolverSetting
case
class
URLResolverSetting(value:
Resolver[String])
extends
EnvironmentSetting[Resolver[String]]
{
val
key
=
"url-‐resolver"
}
!
object
URLResolverSetting
extends
ResolverSetting
({
case
setting:
URLResolverSetting
=>
setting.value
})
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
97. ResolverSetting
class
ResolverSetting[T](
finder
:
PartialFunction[
EnvironmentSetting[_],
Resolver[T]])
{
!
def
resolve(identity
:
ResourceIdentity)
:
EnvironmentReader[Option[T]]
=
EnvironmentReader
{
settings
=>
for
{
resolver
<-‐
settings.collectFirst(finder)
result
<-‐
resolver.resolve(identity)
}
yield
result
}
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
98. Wooh …
That's far more
complex than my …
blah blah in blah
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
99. Yup
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
100. Nope
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
101. Remember I
mentioned Runars talk
did my head in.*
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
102. It's actually really
easy to work with
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
103. Each components is
responsible for one
thing
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
105. You spend most of
your time doing
simple, safe,
composition
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
106. Spray
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
107. Elephants all the way
down
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
108. The Language
val
route
=
{
language
{
lang
=>
implicit
val
env
=
RequestEnvironmentProvider(
EnvironmentConfig(language
=
Some(lang))
)
…
!
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
109. The Directive*
def
language:
Directive1[Lang]
=
{
headerValue
{
!
case
HttpHeader("accept-‐language",
langString)
=>
langString.split(',').headOption.flatMap(firstLanguage
=>
Lang.get(firstLanguage))
!
case
_
=>
None
!
}
|
provide(Lang.defaultLang)
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
110. Creating a Response
def
getStream(implicit
env:
RequestEnvironmentProvider):
Route
=
{
path("stream"
/
StreamPath)
{
case
(stream,
afterStory)
=>
read(FetchStream(stream,
afterStory))
{
stream
=>
val
streamEnv
=
environmentForStreamWithTopics(
env,
stream.identity.references
)
respondWithHeaders(
`Cache-‐Control`(`public`,
`max-‐age`(60)))
{
complete
{
implicit
val
criteriaMarshaller:
Marshaller[StoryStream]
=
resourceMarshaller(streamEnv)
stream
}
}
}
}
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
111. A Little akka Helper
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
112. Reading the Graph
def
read[T](message
:
GraphRequest[T])(f
:
T
=>
Route):Route
=
{
ctx
=>
val
response:
Future[T]
=
Graph.reader.ask(message).asInstanceOf[Future[T]]
response.map
{
case
Error(messages)
=>
{
ctx.complete(
InternalServerError,
messages.mkString("n")
)
}
case
result
=>
f(result)(ctx)
}
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
113. akka
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
115. Topic Actor
private
class
TopicActor
(system
:
GraphSystem,
topic
:
StreamComponentIdentity)
extends
GraphWorker(system)
with
Stash
{
!
override
def
preStart()
{
available(topic)
onAvailable
{
become(active)
}
onMissing
{
topicManager
!
UpdateTopic(topic)
become(pending)
}
}
!
…
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
116. Receive
def
receive
=
PartialFunction.empty
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
117. Pending
def
pending
:
Actor.Receive
=
{
case
message
@
LinkStory(story,
identity)
if
identity
==
topic
=>
{
stash()
}
!
case
identity
if
identity
==
topic
=>
{
unstashAll()
become(active)
}
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
118. Active
def
active
:
Actor.Receive
=
{
case
LinkStory(story,
identity)
if
identity
==
topic
=>
{
gs.write(associateWithSubject(story,
topic))
}
}
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
154. Talk to Me or Andrea
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
155. You miss 100 percent
of the the shots you
don't take
– Wayne Gretzky
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013
156. Questions?
Kevin O’Neill
CTO - PlayUp
@kevinoneill
kevin@playup.com
Kevin O’Neill - CTO PlayUp - @kevinoneill
Melbourne Scala User Group - August 2013