A Slice of Scala

Preview:

DESCRIPTION

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.

Citation preview

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Kevin O’Neill CTO PlayUp

A Slice of Scala

@kevinoneill

August 2013

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

A little History

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Engage & Entertain Around Live Sport

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Mobile Games

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

SMS Based

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Number of Runs

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Complex

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Carrier Integration

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Smart Phone Revolution

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Move from a Content Creator to a Content

Enabler

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Top 10 in Engagement

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Over 3 Million Likes

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

30% - 40% Active

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Manually Curated

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

We Know there's an Opportunity

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

October 2011

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Technologist at Large

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Version 2

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Rebuild Based on Hypermedia*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Same Feature Set

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Different Skin

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

iOS

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Android

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Ruby

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Version 3

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Platform Extensions

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Tiles

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Third Party

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Ticketing

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Ruby

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

PHP

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Version 4

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Engagement Too Deep

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Streams

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Graph Storage

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Story

League

Region

Team Story

Team

Story

League

TeamStory

Story

User

Story

about

about

about

aboutabout

follows competes in

competes in

follows

competes in

Region

follows

Team

Story

competes in

about

about

User

follows

follows

Story

Contest

about

plays in

plays in

Story

about

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Value is in the Connections

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Ruby

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

50 Seconds

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Cypher Processing too much Data

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Java plugin

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

5 Seconds

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

10 Times too Long*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Aiming Around 200ms

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Time to Change

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Scala

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Just Couldn't Face Java

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Some Experience with it on a Large Project

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

The Stack

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Scala 2.10.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

akka 2.1.x*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Spray M8+

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Play 2.1.x*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Other Bits

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Neo4j 1.9.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Scalaz 7.0.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Blueprints 2.4.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Scala Test 2.0.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Scala Check 1.10.x

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

SBT 1.12.x*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Systems

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Two akka Services*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Graph Service

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Sports Connect

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Fanbase Connect*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

One Spray Server

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Hypermedia API

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

One Play Application*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

HTML Front End

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Admin Front End*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

JSON Generation

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Problem : How do you isolate environment

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Lambda: The Ultimate Dependency Injection

Framework

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Did my Head in

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

So what if …

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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) }

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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)  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

urlForIdentity

protected  def  urlForIdentity(identity:ResourceIdentity)    :  EnvironmentReader[JValue]  =  for  { !    r  <-­‐  URLResolverSetting.resolve(identity)      href  <-­‐  mapOrJNothing(r)  {        ref  :  String  =>  pure(JString(ref))    } !}  yield  href  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

URLResolverSetting

case  class  URLResolverSetting(value:  Resolver[String])    extends  EnvironmentSetting[Resolver[String]]  {          val  key  =  "url-­‐resolver"  }  !object  URLResolverSetting  extends  ResolverSetting  ({      case  setting:  URLResolverSetting  =>  setting.value  })  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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      }  }  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Wooh … That's far more

complex than my … blah blah in blah

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Yup

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Nope

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Remember I mentioned Runars talk

did my head in.*

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

It's actually really easy to work with

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Each components is responsible for one

thing

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Combining components is trivial

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

You spend most of your time doing

simple, safe, composition

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Spray

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Elephants all the way down

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

The Language

val  route  =  {          language  {  lang  =>                  implicit  val  env  =  RequestEnvironmentProvider(                    EnvironmentConfig(language  =  Some(lang))                ) … !}

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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)  }  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Creating a Responsedef  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        }      }    }  }      }  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

A Little akka Helper

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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)          }  }

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

akka

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Topic Management

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

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)          }      }  !… }

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Receive

def  receive  =  PartialFunction.empty

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Pending

def  pending  :  Actor.Receive  =  {      case  message  @  LinkStory(story,  identity)        if  identity  ==  topic  =>  {              stash()          }  !    case  identity  if  identity  ==  topic  =>  {          unstashAll()          become(active)      }  }

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Active

   def  active  :  Actor.Receive  =  {          case  LinkStory(story,  identity)  if  identity  ==  topic  =>  {              gs.write(associateWithSubject(story,  topic))          }      }  

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Baby Steps

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Challenges

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

As the Carpenters said …

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

We've Only Just Begun

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Data Load

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Sparsity

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Propagation

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Friends

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

500 Topics

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

10,000,000 Nodes

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

1,000,000 Topics

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

10,000,000,000 Nodes

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Time Series Data

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Distribution

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Need to change the way you think about

services

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Actors are not Queues

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Monitoring is Hard

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

"Real Time"

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Balancing Load vs Caching

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Two Hard Problems

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Naming

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Cache Invalidation

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Off by One Errors

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Caching Stuff is Easy

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Invalidation is Hard

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Limited Use

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Just be Fast

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Payments

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Ticketing

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

À la carte

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Cross Platform

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Come Join Us

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Disrupting

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Looking for the 'X' factor

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Hiring Selectively

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Talk to Me or Andrea

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

You miss 100 percent of the the shots you don't take

– Wayne Gretzky

Melbourne Scala User Group - August 2013Kevin O’Neill - CTO PlayUp - @kevinoneill

Kevin O’NeillCTO - PlayUp

kevin@playup.com@kevinoneill

Questions?

Recommended