Upload
paulo-siqueira
View
325
Download
4
Embed Size (px)
Citation preview
Scala na Carjump
Como a [Carjump] usa Scala para revolucionar o mercado de compartilhamento de carros
Paulo "JCranky" SiqueiraSenior Scala Dev @ Carjump
JCranky
Dev Scala, com passado Java
> Berlin> Carjump
JCranky
Um dos fundadores dos Scaladores
> scaladores.com.br
> continua vivo > (Felipe e Onilton)
JCranky
scaladores.com.br
groups.google.com/group/scaladores
http://scaladores.herokuapp.com/
Típica Startup
Fundada há poucos anos, comprada pelos sócios atuais
Passou por rodadas de investimentos
Atua no ramo de carsharing
Mas que diabos é CarSharing?
[Compartilhamento de Carros]
ou
Forma moderna de [Aluguel] de carros
[MODERNA]
[Stationary]
ou
[Fixa]
[REALMENTE moderna]
> Estacione em qualquer lugar
(dentro de uma área prédefinida)
Carjump: O que?
Agregação de vários provedores em um único App.
Ao ponto: Backend!
> Scala> Startup e desenvolvedor único...> ... para tudo, inclusive frontend
Conceito original
"Ache o carro e pule para a App do provedor"
Arquitetura e Componentes
> Scala Futures> Java Futures (passado! \o/)> Akka> Mongo> Scalatra> Heroku
Arquitetura
if (password < 0) login()
Scala Futures
cities.flatMap { city => val carsF = Future( new CityWorker(city).call)
Try(Await.result( carsF, timeout)) match {
// handle result }}
val system = ActorSystem("Fetchers")var attempts = 0
while ( system == null && attempts < 5) {
// whatever ...}
Akka - CarFetcher
override def receive: Receive = { case FETCH => val cars = safeFetch()
context.system.scheduler .scheduleOnce(pollPeriod, self, FETCH)
persist(cars)}
Scalatra
get("/") { new AsyncResult { val is = Future { // 56734 lines } }}
Novo conceito:
[One App to Rule 'em All]
Evolution
[MiniServices]
> uso mais intenso do Scalatra
> APIs RESTful> DBs individuais
Async
Quase tudo Async
> Scalatra nos queimou!
Future composition
for { user < isEmailValidated(user) sepaDetails < paymentService .getSepa(user.code) remote < remoteCreditCheck( user, sepaDetails)} yield remote
usando um login token
val findQ = tokensTable .filter(_.userId === userId) .filter(_.sentAt.isDefined) .filter(_.token.isDefined) .filter(_.usedAt.isEmpty) .filter(_.expireAt.isDefined)
Mas nada aconteceu!
IO Monad, declarando o que vai ser feito no BD
um pouco mais de lógica
val q = findQ.result .flatMap { tokens =>
// verify if token is valid}
agora vai!
db.run(q.transactionally)
Scalatra: nossa triste realidade.
ScentryStrategy
def authenticate()( implicit request: HttpServletRequest, response: HttpServletResponse): Option[HttpUser]
ScentryStrategy
def authenticate()(...) { val f = validate(request) Await.result(f, 5 second)}
Heroku
Fator limitante
Arquitetura engessada
E finalmente...
... nova arquitetura
Nova arquitetura
Grandes mudanças
Parcialmente no Heroku,parcialmente no AWS EC2
> Akka cluster
> (pelo menos) Um provedor por nó
> EC2 micro para cada máquina / nó
cluster config
// other akka remote config
akka.cluster { seednodes = [...] roles = ["provider", "drivenow"]}
find cluster node
(simplificado)
val cluster = Cluster(context.system)
cluster.state.members .filter(m => m.roles.contains(key) && m.status == Status.Up) .map(_.alongside(_.address))
Secret sauce
Ansible!
Provisionamento mega simples de todos os nós no EC2.(ou seria inviável migrar para o EC2)
Install Java
apt_repository: repo=ppa:webupd8team/java update_cache=yes
apt: name=oraclejava8installer state=present
(omitido accept license)
Automatizando tudo!
Install Java, Scala, etc Build do projetos Setup Docker etc
Obrigado!
Perguntas?!