SlideShare ist ein Scribd-Unternehmen logo
1 von 82
Functional Reactive Programming
in the Netflix API
Ben Christensen
Software Engineer – API Platform at Netflix
@benjchristensen
http://www.linkedin.com/in/benjchristensen
http://techblog.netflix.com/
QCon London – March 6 2013
onsdag den 6. marts 13
InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/netflix-functional-rx
Presented at QCon London
www.qconlondon.com
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
onsdag den 6. marts 13
More than 33 million Subscribers
in more than 50 Countries and Territories
onsdag den 6. marts 13
Netflix accounts for 33% of Peak Downstream
Internet Traffic in North America
Netflix subscribers are watching
more than 1 billion hours a month
onsdag den 6. marts 13
API traffic has grown from
~20 million/day in 2010 to >2 billion/day
0
500
1000
1500
2000
2010 2011 2012 Today
millionsofAPIrequestsperday
onsdag den 6. marts 13
Discovery Streaming
onsdag den 6. marts 13
Netflix API Streaming
onsdag den 6. marts 13
onsdag den 6. marts 13
Open API Netflix Devices
API Request Volume by Audience
onsdag den 6. marts 13
Netflix API
Dependency A
Dependency D
Dependency G
Dependency J
Dependency M
Dependency P
Dependency B
Dependency E
Dependency H
Dependency K
Dependency N
Dependency Q
Dependency C
Dependency F
Dependency I
Dependency L
Dependency O
Dependency R
onsdag den 6. marts 13
/ps3/home
Dependency F
10 Threads
Dependency G
10 Threads
Dependency H
10 Threads
Dependency I
5 Threads
Dependency J
8 Threads
Dependency A
10 Threads
Dependency B
8 Threads
Dependency C
10 Threads
Dependency D
15 Threads
Dependency E
5 Threads
Dependency K
15 Threads
Dependency L
4 Threads
Dependency M
5 Threads
Dependency N
10 Threads
Dependency O
10 Threads
Dependency P
10 Threads
Dependency Q
8 Threads
Dependency R
10 Threads
Dependency S
8 Threads
Dependency T
10 Threads
/android/home
/tv/home
Functional Reactive Dynamic Endpoints
Asynchronous Java API
onsdag den 6. marts 13
/ps3/home
Dependency F
10 Threads
Dependency G
10 Threads
Dependency H
10 Threads
Dependency I
5 Threads
Dependency J
8 Threads
Dependency A
10 Threads
Dependency B
8 Threads
Dependency C
10 Threads
Dependency D
15 Threads
Dependency E
5 Threads
Dependency K
15 Threads
Dependency L
4 Threads
Dependency M
5 Threads
Dependency N
10 Threads
Dependency O
10 Threads
Dependency P
10 Threads
Dependency Q
8 Threads
Dependency R
10 Threads
Dependency S
8 Threads
Dependency T
10 Threads
/android/home
/tv/home
Functional Reactive Dynamic Endpoints
Asynchronous Java API
Hystrix
fault-isolation layer
onsdag den 6. marts 13
/ps3/home
Dependency F
10 Threads
Dependency G
10 Threads
Dependency H
10 Threads
Dependency I
5 Threads
Dependency J
8 Threads
Dependency A
10 Threads
Dependency B
8 Threads
Dependency C
10 Threads
Dependency D
15 Threads
Dependency E
5 Threads
Dependency K
15 Threads
Dependency L
4 Threads
Dependency M
5 Threads
Dependency N
10 Threads
Dependency O
10 Threads
Dependency P
10 Threads
Dependency Q
8 Threads
Dependency R
10 Threads
Dependency S
8 Threads
Dependency T
10 Threads
/android/home
/tv/home
Functional Reactive Dynamic Endpoints
Asynchronous Java API
onsdag den 6. marts 13
RxJava
“a library for composing
asynchronous and event-based
programs using observable
sequences for the Java VM”
A Java port of Rx (Reactive Extensions)
https://rx.codeplex.com (.Net and Javascript by Microsoft)
onsdag den 6. marts 13
Do we really need another way of
“managing” concurrency?
onsdag den 6. marts 13
Discovery of Rx began with a re-architecture ...
onsdag den 6. marts 13
... that collapsed network traffic into coarse API calls ...
onsdag den 6. marts 13
... that collapsed network traffic into coarse API calls ...
Nested, conditional, parallel execution
onsdag den 6. marts 13
... and we
wanted to allow
anybody to
create endpoints,
not just the
“API Team”
onsdag den 6. marts 13
onsdag den 6. marts 13
Concurrency without
each engineer reading
and re-reading this ->
(awesome book ... everybody isn’t
going to - or should have to - read
it though, that’s the point)
onsdag den 6. marts 13
Owner of API should retain
control of concurrency behavior.
onsdag den 6. marts 13
public Data getData();
What if the implementation needs to change
from synchronous to asynchronous?
How should the client execute that method
without blocking? spawn a thread?
Owner of API should retain
control of concurrency behavior.
onsdag den 6. marts 13
public void getData(Callback<T> c);
public Future<T> getData();
public Future<List<Future<T>>> getData();
What about ... ?
onsdag den 6. marts 13
Iterable
pull
Observable
push
T next()
throws Exception
returns;
onNext(T)
onError(Exception)
onCompleted()
onsdag den 6. marts 13
Iterable
pull
Observable
push
T next()
throws Exception
returns;
onNext(T)
onError(Exception)
onCompleted()
	
  //	
  Iterable<String>	
  
	
  //	
  that	
  contains	
  75	
  Strings
	
  getDataFromLocalMemory()
	
  	
  .skip(10)
	
  	
  .take(5)
	
  	
  .map({	
  s	
  -­‐>	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})
	
  	
  .forEach(
	
  	
  	
  	
  	
  {	
  println	
  "next	
  =>	
  "	
  +	
  it})
	
  //	
  Observable<String>	
  
	
  //	
  that	
  emits	
  75	
  Strings
	
  getDataFromNetwork()
	
  	
  .skip(10)
	
  	
  .take(5)
	
  	
  .map({	
  s	
  -­‐>	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})
	
  	
  .subscribe(
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})
onsdag den 6. marts 13
Iterable
pull
Observable
push
T next()
throws Exception
returns;
onNext(T)
onError(Exception)
onCompleted()
	
  //	
  Iterable<String>	
  
	
  //	
  that	
  contains	
  75	
  Strings
	
  getDataFromLocalMemory()
	
  	
  .skip(10)
	
  	
  .take(5)
	
  	
  .map({	
  s	
  -­‐>	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})
	
  	
  .forEach(
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})
	
  //	
  Observable<String>	
  
	
  //	
  that	
  emits	
  75	
  Strings
	
  getDataFromNetwork()
	
  	
  .skip(10)
	
  	
  .take(5)
	
  	
  .map({	
  s	
  -­‐>	
  
	
  	
  	
  return	
  s	
  +	
  "_transformed"})
	
  	
  .subscribe(
	
  	
  	
  	
  	
  {	
  println	
  "onNext	
  =>	
  "	
  +	
  it})
onsdag den 6. marts 13
Instead of blocking APIs ...
class	
  VideoService	
  {
	
  	
  	
  def	
  VideoList	
  getPersonalizedListOfMovies(userId);
	
  	
  	
  def	
  VideoBookmark	
  getBookmark(userId,	
  videoId);
	
  	
  	
  def	
  VideoRating	
  getRating(userId,	
  videoId);
	
  	
  	
  def	
  VideoMetadata	
  getMetadata(videoId);
}
class	
  VideoService	
  {
	
  	
  	
  def	
  Observable<VideoList>	
  getPersonalizedListOfMovies(userId);
	
  	
  	
  def	
  Observable<VideoBookmark>	
  getBookmark(userId,	
  videoId);
	
  	
  	
  def	
  Observable<VideoRating>	
  getRating(userId,	
  videoId);
	
  	
  	
  def	
  Observable<VideoMetadata>	
  getMetadata(videoId);
}
... create Observable APIs:
onsdag den 6. marts 13
onsdag den 6. marts 13
onsdag den 6. marts 13
onsdag den 6. marts 13
onsdag den 6. marts 13
onsdag den 6. marts 13
onsdag den 6. marts 13
Observable.toObservable("one",	
  "two",	
  "three")
	
  	
  	
  	
  	
  .take(2)
	
  	
  	
  	
  	
  .subscribe((arg)	
  -­‐>	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  System.out.println(arg);
	
  	
  	
  	
  	
  });
Java8
Observable.toObservable("one",	
  "two",	
  "three")
	
  	
  .take(2)
	
  	
  .subscribe((arg:	
  String)	
  =>	
  {
	
  	
  	
  	
  	
  	
  println(arg)
	
  	
  })
Scala
(-­‐>	
  
	
  	
  (Observable/toObservable	
  ["one"	
  "two"	
  "three"])
	
  	
  (.take	
  2)	
  
	
  	
  (.subscribe	
  (fn	
  [arg]	
  (println	
  arg))))
Clojure
	
  	
  Observable.toObservable("one",	
  "two",	
  "three")
	
  	
  	
  	
  .take(2)	
  
	
  	
  	
  	
  .subscribe({arg	
  -­‐>	
  println(arg)})
Groovy
	
  	
  Observable.toObservable("one",	
  "two",	
  "three")
	
  	
  	
  	
  .take(2)	
  
	
  	
  	
  	
  .subscribe(lambda	
  {	
  |arg|	
  puts	
  arg	
  })
JRuby
onsdag den 6. marts 13
 	
  	
  	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(new	
  Video(id))
	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  })
onsdag den 6. marts 13
 	
  	
  	
  def	
  Observable<VideoRating>	
  getRating(userId,	
  videoId)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  //	
  fetch	
  the	
  VideoRating	
  for	
  this	
  user	
  asynchronously
	
  	
  	
  	
  	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  executor.execute(new	
  Runnable()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  void	
  run()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VideoRating	
  rating	
  =	
  ...	
  do	
  network	
  call	
  ...
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(rating)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  }
Asynchronous Observable with Single Value
onsdag den 6. marts 13
 	
  	
  	
  def	
  Observable<VideoRating>	
  getRating(userId,	
  videoId)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  //	
  fetch	
  the	
  VideoRating	
  for	
  this	
  user	
  asynchronously
	
  	
  	
  	
  	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  executor.execute(new	
  Runnable()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  void	
  run()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  VideoRating	
  rating	
  =	
  ...	
  do	
  network	
  call	
  ...
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(rating)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  }
Asynchronous Observable with Single Value
onsdag den 6. marts 13
Synchronous Observable with Multiple Values
	
  	
  	
  	
  def	
  Observable<Video>	
  getVideos()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for(v	
  in	
  videos)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(v)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  }
Caution: This is eager and will always emit all values
regardless of subsequent operators such as take(10)
onsdag den 6. marts 13
Synchronous Observable with Multiple Values
	
  	
  	
  	
  def	
  Observable<Video>	
  getVideos()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for(v	
  in	
  videos)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(v)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  }
Caution: This is eager and will always emit all values
regardless of subsequent operators such as take(10)
onsdag den 6. marts 13
Asynchronous Observable with Multiple Values
	
  def	
  Observable<Video>	
  getVideos()	
  {
	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  executor.execute(new	
  Runnable()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  void	
  run()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for(id	
  in	
  videoIds)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Video	
  v	
  =	
  ...	
  do	
  network	
  call	
  ...
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(v)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  })
	
  }
onsdag den 6. marts 13
Asynchronous Observable with Multiple Values
	
  def	
  Observable<Video>	
  getVideos()	
  {
	
  	
  	
  	
  return	
  Observable.create({	
  observer	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  executor.execute(new	
  Runnable()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  void	
  run()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  try	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  for(id	
  in	
  videoIds)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Video	
  v	
  =	
  ...	
  do	
  network	
  call	
  ...
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onNext(v)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onCompleted();
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  catch(Exception	
  e)	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  observer.onError(e);
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  })
	
  	
  	
  	
  })
	
  }
onsdag den 6. marts 13
Observable<SomeData> a = getDataA();
Observable<SomeData> b = getDataB();
Observable<SomeData> c = getDataC();
Observable.merge(a, b, c)
.subscribe(
{ element -> println("data: " + element)},
{ exception -> println("error occurred: "
+ exception.getMessage())}
)
Combining via Merge
onsdag den 6. marts 13
Observable<SomeData> a = getDataA();
Observable<String> b = getDataB();
Observable<MoreData> c = getDataC();
Observable.zip(a, b, c, {x, y, z -> [x, y, z]})
.subscribe(
{ triple -> println("a: " + triple[0]
+ " b: " + triple[1]
+ " c: " + triple[2])},
{ exception -> println("error occurred: "
+ exception.getMessage())}
)
Combining via Zip
onsdag den 6. marts 13
Observable<SomeData> a = getDataA();
Observable<String> b = getDataB();
Observable<MoreData> c = getDataC();
Observable.zip(a, b, c, {x, y, z -> [x, y, z]})
.subscribe(
{ triple -> println("a: " + triple[0]
+ " b: " + triple[1]
+ " c: " + triple[2])},
{ exception -> println("error occurred: "
+ exception.getMessage())}
)
Error Handling
onsdag den 6. marts 13
Observable<SomeData> a = getDataA();
Observable<String> b = getDataB();
Observable<MoreData> c = getDataC()
.onErrorResumeNext(getFallbackForDataC());
Observable.zip(a, b, c, {x, y, z -> [x, y, z]})
.subscribe(
{ triple -> println("a: " + triple[0]
+ " b: " + triple[1]
+ " c: " + triple[2])},
{ exception -> println("error occurred: "
+ exception.getMessage())}
)
Error Handling
onsdag den 6. marts 13
def Observable getVideos(userId) {
return VideoService.getVideos(userId)
}
onsdag den 6. marts 13
def Observable getVideos(userId) {
return VideoService.getVideos(userId)
}
Asynchronous request that
returns Observable<Video>
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
}
Reactive operator on the Observable
that takes the first 10 Video objects
then unsubscribes.
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.map({ Video video ->
// transform video object
})
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.map({ Video video ->
// transform video object
})
}
The ‘map’ operator allows transforming
the input value into a different output.
onsdag den 6. marts 13
 	
  	
  	
  Observable<R>	
  b	
  =	
  Observable<T>.map({	
  T	
  t	
  -­‐>	
  
	
  	
  	
  	
  	
  	
  R	
  r	
  =	
  ...	
  transform	
  t	
  ...
	
  	
  	
  	
  	
  	
  return	
  r;
	
  	
  	
  	
  })
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
})
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
})
}
We change to ‘mapMany’ which is
like merge(map()) since we will return
an Observable<T> instead of T.
onsdag den 6. marts 13
 Observable<R>	
  b	
  =	
  Observable<T>.mapMany({	
  T	
  t	
  -­‐>	
  
	
  	
  	
  	
  Observable<R>	
  r	
  =	
  ...	
  transform	
  t	
  ...
	
  	
  	
  	
  return	
  r;
	
  })
onsdag den 6. marts 13
 Observable<R>	
  b	
  =	
  Observable<T>.mapMany({	
  T	
  t	
  -­‐>	
  
	
  	
  	
  	
  Observable<R>	
  r	
  =	
  ...	
  transform	
  t	
  ...
	
  	
  	
  	
  return	
  r;
	
  })
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
})
}
Nested asynchronous calls
that return more Observables.
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
})
}
Observable<VideoMetadata>
Observable<VideoBookmark>
Observable<VideoRating>
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
})
}
Each Observable transforms
its data using ‘map’
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
// for each video we want to fetch metadata
def m = video.getMetadata()
.map({ Map<String, String> md ->
// transform to the data and format we want
return [title: md.get("title"),
length: md.get("duration")]
})
// and its rating and bookmark
def b ...
def r ...
// compose these together
})
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
def m ...
def b ...
def r ...
// compose these together
})
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
def m ...
def b ...
def r ...
// compose these together
return Observable.zip(m, b, r, {
metadata, bookmark, rating ->
// now transform to complete dictionary
// of data we want for each Video
return [id: video.videoId]
<< metadata << bookmark << rating
})
})
}
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
def m ...
def b ...
def r ...
// compose these together
return Observable.zip(m, b, r, {
metadata, bookmark, rating ->
// now transform to complete dictionary
// of data we want for each Video
return [id: video.videoId]
<< metadata << bookmark << rating
})
})
}
The ‘zip’ operator combines the 3
asynchronous Observables into 1
onsdag den 6. marts 13
 	
  	
  	
  Observable.zip(a,	
  b,	
  {	
  a,	
  b,	
  -­‐>	
  
	
  	
  	
  	
  	
  	
  ...	
  operate	
  on	
  values	
  from	
  both	
  a	
  &	
  b	
  ...
	
  	
  	
  	
  	
  	
  return	
  [a,	
  b];	
  //	
  i.e.	
  return	
  tuple
	
  	
  	
  	
  })
onsdag den 6. marts 13
def Observable<Map> getVideos(userId) {
return VideoService.getVideos(userId)
// we only want the first 10 of each list
.take(10)
.mapMany({ Video video ->
def m ...
def b ...
def r ...
// compose these together
return Observable.zip(m, b, r, {
metadata, bookmark, rating ->
// now transform to complete dictionary
// of data we want for each Video
return [id: video.videoId]
<< metadata << bookmark << rating
})
})
}
return a single Map (dictionary)
of transformed and combined data
from 4 asynchronous calls
onsdag den 6. marts 13
onsdag den 6. marts 13
Observable<Video> emits n videos to onNext()
onsdag den 6. marts 13
Takes first 10 then unsubscribes from origin.
Returns Observable<Video> that emits 10 Videos.
onsdag den 6. marts 13
For each of the 10 Video objects it transforms
via ‘mapMany’ function that does nested async calls.
onsdag den 6. marts 13
For each Video ‘v’ it calls getMetadata()
which returns Observable<VideoMetadata>
These nested async
requests return Observables
that emit 1 value.
onsdag den 6. marts 13
The Observable<VideoMetadata> is transformed via
a ‘map’ function to return a Map of key/values.
onsdag den 6. marts 13
Same for Observable<VideoBookmark> and
Observable<VideoRating>
onsdag den 6. marts 13
The 3 ‘mapped’ Observables are combined with a
‘zip’ function that emits a Map with all data.
onsdag den 6. marts 13
The full sequence emits Observable<Map> that
emits a Map for each of 10 Videos.
onsdag den 6. marts 13
Client code treats all interactions
with the API as asynchronous
The API implementation chooses
whether something is
blocking or non-blocking
and
what resources it uses.
onsdag den 6. marts 13
Example of latency reduction achieved by increasing
number of threads used by Observables.
onsdag den 6. marts 13
+
Observable<User>	
  u	
  =	
  new	
  GetUserCommand(id).observe();
Observable<Geo>	
  g	
  =	
  new	
  GetGeoCommand(request).observe();
Observable.zip(u,	
  g,	
  {user,	
  geo	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  [username:	
  user.getUsername(),
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  currentLocation:	
  geo.getCounty()]	
  	
  	
  
})
RxJava coming to Hystrix
https://github.com/Netflix/Hystrix
onsdag den 6. marts 13
<dependency	
  org="com.netflix.rxjava"	
  name="rxjava-­‐core"	
  rev="x.y.z"	
  />
<dependency	
  org="com.netflix.rxjava"	
  name="rxjava-­‐groovy"	
  rev="x.y.z"	
  />
<dependency	
  org="com.netflix.rxjava"	
  name="rxjava-­‐clojure"	
  rev="x.y.z"	
  />
<dependency	
  org="com.netflix.rxjava"	
  name="rxjava-­‐scala"	
  rev="x.y.z"	
  />
<dependency	
  org="com.netflix.rxjava"	
  name="rxjava-­‐jruby"	
  rev="x.y.z"	
  />
<dependency>
	
  	
  	
  	
  <groupId>com.netflix.rxjava</groupId>
	
  	
  	
  	
  <artifactId>rxjava-­‐core</artifactId>
	
  	
  	
  	
  <version>x.y.z</version>
</dependency>
... or for a different language ...
To get started ...
onsdag den 6. marts 13
Functional Reactive in the Netflix API with RxJava
http://techblog.netflix.com/2013/02/rxjava-netflix-api.html
Optimizing the Netflix API
http://techblog.netflix.com/2013/01/optimizing-netflix-api.html
RxJava
https://github.com/Netflix/RxJava
@RxJava
Ben Christensen
@benjchristensen
http://www.linkedin.com/in/benjchristensen
Netflix is Hiring
http://jobs.netflix.com
onsdag den 6. marts 13

Weitere ähnliche Inhalte

Was ist angesagt?

Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Julian Robichaux
 
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...César Hernández
 
Reverse engineering and instrumentation of android apps
Reverse engineering and instrumentation of android appsReverse engineering and instrumentation of android apps
Reverse engineering and instrumentation of android appsGaurav Lochan
 
Philip Shurpik "Architecting React Native app"
Philip Shurpik "Architecting React Native app"Philip Shurpik "Architecting React Native app"
Philip Shurpik "Architecting React Native app"Fwdays
 
Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8Martijn Dashorst
 
Wicket 10 years and beyond
Wicket   10 years and beyond Wicket   10 years and beyond
Wicket 10 years and beyond Martijn Dashorst
 
10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were PossibleLukas Eder
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav DukhinFwdays
 
Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsShekhar Gulati
 
Java REST API Framework Comparison - UberConf 2021
Java REST API Framework Comparison - UberConf 2021Java REST API Framework Comparison - UberConf 2021
Java REST API Framework Comparison - UberConf 2021Matt Raible
 
AOTB2014: Agile Testing on the Java Platform
AOTB2014: Agile Testing on the Java PlatformAOTB2014: Agile Testing on the Java Platform
AOTB2014: Agile Testing on the Java PlatformPeter Pilgrim
 
Hyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkitHyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkit7mind
 
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...QAFest
 
Scala, Functional Programming and Team Productivity
Scala, Functional Programming and Team ProductivityScala, Functional Programming and Team Productivity
Scala, Functional Programming and Team Productivity7mind
 
Bytecode manipulation with Javassist for fun and profit
Bytecode manipulation with Javassist for fun and profitBytecode manipulation with Javassist for fun and profit
Bytecode manipulation with Javassist for fun and profitJérôme Kehrli
 
ScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency InjectionScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency Injection7mind
 
Who Needs Thumbs? Reverse Engineering Scramble With Friends
Who Needs Thumbs? Reverse Engineering Scramble With FriendsWho Needs Thumbs? Reverse Engineering Scramble With Friends
Who Needs Thumbs? Reverse Engineering Scramble With FriendsApkudo
 

Was ist angesagt? (20)

Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
 
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
2018 (codeone) Graal VM and MicroProfile a polyglot microservices solution [d...
 
Reverse engineering and instrumentation of android apps
Reverse engineering and instrumentation of android appsReverse engineering and instrumentation of android apps
Reverse engineering and instrumentation of android apps
 
Philip Shurpik "Architecting React Native app"
Philip Shurpik "Architecting React Native app"Philip Shurpik "Architecting React Native app"
Philip Shurpik "Architecting React Native app"
 
Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8Whats up with wicket 8 and java 8
Whats up with wicket 8 and java 8
 
Wicket 10 years and beyond
Wicket   10 years and beyond Wicket   10 years and beyond
Wicket 10 years and beyond
 
Gradle in 45min
Gradle in 45minGradle in 45min
Gradle in 45min
 
10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible10 SQL Tricks that You Didn't Think Were Possible
10 SQL Tricks that You Didn't Think Were Possible
 
The State of Wicket
The State of WicketThe State of Wicket
The State of Wicket
 
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
"Applied Enterprise Metaprogramming in JavaScript", Vladyslav Dukhin
 
Developing modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular jsDeveloping modern java web applications with java ee 7 and angular js
Developing modern java web applications with java ee 7 and angular js
 
Java REST API Framework Comparison - UberConf 2021
Java REST API Framework Comparison - UberConf 2021Java REST API Framework Comparison - UberConf 2021
Java REST API Framework Comparison - UberConf 2021
 
AOTB2014: Agile Testing on the Java Platform
AOTB2014: Agile Testing on the Java PlatformAOTB2014: Agile Testing on the Java Platform
AOTB2014: Agile Testing on the Java Platform
 
Hyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkitHyper-pragmatic Pure FP testing with distage-testkit
Hyper-pragmatic Pure FP testing with distage-testkit
 
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
QA Fest 2018. Adam Stasiak. React Native is Coming – the story of hybrid mobi...
 
Scala, Functional Programming and Team Productivity
Scala, Functional Programming and Team ProductivityScala, Functional Programming and Team Productivity
Scala, Functional Programming and Team Productivity
 
Bytecode manipulation with Javassist for fun and profit
Bytecode manipulation with Javassist for fun and profitBytecode manipulation with Javassist for fun and profit
Bytecode manipulation with Javassist for fun and profit
 
Hack the Future
Hack the FutureHack the Future
Hack the Future
 
ScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency InjectionScalaUA - distage: Staged Dependency Injection
ScalaUA - distage: Staged Dependency Injection
 
Who Needs Thumbs? Reverse Engineering Scramble With Friends
Who Needs Thumbs? Reverse Engineering Scramble With FriendsWho Needs Thumbs? Reverse Engineering Scramble With Friends
Who Needs Thumbs? Reverse Engineering Scramble With Friends
 

Ähnlich wie Functional Reactive Programming in the Netflix API

Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaPratama Nur Wijaya
 
Tek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJSTek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJSPablo Godel
 
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)Cyrille Le Clerc
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsJim Jeffers
 
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Alina Vilk
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyDarío Blanco Iturriaga
 
WebRTC Standards & Implementation Q&A - All about browser interoperability
WebRTC Standards & Implementation Q&A - All about browser interoperabilityWebRTC Standards & Implementation Q&A - All about browser interoperability
WebRTC Standards & Implementation Q&A - All about browser interoperabilityAmir Zmora
 
Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017Matt Raible
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsSimo Ahava
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJSGregor Woiwode
 
Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Bram Adams
 
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020AWSKRUG - AWS한국사용자모임
 
OGCE Project Overview
OGCE Project OverviewOGCE Project Overview
OGCE Project Overviewmarpierc
 
Job Managment Portlet
Job Managment PortletJob Managment Portlet
Job Managment Portletriround
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Matt Raible
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpmsom_nangia
 

Ähnlich wie Functional Reactive Programming in the Netflix API (20)

Android architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta IndonesiaAndroid architecture component - FbCircleDev Yogyakarta Indonesia
Android architecture component - FbCircleDev Yogyakarta Indonesia
 
Tek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJSTek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJS
 
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
 
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
 
Vue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapyVue JS @ MindDoc. The progressive road to online therapy
Vue JS @ MindDoc. The progressive road to online therapy
 
WebRTC Standards & Implementation Q&A - All about browser interoperability
WebRTC Standards & Implementation Q&A - All about browser interoperabilityWebRTC Standards & Implementation Q&A - All about browser interoperability
WebRTC Standards & Implementation Q&A - All about browser interoperability
 
Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017Front End Development for Back End Developers - vJUG24 2017
Front End Development for Back End Developers - vJUG24 2017
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJS
 
Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!
 
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020
Amplify를 통해 클라우드 기반 모바일 앱 개발하기 - 박태성(IDEASAM) :: AWS Community Day 2020
 
OGCE Project Overview
OGCE Project OverviewOGCE Project Overview
OGCE Project Overview
 
Origins of Serverless
Origins of ServerlessOrigins of Serverless
Origins of Serverless
 
Griffon Presentation
Griffon PresentationGriffon Presentation
Griffon Presentation
 
Job Managment Portlet
Job Managment PortletJob Managment Portlet
Job Managment Portlet
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 

Mehr von C4Media

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoC4Media
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileC4Media
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020C4Media
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsC4Media
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No KeeperC4Media
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like OwnersC4Media
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaC4Media
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideC4Media
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDC4Media
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine LearningC4Media
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at SpeedC4Media
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsC4Media
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsC4Media
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerC4Media
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleC4Media
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeC4Media
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereC4Media
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing ForC4Media
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data EngineeringC4Media
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreC4Media
 

Mehr von C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 

Kürzlich hochgeladen

Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 

Kürzlich hochgeladen (20)

Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 

Functional Reactive Programming in the Netflix API

  • 1. Functional Reactive Programming in the Netflix API Ben Christensen Software Engineer – API Platform at Netflix @benjchristensen http://www.linkedin.com/in/benjchristensen http://techblog.netflix.com/ QCon London – March 6 2013 onsdag den 6. marts 13
  • 2. InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /netflix-functional-rx
  • 3. Presented at QCon London www.qconlondon.com Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide
  • 4. onsdag den 6. marts 13
  • 5. More than 33 million Subscribers in more than 50 Countries and Territories onsdag den 6. marts 13
  • 6. Netflix accounts for 33% of Peak Downstream Internet Traffic in North America Netflix subscribers are watching more than 1 billion hours a month onsdag den 6. marts 13
  • 7. API traffic has grown from ~20 million/day in 2010 to >2 billion/day 0 500 1000 1500 2000 2010 2011 2012 Today millionsofAPIrequestsperday onsdag den 6. marts 13
  • 10. onsdag den 6. marts 13
  • 11. Open API Netflix Devices API Request Volume by Audience onsdag den 6. marts 13
  • 12. Netflix API Dependency A Dependency D Dependency G Dependency J Dependency M Dependency P Dependency B Dependency E Dependency H Dependency K Dependency N Dependency Q Dependency C Dependency F Dependency I Dependency L Dependency O Dependency R onsdag den 6. marts 13
  • 13. /ps3/home Dependency F 10 Threads Dependency G 10 Threads Dependency H 10 Threads Dependency I 5 Threads Dependency J 8 Threads Dependency A 10 Threads Dependency B 8 Threads Dependency C 10 Threads Dependency D 15 Threads Dependency E 5 Threads Dependency K 15 Threads Dependency L 4 Threads Dependency M 5 Threads Dependency N 10 Threads Dependency O 10 Threads Dependency P 10 Threads Dependency Q 8 Threads Dependency R 10 Threads Dependency S 8 Threads Dependency T 10 Threads /android/home /tv/home Functional Reactive Dynamic Endpoints Asynchronous Java API onsdag den 6. marts 13
  • 14. /ps3/home Dependency F 10 Threads Dependency G 10 Threads Dependency H 10 Threads Dependency I 5 Threads Dependency J 8 Threads Dependency A 10 Threads Dependency B 8 Threads Dependency C 10 Threads Dependency D 15 Threads Dependency E 5 Threads Dependency K 15 Threads Dependency L 4 Threads Dependency M 5 Threads Dependency N 10 Threads Dependency O 10 Threads Dependency P 10 Threads Dependency Q 8 Threads Dependency R 10 Threads Dependency S 8 Threads Dependency T 10 Threads /android/home /tv/home Functional Reactive Dynamic Endpoints Asynchronous Java API Hystrix fault-isolation layer onsdag den 6. marts 13
  • 15. /ps3/home Dependency F 10 Threads Dependency G 10 Threads Dependency H 10 Threads Dependency I 5 Threads Dependency J 8 Threads Dependency A 10 Threads Dependency B 8 Threads Dependency C 10 Threads Dependency D 15 Threads Dependency E 5 Threads Dependency K 15 Threads Dependency L 4 Threads Dependency M 5 Threads Dependency N 10 Threads Dependency O 10 Threads Dependency P 10 Threads Dependency Q 8 Threads Dependency R 10 Threads Dependency S 8 Threads Dependency T 10 Threads /android/home /tv/home Functional Reactive Dynamic Endpoints Asynchronous Java API onsdag den 6. marts 13
  • 16. RxJava “a library for composing asynchronous and event-based programs using observable sequences for the Java VM” A Java port of Rx (Reactive Extensions) https://rx.codeplex.com (.Net and Javascript by Microsoft) onsdag den 6. marts 13
  • 17. Do we really need another way of “managing” concurrency? onsdag den 6. marts 13
  • 18. Discovery of Rx began with a re-architecture ... onsdag den 6. marts 13
  • 19. ... that collapsed network traffic into coarse API calls ... onsdag den 6. marts 13
  • 20. ... that collapsed network traffic into coarse API calls ... Nested, conditional, parallel execution onsdag den 6. marts 13
  • 21. ... and we wanted to allow anybody to create endpoints, not just the “API Team” onsdag den 6. marts 13
  • 22. onsdag den 6. marts 13
  • 23. Concurrency without each engineer reading and re-reading this -> (awesome book ... everybody isn’t going to - or should have to - read it though, that’s the point) onsdag den 6. marts 13
  • 24. Owner of API should retain control of concurrency behavior. onsdag den 6. marts 13
  • 25. public Data getData(); What if the implementation needs to change from synchronous to asynchronous? How should the client execute that method without blocking? spawn a thread? Owner of API should retain control of concurrency behavior. onsdag den 6. marts 13
  • 26. public void getData(Callback<T> c); public Future<T> getData(); public Future<List<Future<T>>> getData(); What about ... ? onsdag den 6. marts 13
  • 28. Iterable pull Observable push T next() throws Exception returns; onNext(T) onError(Exception) onCompleted()  //  Iterable<String>    //  that  contains  75  Strings  getDataFromLocalMemory()    .skip(10)    .take(5)    .map({  s  -­‐>        return  s  +  "_transformed"})    .forEach(          {  println  "next  =>  "  +  it})  //  Observable<String>    //  that  emits  75  Strings  getDataFromNetwork()    .skip(10)    .take(5)    .map({  s  -­‐>        return  s  +  "_transformed"})    .subscribe(          {  println  "onNext  =>  "  +  it}) onsdag den 6. marts 13
  • 29. Iterable pull Observable push T next() throws Exception returns; onNext(T) onError(Exception) onCompleted()  //  Iterable<String>    //  that  contains  75  Strings  getDataFromLocalMemory()    .skip(10)    .take(5)    .map({  s  -­‐>        return  s  +  "_transformed"})    .forEach(          {  println  "onNext  =>  "  +  it})  //  Observable<String>    //  that  emits  75  Strings  getDataFromNetwork()    .skip(10)    .take(5)    .map({  s  -­‐>        return  s  +  "_transformed"})    .subscribe(          {  println  "onNext  =>  "  +  it}) onsdag den 6. marts 13
  • 30. Instead of blocking APIs ... class  VideoService  {      def  VideoList  getPersonalizedListOfMovies(userId);      def  VideoBookmark  getBookmark(userId,  videoId);      def  VideoRating  getRating(userId,  videoId);      def  VideoMetadata  getMetadata(videoId); } class  VideoService  {      def  Observable<VideoList>  getPersonalizedListOfMovies(userId);      def  Observable<VideoBookmark>  getBookmark(userId,  videoId);      def  Observable<VideoRating>  getRating(userId,  videoId);      def  Observable<VideoMetadata>  getMetadata(videoId); } ... create Observable APIs: onsdag den 6. marts 13
  • 31. onsdag den 6. marts 13
  • 32. onsdag den 6. marts 13
  • 33. onsdag den 6. marts 13
  • 34. onsdag den 6. marts 13
  • 35. onsdag den 6. marts 13
  • 36. onsdag den 6. marts 13
  • 37. Observable.toObservable("one",  "two",  "three")          .take(2)          .subscribe((arg)  -­‐>  {                    System.out.println(arg);          }); Java8 Observable.toObservable("one",  "two",  "three")    .take(2)    .subscribe((arg:  String)  =>  {            println(arg)    }) Scala (-­‐>      (Observable/toObservable  ["one"  "two"  "three"])    (.take  2)      (.subscribe  (fn  [arg]  (println  arg)))) Clojure    Observable.toObservable("one",  "two",  "three")        .take(2)          .subscribe({arg  -­‐>  println(arg)}) Groovy    Observable.toObservable("one",  "two",  "three")        .take(2)          .subscribe(lambda  {  |arg|  puts  arg  }) JRuby onsdag den 6. marts 13
  • 38.        Observable.create({  observer  -­‐>            try  {                  observer.onNext(new  Video(id))                observer.onCompleted();            }  catch(Exception  e)  {                observer.onError(e);            }        }) onsdag den 6. marts 13
  • 39.        def  Observable<VideoRating>  getRating(userId,  videoId)  {                //  fetch  the  VideoRating  for  this  user  asynchronously                return  Observable.create({  observer  -­‐>                        executor.execute(new  Runnable()  {                                def  void  run()  {                                    try  {                                          VideoRating  rating  =  ...  do  network  call  ...                                        observer.onNext(rating)                                        observer.onCompleted();                                      }  catch(Exception  e)  {                                        observer.onError(e);                                      }                                      }                        })                })        } Asynchronous Observable with Single Value onsdag den 6. marts 13
  • 40.        def  Observable<VideoRating>  getRating(userId,  videoId)  {                //  fetch  the  VideoRating  for  this  user  asynchronously                return  Observable.create({  observer  -­‐>                        executor.execute(new  Runnable()  {                                def  void  run()  {                                    try  {                                          VideoRating  rating  =  ...  do  network  call  ...                                        observer.onNext(rating)                                        observer.onCompleted();                                      }  catch(Exception  e)  {                                        observer.onError(e);                                      }                                      }                        })                })        } Asynchronous Observable with Single Value onsdag den 6. marts 13
  • 41. Synchronous Observable with Multiple Values        def  Observable<Video>  getVideos()  {                return  Observable.create({  observer  -­‐>                      try  {                              for(v  in  videos)  {                                observer.onNext(v)                          }                          observer.onCompleted();                      }  catch(Exception  e)  {                          observer.onError(e);                      }                })        } Caution: This is eager and will always emit all values regardless of subsequent operators such as take(10) onsdag den 6. marts 13
  • 42. Synchronous Observable with Multiple Values        def  Observable<Video>  getVideos()  {                return  Observable.create({  observer  -­‐>                      try  {                              for(v  in  videos)  {                                observer.onNext(v)                          }                          observer.onCompleted();                      }  catch(Exception  e)  {                          observer.onError(e);                      }                })        } Caution: This is eager and will always emit all values regardless of subsequent operators such as take(10) onsdag den 6. marts 13
  • 43. Asynchronous Observable with Multiple Values  def  Observable<Video>  getVideos()  {        return  Observable.create({  observer  -­‐>              executor.execute(new  Runnable()  {                    def  void  run()  {                        try  {                                for(id  in  videoIds)  {                                  Video  v  =  ...  do  network  call  ...                                  observer.onNext(v)                              }                              observer.onCompleted();                          }  catch(Exception  e)  {                              observer.onError(e);                          }                      }              })        })  } onsdag den 6. marts 13
  • 44. Asynchronous Observable with Multiple Values  def  Observable<Video>  getVideos()  {        return  Observable.create({  observer  -­‐>              executor.execute(new  Runnable()  {                    def  void  run()  {                        try  {                                for(id  in  videoIds)  {                                  Video  v  =  ...  do  network  call  ...                                  observer.onNext(v)                              }                              observer.onCompleted();                          }  catch(Exception  e)  {                              observer.onError(e);                          }                      }              })        })  } onsdag den 6. marts 13
  • 45. Observable<SomeData> a = getDataA(); Observable<SomeData> b = getDataB(); Observable<SomeData> c = getDataC(); Observable.merge(a, b, c) .subscribe( { element -> println("data: " + element)}, { exception -> println("error occurred: " + exception.getMessage())} ) Combining via Merge onsdag den 6. marts 13
  • 46. Observable<SomeData> a = getDataA(); Observable<String> b = getDataB(); Observable<MoreData> c = getDataC(); Observable.zip(a, b, c, {x, y, z -> [x, y, z]}) .subscribe( { triple -> println("a: " + triple[0] + " b: " + triple[1] + " c: " + triple[2])}, { exception -> println("error occurred: " + exception.getMessage())} ) Combining via Zip onsdag den 6. marts 13
  • 47. Observable<SomeData> a = getDataA(); Observable<String> b = getDataB(); Observable<MoreData> c = getDataC(); Observable.zip(a, b, c, {x, y, z -> [x, y, z]}) .subscribe( { triple -> println("a: " + triple[0] + " b: " + triple[1] + " c: " + triple[2])}, { exception -> println("error occurred: " + exception.getMessage())} ) Error Handling onsdag den 6. marts 13
  • 48. Observable<SomeData> a = getDataA(); Observable<String> b = getDataB(); Observable<MoreData> c = getDataC() .onErrorResumeNext(getFallbackForDataC()); Observable.zip(a, b, c, {x, y, z -> [x, y, z]}) .subscribe( { triple -> println("a: " + triple[0] + " b: " + triple[1] + " c: " + triple[2])}, { exception -> println("error occurred: " + exception.getMessage())} ) Error Handling onsdag den 6. marts 13
  • 49. def Observable getVideos(userId) { return VideoService.getVideos(userId) } onsdag den 6. marts 13
  • 50. def Observable getVideos(userId) { return VideoService.getVideos(userId) } Asynchronous request that returns Observable<Video> onsdag den 6. marts 13
  • 51. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) } onsdag den 6. marts 13
  • 52. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) } Reactive operator on the Observable that takes the first 10 Video objects then unsubscribes. onsdag den 6. marts 13
  • 53. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .map({ Video video -> // transform video object }) } onsdag den 6. marts 13
  • 54. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .map({ Video video -> // transform video object }) } The ‘map’ operator allows transforming the input value into a different output. onsdag den 6. marts 13
  • 55.        Observable<R>  b  =  Observable<T>.map({  T  t  -­‐>              R  r  =  ...  transform  t  ...            return  r;        }) onsdag den 6. marts 13
  • 56. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... }) } onsdag den 6. marts 13
  • 57. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... }) } We change to ‘mapMany’ which is like merge(map()) since we will return an Observable<T> instead of T. onsdag den 6. marts 13
  • 58.  Observable<R>  b  =  Observable<T>.mapMany({  T  t  -­‐>          Observable<R>  r  =  ...  transform  t  ...        return  r;  }) onsdag den 6. marts 13
  • 59.  Observable<R>  b  =  Observable<T>.mapMany({  T  t  -­‐>          Observable<R>  r  =  ...  transform  t  ...        return  r;  }) onsdag den 6. marts 13
  • 60. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... }) } Nested asynchronous calls that return more Observables. onsdag den 6. marts 13
  • 61. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... }) } Observable<VideoMetadata> Observable<VideoBookmark> Observable<VideoRating> onsdag den 6. marts 13
  • 62. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... }) } Each Observable transforms its data using ‘map’ onsdag den 6. marts 13
  • 63. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> // for each video we want to fetch metadata def m = video.getMetadata() .map({ Map<String, String> md -> // transform to the data and format we want return [title: md.get("title"), length: md.get("duration")] }) // and its rating and bookmark def b ... def r ... // compose these together }) } onsdag den 6. marts 13
  • 64. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> def m ... def b ... def r ... // compose these together }) } onsdag den 6. marts 13
  • 65. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> def m ... def b ... def r ... // compose these together return Observable.zip(m, b, r, { metadata, bookmark, rating -> // now transform to complete dictionary // of data we want for each Video return [id: video.videoId] << metadata << bookmark << rating }) }) } onsdag den 6. marts 13
  • 66. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> def m ... def b ... def r ... // compose these together return Observable.zip(m, b, r, { metadata, bookmark, rating -> // now transform to complete dictionary // of data we want for each Video return [id: video.videoId] << metadata << bookmark << rating }) }) } The ‘zip’ operator combines the 3 asynchronous Observables into 1 onsdag den 6. marts 13
  • 67.        Observable.zip(a,  b,  {  a,  b,  -­‐>              ...  operate  on  values  from  both  a  &  b  ...            return  [a,  b];  //  i.e.  return  tuple        }) onsdag den 6. marts 13
  • 68. def Observable<Map> getVideos(userId) { return VideoService.getVideos(userId) // we only want the first 10 of each list .take(10) .mapMany({ Video video -> def m ... def b ... def r ... // compose these together return Observable.zip(m, b, r, { metadata, bookmark, rating -> // now transform to complete dictionary // of data we want for each Video return [id: video.videoId] << metadata << bookmark << rating }) }) } return a single Map (dictionary) of transformed and combined data from 4 asynchronous calls onsdag den 6. marts 13
  • 69. onsdag den 6. marts 13
  • 70. Observable<Video> emits n videos to onNext() onsdag den 6. marts 13
  • 71. Takes first 10 then unsubscribes from origin. Returns Observable<Video> that emits 10 Videos. onsdag den 6. marts 13
  • 72. For each of the 10 Video objects it transforms via ‘mapMany’ function that does nested async calls. onsdag den 6. marts 13
  • 73. For each Video ‘v’ it calls getMetadata() which returns Observable<VideoMetadata> These nested async requests return Observables that emit 1 value. onsdag den 6. marts 13
  • 74. The Observable<VideoMetadata> is transformed via a ‘map’ function to return a Map of key/values. onsdag den 6. marts 13
  • 75. Same for Observable<VideoBookmark> and Observable<VideoRating> onsdag den 6. marts 13
  • 76. The 3 ‘mapped’ Observables are combined with a ‘zip’ function that emits a Map with all data. onsdag den 6. marts 13
  • 77. The full sequence emits Observable<Map> that emits a Map for each of 10 Videos. onsdag den 6. marts 13
  • 78. Client code treats all interactions with the API as asynchronous The API implementation chooses whether something is blocking or non-blocking and what resources it uses. onsdag den 6. marts 13
  • 79. Example of latency reduction achieved by increasing number of threads used by Observables. onsdag den 6. marts 13
  • 80. + Observable<User>  u  =  new  GetUserCommand(id).observe(); Observable<Geo>  g  =  new  GetGeoCommand(request).observe(); Observable.zip(u,  g,  {user,  geo  -­‐>                  return  [username:  user.getUsername(),                                  currentLocation:  geo.getCounty()]       }) RxJava coming to Hystrix https://github.com/Netflix/Hystrix onsdag den 6. marts 13
  • 81. <dependency  org="com.netflix.rxjava"  name="rxjava-­‐core"  rev="x.y.z"  /> <dependency  org="com.netflix.rxjava"  name="rxjava-­‐groovy"  rev="x.y.z"  /> <dependency  org="com.netflix.rxjava"  name="rxjava-­‐clojure"  rev="x.y.z"  /> <dependency  org="com.netflix.rxjava"  name="rxjava-­‐scala"  rev="x.y.z"  /> <dependency  org="com.netflix.rxjava"  name="rxjava-­‐jruby"  rev="x.y.z"  /> <dependency>        <groupId>com.netflix.rxjava</groupId>        <artifactId>rxjava-­‐core</artifactId>        <version>x.y.z</version> </dependency> ... or for a different language ... To get started ... onsdag den 6. marts 13
  • 82. Functional Reactive in the Netflix API with RxJava http://techblog.netflix.com/2013/02/rxjava-netflix-api.html Optimizing the Netflix API http://techblog.netflix.com/2013/01/optimizing-netflix-api.html RxJava https://github.com/Netflix/RxJava @RxJava Ben Christensen @benjchristensen http://www.linkedin.com/in/benjchristensen Netflix is Hiring http://jobs.netflix.com onsdag den 6. marts 13