SlideShare a Scribd company logo
Product Engineering 
Bora
SoundCloud Public API 
● for external developers 
● no built-in assumptions
Growing 
● api team became a bottleneck 
● undocumented endpoints
Client Specific APIs
Reduce Chattiness
soundcloud.com/explore 
/explore/categories 
API 
/explore/{category} 
/tracks?ids={ids} 
/visuals/{ids}
soundcloud.com/explore 
/explore 
API
Remove Dependencies
Public API 
SC Microservices
API-V2 API-Mobile API-Embedded API-Partners API-* 
SC Microservices
Building Products at SoundCloud 
● Dealing with the Monolith 
● Breaking the Monolith 
● Microservices in Scala and Finagle
Java Interoperability
API-V2 API-Mobile API-Embedded API-Partners API-* 
SC Microservices 
BFF 
JVM-KIT
Futures
API-V2 API-Mobile API-Embedded API-Partners API-* 
SC Microservices
def userTracks(userUrn: Urn): Future[List[Track]] = { 
for { 
trackUrns <- userTrackRepo.trackUrns(userUrn) 
tracks <- trackRepo.tracks(trackUrns) 
} yield tracks 
}
val resources: List[Future[List[Resource]]] = List( 
trackRepo.tracks(trackUrns), 
userRepo.users(userUrns), 
playlistRepo.playlists(playlistUrns), 
groupRepo.groups(groupUrns)) 
Future.collect(resources).map { 
case List(tracks, users, playlists, groups) => ... 
}
Traits
abstract class JsonMapping(val trackJson: JsValue) 
trait MiniTrack extends JsonMapping { 
val urn = Urn((trackJson  "self"  "urn").as[String]) 
val title = (trackJson  "title").as[String] 
} 
trait Stats extends JsonMapping { 
val play_count = (trackJson  "play_count").as[Int] 
val like_count = (trackJson  "like_count").as[Int] 
} 
trait Artwork extends JsonMapping { 
val artwork_url = (trackJson  "artwork_url").as[String] 
}
new JsonMapping(trackJson) 
with MiniTrack 
with Stats 
with Artwork 
... 
new JsonMapping(trackJson) 
with MiniTrack 
with Stats 
... 
new JsonMapping(trackJson) 
with MiniTrack 
with Scheduling
Higher-order Functions
trait TracksController extends BaseController { 
get("/tracks/:urn") { 
request => 
val trackUrn = Urn(request.routeParams("urn")) 
trackRepo.track(trackUrn).map(render) 
} 
} 
... 
def get(path: String)(callback: RequestHandler) = 
register(path, HttpMethod.GET, callback) 
type RequestHandler = Request => Future[Response]
Collections
// Playlist has a tracks : List[Tracks] 
val playlists: List[Playlist] 
val emptyPlaylists = 
playlists.filter(_.tracks.isEmpty) 
val allTracks = 
playlists.map(_.tracks).flatten 
val tracksByCreator: Map[User, List[Track]] = 
allTracks.groupBy(_.creator) 
val trackCount = 
playlists.map(_.tracks.size).sum
Case Classes & Pattern Matching
case class JsonResponse( 
status: StatusCode, 
body: JsValue, 
headers: HttpHeaders = HttpHeaders.EMPTY_HEADERS, 
pagination: Pagination = Pagination.empty 
)
def tracks(urns: List[Urn]) = { 
fetch(Path() / "tracks", urns).map { 
case JsonResponse(OkStatus, body, _, _) => body 
case JsonResponse(NotFoundStatus, _, _, _) => ... 
case JsonResponse(UnauthorizedStatus, _, _, _) => ... 
case _ => throw ... 
} 
}
class Urn implements Serializable, Comparable<Urn>//JAVA Interop 
object Urn { 
... 
def unapply(obj: Urn): Option[(String, String, String)] = 
Some(obj.getNamespace, obj.getCollection, obj.getIdentifier) 
} 
urn match { 
case Urn(_, "tracks", _) => ... 
case Urn(_, "playlists", _) => … 
case Urn(_, "comments", _) => ... 
}
Implicits
def tracks(urns: List[Urn]) = 
fetch(Path() / "tracks", urns) 
... 
def fetch(path: Path, params: Params) 
// defined in the package object 
implicit def urnsToParams(urns: Iterable[Urn]): Params = 
Params("urns" -> urns) 
… 
// we can still use make this 
fetch(Path() / "tracks", Params("ids" -> ids))
XML!!!
trait AssignmentsController extends V2Controller with ExceptionHandler {class TracksXmlVisitor(val wrapped: Node) extends 
TracksVisitor { 
type TrackType = XmlTrack 
def apply(visit: VisitTrack): Option[Node] = 
apply(wrapped, visit) 
private def apply(node: Node, visit: VisitTrack): Option[Node] = { 
node match { 
case node: Node if (isTrack(node)) => 
visitTrack(node, visit) 
case node: Elem => 
val att = node.attributes 
val children = node.child.map { 
case text: Text => 
Some(text) 
case other => 
apply(other, visit) 
}.flatten 
Some(new Elem(node.prefix, node.label, node.attributes, node.scope, true, children: _*)) 
case other => 
Some(other) 
} 
} 
private def visitTrack(node: Node, visit: VisitTrack) = { 
val id = (node  "id").text.toInt 
val urn = Urn(s"soundcloud:tracks:$id") 
visit(urn, XmlTrack(node)) 
} 
private def isTrack(node: Node) = 
(node  "kind").text == "track" 
}
API Development and Scala @ SoundCloud

More Related Content

What's hot

Workshop apache camel
Workshop apache camelWorkshop apache camel
Workshop apache camelMarko Seifert
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015
Phillip Trelford
 
Terraform infraestructura como código
Terraform infraestructura como códigoTerraform infraestructura como código
Terraform infraestructura como código
Victor Adsuar
 
ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]
Guillermo Paz
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
NAVER Engineering
 
Customizing the unix environment
Customizing the unix environmentCustomizing the unix environment
Customizing the unix environment
Dr. Girish GS
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Юлия Коваленко
 
Modern JS with ES6
Modern JS with ES6Modern JS with ES6
Modern JS with ES6
Kevin Langley Jr.
 
Ff to-fp
Ff to-fpFf to-fp
Ff to-fp
Andy Petrella
 
Переход на Scala: босиком по граблям
Переход на Scala: босиком по граблямПереход на Scala: босиком по граблям
Переход на Scala: босиком по граблям
Sveta Bozhko
 
Javascript ES6 generators
Javascript ES6 generatorsJavascript ES6 generators
Javascript ES6 generators
Ramesh Nair
 
Try PostgreSQL on linux
Try PostgreSQL on linuxTry PostgreSQL on linux
Try PostgreSQL on linux
Aey Unthika
 
Efficient Use of indexes in MySQL
Efficient Use of indexes in MySQLEfficient Use of indexes in MySQL
Efficient Use of indexes in MySQL
Aleksandr Kuzminsky
 
Functional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipperFunctional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipper
osfameron
 
Mkscript sh
Mkscript shMkscript sh
Mkscript sh
Ben Pope
 
The PostgreSQL JSON Feature Tour
The PostgreSQL JSON Feature TourThe PostgreSQL JSON Feature Tour
The PostgreSQL JSON Feature Tour
Stefanie Janine Stölting
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Puppet
 

What's hot (17)

Workshop apache camel
Workshop apache camelWorkshop apache camel
Workshop apache camel
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015
 
Terraform infraestructura como código
Terraform infraestructura como códigoTerraform infraestructura como código
Terraform infraestructura como código
 
ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]ES6 in Production [JSConfUY2015]
ES6 in Production [JSConfUY2015]
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
 
Customizing the unix environment
Customizing the unix environmentCustomizing the unix environment
Customizing the unix environment
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018
 
Modern JS with ES6
Modern JS with ES6Modern JS with ES6
Modern JS with ES6
 
Ff to-fp
Ff to-fpFf to-fp
Ff to-fp
 
Переход на Scala: босиком по граблям
Переход на Scala: босиком по граблямПереход на Scala: босиком по граблям
Переход на Scala: босиком по граблям
 
Javascript ES6 generators
Javascript ES6 generatorsJavascript ES6 generators
Javascript ES6 generators
 
Try PostgreSQL on linux
Try PostgreSQL on linuxTry PostgreSQL on linux
Try PostgreSQL on linux
 
Efficient Use of indexes in MySQL
Efficient Use of indexes in MySQLEfficient Use of indexes in MySQL
Efficient Use of indexes in MySQL
 
Functional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipperFunctional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipper
 
Mkscript sh
Mkscript shMkscript sh
Mkscript sh
 
The PostgreSQL JSON Feature Tour
The PostgreSQL JSON Feature TourThe PostgreSQL JSON Feature Tour
The PostgreSQL JSON Feature Tour
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
 

Viewers also liked

Availability Objectives of SoundClouds Microservices
Availability Objectives of SoundClouds MicroservicesAvailability Objectives of SoundClouds Microservices
Availability Objectives of SoundClouds Microservices
Bora Tunca
 
Microservices @ SoundCloud
Microservices @ SoundCloudMicroservices @ SoundCloud
Microservices @ SoundCloud
Bora Tunca
 
SoundCloud's Toolbox for Microservices
SoundCloud's Toolbox for MicroservicesSoundCloud's Toolbox for Microservices
SoundCloud's Toolbox for Microservices
Bora Tunca
 
SoundCloud: A Success Story
SoundCloud: A Success StorySoundCloud: A Success Story
SoundCloud: A Success StoryRyan Kam
 
BFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s MicroservicesBFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s Microservices
Bora Tunca
 
Sound cloud analysis
Sound cloud analysisSound cloud analysis
Sound cloud analysis
alexplatt
 
SoundCloud Presentation @ AWS Startup Event London
SoundCloud Presentation @ AWS Startup Event LondonSoundCloud Presentation @ AWS Startup Event London
SoundCloud Presentation @ AWS Startup Event London
Eric Wahlforss
 
Soundcloud
SoundcloudSoundcloud
Soundcloud
Swinne
 
From the Monolith to Microservices - CraftConf 2015
From the Monolith to Microservices - CraftConf 2015From the Monolith to Microservices - CraftConf 2015
From the Monolith to Microservices - CraftConf 2015
Randy Shoup
 
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
Randy Shoup
 
Latest SoundCloud Market Research on Vertical Expansion
Latest SoundCloud Market Research on Vertical ExpansionLatest SoundCloud Market Research on Vertical Expansion
Latest SoundCloud Market Research on Vertical ExpansionInes Chen
 
Integrated Marketing Campaign - SoundCloud
Integrated Marketing Campaign - SoundCloudIntegrated Marketing Campaign - SoundCloud
Integrated Marketing Campaign - SoundCloud
Jerlynne Tan
 
Innovation - Soundcloud
Innovation - SoundcloudInnovation - Soundcloud
Innovation - Soundcloud
Sarah Lee
 

Viewers also liked (13)

Availability Objectives of SoundClouds Microservices
Availability Objectives of SoundClouds MicroservicesAvailability Objectives of SoundClouds Microservices
Availability Objectives of SoundClouds Microservices
 
Microservices @ SoundCloud
Microservices @ SoundCloudMicroservices @ SoundCloud
Microservices @ SoundCloud
 
SoundCloud's Toolbox for Microservices
SoundCloud's Toolbox for MicroservicesSoundCloud's Toolbox for Microservices
SoundCloud's Toolbox for Microservices
 
SoundCloud: A Success Story
SoundCloud: A Success StorySoundCloud: A Success Story
SoundCloud: A Success Story
 
BFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s MicroservicesBFF Pattern in Action: SoundCloud’s Microservices
BFF Pattern in Action: SoundCloud’s Microservices
 
Sound cloud analysis
Sound cloud analysisSound cloud analysis
Sound cloud analysis
 
SoundCloud Presentation @ AWS Startup Event London
SoundCloud Presentation @ AWS Startup Event LondonSoundCloud Presentation @ AWS Startup Event London
SoundCloud Presentation @ AWS Startup Event London
 
Soundcloud
SoundcloudSoundcloud
Soundcloud
 
From the Monolith to Microservices - CraftConf 2015
From the Monolith to Microservices - CraftConf 2015From the Monolith to Microservices - CraftConf 2015
From the Monolith to Microservices - CraftConf 2015
 
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...The eBay Architecture:  Striking a Balance between Site Stability, Feature Ve...
The eBay Architecture: Striking a Balance between Site Stability, Feature Ve...
 
Latest SoundCloud Market Research on Vertical Expansion
Latest SoundCloud Market Research on Vertical ExpansionLatest SoundCloud Market Research on Vertical Expansion
Latest SoundCloud Market Research on Vertical Expansion
 
Integrated Marketing Campaign - SoundCloud
Integrated Marketing Campaign - SoundCloudIntegrated Marketing Campaign - SoundCloud
Integrated Marketing Campaign - SoundCloud
 
Innovation - Soundcloud
Innovation - SoundcloudInnovation - Soundcloud
Innovation - Soundcloud
 

Similar to API Development and Scala @ SoundCloud

All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
John De Goes
 
Akka http 2
Akka http 2Akka http 2
Akka http 2
Jean Detoeuf
 
Server Side Swift with Swag
Server Side Swift with SwagServer Side Swift with Swag
Server Side Swift with Swag
Jens Ravens
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
Ruslan Shevchenko
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
Metosin Oy
 
How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
kwatch
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
Kris Wallsmith
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
Łukasz Bałamut
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
Daniel Cukier
 
Laravel
LaravelLaravel
Laravel
biplob04
 
router-simple.cr
router-simple.crrouter-simple.cr
router-simple.cr
karupanerura
 
Ruby is Awesome
Ruby is AwesomeRuby is Awesome
Ruby is Awesome
Astrails
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
Istanbul Tech Talks
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
Ostap Andrusiv
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - Javaz
Alexey Remnev
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Matt Stubbs
 
Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發
HO-HSUN LIN
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 

Similar to API Development and Scala @ SoundCloud (20)

All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Akka http 2
Akka http 2Akka http 2
Akka http 2
 
Server Side Swift with Swag
Server Side Swift with SwagServer Side Swift with Swag
Server Side Swift with Swag
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
 
Reitit - Clojure/North 2019
Reitit - Clojure/North 2019Reitit - Clojure/North 2019
Reitit - Clojure/North 2019
 
How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Laravel
LaravelLaravel
Laravel
 
router-simple.cr
router-simple.crrouter-simple.cr
router-simple.cr
 
Aimaf
AimafAimaf
Aimaf
 
Ruby is Awesome
Ruby is AwesomeRuby is Awesome
Ruby is Awesome
 
ITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function ProgrammingITT 2015 - Saul Mora - Object Oriented Function Programming
ITT 2015 - Saul Mora - Object Oriented Function Programming
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - Javaz
 
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIsBig Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
Big Data LDN 2017: Processing Fast Data With Apache Spark: the Tale of Two APIs
 
Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發Chaincode Development 區塊鏈鏈碼開發
Chaincode Development 區塊鏈鏈碼開發
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 

Recently uploaded

Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 

Recently uploaded (20)

Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 

API Development and Scala @ SoundCloud

  • 2. SoundCloud Public API ● for external developers ● no built-in assumptions
  • 3.
  • 4.
  • 5.
  • 6. Growing ● api team became a bottleneck ● undocumented endpoints
  • 7.
  • 8.
  • 11.
  • 12. soundcloud.com/explore /explore/categories API /explore/{category} /tracks?ids={ids} /visuals/{ids}
  • 14.
  • 16. Public API SC Microservices
  • 17. API-V2 API-Mobile API-Embedded API-Partners API-* SC Microservices
  • 18.
  • 19.
  • 20. Building Products at SoundCloud ● Dealing with the Monolith ● Breaking the Monolith ● Microservices in Scala and Finagle
  • 21.
  • 23. API-V2 API-Mobile API-Embedded API-Partners API-* SC Microservices BFF JVM-KIT
  • 25. API-V2 API-Mobile API-Embedded API-Partners API-* SC Microservices
  • 26. def userTracks(userUrn: Urn): Future[List[Track]] = { for { trackUrns <- userTrackRepo.trackUrns(userUrn) tracks <- trackRepo.tracks(trackUrns) } yield tracks }
  • 27. val resources: List[Future[List[Resource]]] = List( trackRepo.tracks(trackUrns), userRepo.users(userUrns), playlistRepo.playlists(playlistUrns), groupRepo.groups(groupUrns)) Future.collect(resources).map { case List(tracks, users, playlists, groups) => ... }
  • 29. abstract class JsonMapping(val trackJson: JsValue) trait MiniTrack extends JsonMapping { val urn = Urn((trackJson "self" "urn").as[String]) val title = (trackJson "title").as[String] } trait Stats extends JsonMapping { val play_count = (trackJson "play_count").as[Int] val like_count = (trackJson "like_count").as[Int] } trait Artwork extends JsonMapping { val artwork_url = (trackJson "artwork_url").as[String] }
  • 30. new JsonMapping(trackJson) with MiniTrack with Stats with Artwork ... new JsonMapping(trackJson) with MiniTrack with Stats ... new JsonMapping(trackJson) with MiniTrack with Scheduling
  • 32. trait TracksController extends BaseController { get("/tracks/:urn") { request => val trackUrn = Urn(request.routeParams("urn")) trackRepo.track(trackUrn).map(render) } } ... def get(path: String)(callback: RequestHandler) = register(path, HttpMethod.GET, callback) type RequestHandler = Request => Future[Response]
  • 34. // Playlist has a tracks : List[Tracks] val playlists: List[Playlist] val emptyPlaylists = playlists.filter(_.tracks.isEmpty) val allTracks = playlists.map(_.tracks).flatten val tracksByCreator: Map[User, List[Track]] = allTracks.groupBy(_.creator) val trackCount = playlists.map(_.tracks.size).sum
  • 35. Case Classes & Pattern Matching
  • 36. case class JsonResponse( status: StatusCode, body: JsValue, headers: HttpHeaders = HttpHeaders.EMPTY_HEADERS, pagination: Pagination = Pagination.empty )
  • 37. def tracks(urns: List[Urn]) = { fetch(Path() / "tracks", urns).map { case JsonResponse(OkStatus, body, _, _) => body case JsonResponse(NotFoundStatus, _, _, _) => ... case JsonResponse(UnauthorizedStatus, _, _, _) => ... case _ => throw ... } }
  • 38. class Urn implements Serializable, Comparable<Urn>//JAVA Interop object Urn { ... def unapply(obj: Urn): Option[(String, String, String)] = Some(obj.getNamespace, obj.getCollection, obj.getIdentifier) } urn match { case Urn(_, "tracks", _) => ... case Urn(_, "playlists", _) => … case Urn(_, "comments", _) => ... }
  • 39.
  • 41. def tracks(urns: List[Urn]) = fetch(Path() / "tracks", urns) ... def fetch(path: Path, params: Params) // defined in the package object implicit def urnsToParams(urns: Iterable[Urn]): Params = Params("urns" -> urns) … // we can still use make this fetch(Path() / "tracks", Params("ids" -> ids))
  • 42.
  • 44. trait AssignmentsController extends V2Controller with ExceptionHandler {class TracksXmlVisitor(val wrapped: Node) extends TracksVisitor { type TrackType = XmlTrack def apply(visit: VisitTrack): Option[Node] = apply(wrapped, visit) private def apply(node: Node, visit: VisitTrack): Option[Node] = { node match { case node: Node if (isTrack(node)) => visitTrack(node, visit) case node: Elem => val att = node.attributes val children = node.child.map { case text: Text => Some(text) case other => apply(other, visit) }.flatten Some(new Elem(node.prefix, node.label, node.attributes, node.scope, true, children: _*)) case other => Some(other) } } private def visitTrack(node: Node, visit: VisitTrack) = { val id = (node "id").text.toInt val urn = Urn(s"soundcloud:tracks:$id") visit(urn, XmlTrack(node)) } private def isTrack(node: Node) = (node "kind").text == "track" }