@flaviowbrasil 
Aficionado por open 
source 
Expert em 
escalabilidade 
Mestre Jedi Scala 
Prefere uma sessão de 
profiling a uma tarde 
na praia
@herval 
Fundador de Startups 
Dois Easter Eggs 
publicados 
Padawan Scala 
Tem um cachorro
A Nuvem de Som 
12 horas de novo conteúdo/ minuto 
350 milhões de usuários/mês 
12 milhões de horas ouvidas/mês 
1 usuário no espaço
Era uma vez uma startup...
Era uma vez uma startup... 
Uma base de código
Era uma vez uma startup... 
Uma base de código 
Um punhado de construtores
Move fast 
and break 
things
Um milhão de features 
Base de código gigante
Quebrando os muros
Muitos vilarejos, muitos idiomas
Muitos vilarejos, muitos idiomas 
Microserviços → "tudo é http" 
Culturas de código 
Infraestrutura 
Monitoramento 
"production ready"
Ninguém entende ninguém
Move fast 
without breaking everything, bitte.
Java
Java 
Serviços de base 
Bibliotecas compartilhadas 
Monitoria 
Autenticação/segurança 
(cross-cutting concerns)
Java 
Serviços de base 
Bibliotecas compartilhadas 
Monitoria 
Autenticação/segurança 
(cross-cutting concerns) 
INFRAESTRUTURA BÁSICA
JVM-Kit 
+ Finagle
Estudo de caso 
O novo Stream
Reescrever pra quê?
Reescrever pra quê? 
API 
Cassandra 
MySQL
Reescrever pra quê? 
API 
Cassandra 
MySQL
Reescrever pra quê? 
80% request queueing 
API 
Cassandra 
MySQL
Reescrever pra quê? 
Novas features 
Latência 
Vazão 
Microserviços
API 
Timeline
API 
Timeline 
Roshi
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc.
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc.
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários 
Likes 
Coment. 
Promoted 
Stats
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários 
Likes 
Coment. 
Promoted 
Stats 
...
Buscar 
API 
Agregar 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários 
Likes 
Coment. 
Promoted 
Stats 
...
Buscar 
Latência
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários 
Likes 
Coment. 
Promoted 
Stats 
...
Agregar 
Complexidade
API 
Timeline 
Roshi 
Autentic. 
Autoriz. 
Geo loc. 
Playlists 
Tracks 
Usuários 
Likes 
Coment. 
Promoted 
Stats 
...
Scala 
yay!
Buscar 
Paralelizar
Futuros
Futuros 
Referência para um 
valor que será 
disponibilizado no 
futuro.
Futuros 
val response: Future[Int] = … 
// Não compila 
response + 1
Futuros 
val response: Future[Int] = … 
// Adiciona um callback 
response.onSuccess { int => 
println(int) 
}
Futuros 
val response: Future[Int] = … 
// Compõe um novo futuro 
val count: Future[Int] = 
response.map { int => 
int + 1 
}
Futuros 
for { 
user <- authenticate(request) 
} yield { 
}
Futuros 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
} yield { 
}
Futuros 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
timeline <- timelineFor(user, geo) 
} yield { 
}
Futuros 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
timeline <- timelineFor(user, geo) 
resources <- 
fetchTracks(timeline) 
.join(fetchPlaylists(timeline)) 
.join(fetchComments(timeline)) 
} yield { 
}
Futuros 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
timeline <- timelineFor(user, geo) 
resources <- 
fetchTracks(timeline) 
.join(fetchPlaylists(timeline)) 
.join(fetchComments(timeline)) 
} yield { 
new EnrichedTimeline(timeline, resources) 
}
Futuros 
def handle(request: Request): Future[EnrichedTimeline] = 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
timeline <- timelineFor(user, geo) 
resources <- 
fetchTracks(timeline) 
.join(fetchPlaylists(timeline)) 
.join(fetchComments(timeline)) 
} yield { 
new EnrichedTimeline(timeline, resources) 
}
Futuros 
+ NIO 
Escalabilidade
Máquinas
Máquinas 
Processos
Máquinas 
Processos 
Threads
Máquinas 
Processos 
Threads 
Futuros
Futuros 
def handle(request: Request): Future[EnrichedTimeline] = 
for { 
user <- authenticate(request) 
geo <- geoLocationFor(request, user) 
timeline <- timelineFor(user, geo) 
resources <- 
fetchTracks(timeline) 
.join(fetchPlaylists(timeline)) 
.join(fetchComments(timeline)) 
} yield { 
new EnrichedTimeline(timeline, resources) 
}
Agregar 
Funcional
Collections
val timeline: Timeline = …
val timeline: Timeline = … 
val actorsToFetch: List[User] = 
timeline.items.map(_.actor)
val timeline: Timeline = … 
val actorsToFetch: List[User] = 
timeline.items.map(_.actor) 
val itemsByActor: Map[User, List[Item]] = 
timeline.items.groupBy(_.actor)
val timeline: Timeline = … 
val actorsToFetch: List[User] = 
timeline.items.map(_.actor) 
val itemsByActor: Map[User, List[Item]] = 
timeline.items.groupBy(_.actor) 
val numberOfItemsByActor: Map[User, Int] = 
itemsByActor.mapValues(_.size)
def createEnrichedTimeline( 
timeline: Timeline, 
users: Map[User, EnrichedUser]) = { 
timeline.items.map { item => 
new EnrichedItem( 
item, users.get(item.actor)) 
} 
}
Options
Option[T] 
None Some(value)
Options 
def findUser(id: Int): Option[User] 
// Não compila 
render.json(findUser(666).name)
def findUser(id: Int): Option[User] 
// Compila 
findUser(666).map { 
case Some(user) => render.json(user.name) 
case None => render.notFound 
} 
Options
Pattern 
Matching
case class User(name: String, gender: Gender, email: Email)
case class User(name: String, gender: Gender, email: Email) 
timelineActors.foreach { 
}
case class User(name: String, gender: Gender, email: Email) 
timelineActors.foreach { 
case User(name, Female, Email(_, “soundcloud.com”) => 
println(“mulher trabalhando na soundcloud”) 
}
case class User(name: String, gender: Gender, email: Email) 
timelineActors.foreach { 
case User(name, Female, Email(_, “soundcloud.com”) => 
println(“mulher trabalhando na soundcloud”) 
case User(name, Male, Email(_, “soundcloud.com”) => 
println(“homem trabalhando na soundcloud”) 
}
case class User(name: String, gender: Gender, email: Email) 
timelineActors.foreach { 
case User(name, Female, Email(_, “soundcloud.com”) => 
println(“mulher trabalhando na soundcloud”) 
case User(name, Male, Email(_, “soundcloud.com”) => 
println(“homem trabalhando na soundcloud”) 
case User(name, gender, Email(_, “qconrio.com.br”) => 
println(“organizador da qconrio”) 
}
case class User(name: String, gender: Gender, email: Email) 
timelineActors.foreach { 
case User(name, Female, Email(_, “soundcloud.com”) => 
println(“mulher trabalhando na soundcloud”) 
case User(name, Male, Email(_, “soundcloud.com”) => 
println(“homem trabalhando na soundcloud”) 
case User(name, gender, Email(_, “qconrio.com.br”) => 
println(“organizador da qconrio”) 
case _ => 
println(“pessoa desconhecida”) 
}
Nem tudo são flores...
Código denso 
def flatMap[B, That] 
(f: (A) ⇒ Traversable[B]) 
(implicit bf: CanBuildFrom[ 
List[A], B, That]): That
Código denso 
def flatMap[B, That] 
(f: (A) ⇒ Traversable[B]) 
(implicit bf: CanBuildFrom[ 
List[A], B, That]): That 
listOfThings.flatMap(_.toUpperCase)
XML também é código? 
<fruits> 
<fruit type="banana" origin="brazil"/> 
<fruit type="apple"/> 
<fruit type="orange" origin="usa"/> 
<fruit type="orange" origin="brazil"/> 
</fruits>  "fruit" 
filter { _  "@origin" 
exists (_.text == "brazil") }
Mas e o Stream...?
Mas e o Stream...? 
API 
Cassandra 
MySQL
Mas e o Stream...? 
API 
MySQL 
Tracks 
SPelarvyilcisets 
SMeurvltiicpele 
Services 
Timeline Redis 
Service
Mas e o Stream...? 
~150 ms 
~0% request queueing 
API 
MySQL 
Tracks 
SPelarvyilcisets 
SMeurvltiicpele 
Services 
Timeline Redis 
Service
Mas só o Stream...? 
Data team 
Outros serviços em 
Scala 
Ferramental jvmkit
Stranglers
Stranglers
Stranglers 
Novo 
stream 
Cache
O presente
Em resumo... 
Produtivo como Ruby, typesafe 
como Java* 
Move faster 
break fewer things
O futuro
O futuro 
Padrões de código 
Bibliotecas mais estáveis 
Facilidade de inovação 
"One Scala"
Perguntas?

Scala na soundcloud [QCon]

  • 2.
    @flaviowbrasil Aficionado poropen source Expert em escalabilidade Mestre Jedi Scala Prefere uma sessão de profiling a uma tarde na praia
  • 3.
    @herval Fundador deStartups Dois Easter Eggs publicados Padawan Scala Tem um cachorro
  • 4.
    A Nuvem deSom 12 horas de novo conteúdo/ minuto 350 milhões de usuários/mês 12 milhões de horas ouvidas/mês 1 usuário no espaço
  • 5.
    Era uma vezuma startup...
  • 6.
    Era uma vezuma startup... Uma base de código
  • 7.
    Era uma vezuma startup... Uma base de código Um punhado de construtores
  • 8.
    Move fast andbreak things
  • 9.
    Um milhão defeatures Base de código gigante
  • 10.
  • 11.
  • 12.
    Muitos vilarejos, muitosidiomas Microserviços → "tudo é http" Culturas de código Infraestrutura Monitoramento "production ready"
  • 13.
  • 14.
    Move fast withoutbreaking everything, bitte.
  • 15.
  • 16.
    Java Serviços debase Bibliotecas compartilhadas Monitoria Autenticação/segurança (cross-cutting concerns)
  • 17.
    Java Serviços debase Bibliotecas compartilhadas Monitoria Autenticação/segurança (cross-cutting concerns) INFRAESTRUTURA BÁSICA
  • 19.
  • 20.
    Estudo de caso O novo Stream
  • 22.
  • 23.
    Reescrever pra quê? API Cassandra MySQL
  • 24.
    Reescrever pra quê? API Cassandra MySQL
  • 25.
    Reescrever pra quê? 80% request queueing API Cassandra MySQL
  • 26.
    Reescrever pra quê? Novas features Latência Vazão Microserviços
  • 27.
  • 28.
  • 29.
    API Timeline Roshi Autentic. Autoriz. Geo loc.
  • 30.
    API Timeline Roshi Autentic. Autoriz. Geo loc.
  • 31.
    API Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários
  • 32.
    API Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários Likes Coment. Promoted Stats
  • 33.
    API Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários Likes Coment. Promoted Stats ...
  • 34.
    Buscar API Agregar Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários Likes Coment. Promoted Stats ...
  • 35.
  • 36.
    API Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários Likes Coment. Promoted Stats ...
  • 37.
  • 38.
    API Timeline Roshi Autentic. Autoriz. Geo loc. Playlists Tracks Usuários Likes Coment. Promoted Stats ...
  • 39.
  • 40.
  • 42.
  • 43.
    Futuros Referência paraum valor que será disponibilizado no futuro.
  • 44.
    Futuros val response:Future[Int] = … // Não compila response + 1
  • 45.
    Futuros val response:Future[Int] = … // Adiciona um callback response.onSuccess { int => println(int) }
  • 46.
    Futuros val response:Future[Int] = … // Compõe um novo futuro val count: Future[Int] = response.map { int => int + 1 }
  • 47.
    Futuros for { user <- authenticate(request) } yield { }
  • 48.
    Futuros for { user <- authenticate(request) geo <- geoLocationFor(request, user) } yield { }
  • 49.
    Futuros for { user <- authenticate(request) geo <- geoLocationFor(request, user) timeline <- timelineFor(user, geo) } yield { }
  • 50.
    Futuros for { user <- authenticate(request) geo <- geoLocationFor(request, user) timeline <- timelineFor(user, geo) resources <- fetchTracks(timeline) .join(fetchPlaylists(timeline)) .join(fetchComments(timeline)) } yield { }
  • 51.
    Futuros for { user <- authenticate(request) geo <- geoLocationFor(request, user) timeline <- timelineFor(user, geo) resources <- fetchTracks(timeline) .join(fetchPlaylists(timeline)) .join(fetchComments(timeline)) } yield { new EnrichedTimeline(timeline, resources) }
  • 52.
    Futuros def handle(request:Request): Future[EnrichedTimeline] = for { user <- authenticate(request) geo <- geoLocationFor(request, user) timeline <- timelineFor(user, geo) resources <- fetchTracks(timeline) .join(fetchPlaylists(timeline)) .join(fetchComments(timeline)) } yield { new EnrichedTimeline(timeline, resources) }
  • 53.
    Futuros + NIO Escalabilidade
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
    Futuros def handle(request:Request): Future[EnrichedTimeline] = for { user <- authenticate(request) geo <- geoLocationFor(request, user) timeline <- timelineFor(user, geo) resources <- fetchTracks(timeline) .join(fetchPlaylists(timeline)) .join(fetchComments(timeline)) } yield { new EnrichedTimeline(timeline, resources) }
  • 59.
  • 60.
  • 61.
  • 62.
    val timeline: Timeline= … val actorsToFetch: List[User] = timeline.items.map(_.actor)
  • 63.
    val timeline: Timeline= … val actorsToFetch: List[User] = timeline.items.map(_.actor) val itemsByActor: Map[User, List[Item]] = timeline.items.groupBy(_.actor)
  • 64.
    val timeline: Timeline= … val actorsToFetch: List[User] = timeline.items.map(_.actor) val itemsByActor: Map[User, List[Item]] = timeline.items.groupBy(_.actor) val numberOfItemsByActor: Map[User, Int] = itemsByActor.mapValues(_.size)
  • 65.
    def createEnrichedTimeline( timeline:Timeline, users: Map[User, EnrichedUser]) = { timeline.items.map { item => new EnrichedItem( item, users.get(item.actor)) } }
  • 66.
  • 67.
  • 68.
    Options def findUser(id:Int): Option[User] // Não compila render.json(findUser(666).name)
  • 69.
    def findUser(id: Int):Option[User] // Compila findUser(666).map { case Some(user) => render.json(user.name) case None => render.notFound } Options
  • 70.
  • 71.
    case class User(name:String, gender: Gender, email: Email)
  • 72.
    case class User(name:String, gender: Gender, email: Email) timelineActors.foreach { }
  • 73.
    case class User(name:String, gender: Gender, email: Email) timelineActors.foreach { case User(name, Female, Email(_, “soundcloud.com”) => println(“mulher trabalhando na soundcloud”) }
  • 74.
    case class User(name:String, gender: Gender, email: Email) timelineActors.foreach { case User(name, Female, Email(_, “soundcloud.com”) => println(“mulher trabalhando na soundcloud”) case User(name, Male, Email(_, “soundcloud.com”) => println(“homem trabalhando na soundcloud”) }
  • 75.
    case class User(name:String, gender: Gender, email: Email) timelineActors.foreach { case User(name, Female, Email(_, “soundcloud.com”) => println(“mulher trabalhando na soundcloud”) case User(name, Male, Email(_, “soundcloud.com”) => println(“homem trabalhando na soundcloud”) case User(name, gender, Email(_, “qconrio.com.br”) => println(“organizador da qconrio”) }
  • 76.
    case class User(name:String, gender: Gender, email: Email) timelineActors.foreach { case User(name, Female, Email(_, “soundcloud.com”) => println(“mulher trabalhando na soundcloud”) case User(name, Male, Email(_, “soundcloud.com”) => println(“homem trabalhando na soundcloud”) case User(name, gender, Email(_, “qconrio.com.br”) => println(“organizador da qconrio”) case _ => println(“pessoa desconhecida”) }
  • 77.
    Nem tudo sãoflores...
  • 79.
    Código denso defflatMap[B, That] (f: (A) ⇒ Traversable[B]) (implicit bf: CanBuildFrom[ List[A], B, That]): That
  • 80.
    Código denso defflatMap[B, That] (f: (A) ⇒ Traversable[B]) (implicit bf: CanBuildFrom[ List[A], B, That]): That listOfThings.flatMap(_.toUpperCase)
  • 81.
    XML também écódigo? <fruits> <fruit type="banana" origin="brazil"/> <fruit type="apple"/> <fruit type="orange" origin="usa"/> <fruit type="orange" origin="brazil"/> </fruits> "fruit" filter { _ "@origin" exists (_.text == "brazil") }
  • 83.
    Mas e oStream...?
  • 84.
    Mas e oStream...? API Cassandra MySQL
  • 85.
    Mas e oStream...? API MySQL Tracks SPelarvyilcisets SMeurvltiicpele Services Timeline Redis Service
  • 86.
    Mas e oStream...? ~150 ms ~0% request queueing API MySQL Tracks SPelarvyilcisets SMeurvltiicpele Services Timeline Redis Service
  • 87.
    Mas só oStream...? Data team Outros serviços em Scala Ferramental jvmkit
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
    Em resumo... Produtivocomo Ruby, typesafe como Java* Move faster break fewer things
  • 93.
  • 94.
    O futuro Padrõesde código Bibliotecas mais estáveis Facilidade de inovação "One Scala"
  • 95.