reactive programming with rxjava for efficient data access

77
Reactive Programming with RxJava for Efficient Data Access Ben Christensen | Software Engineer, Netflix Michael Nitschinger | Software Engineer, Couchbase

Upload: couchbase

Post on 14-Jun-2015

1.719 views

Category:

Data & Analytics


1 download

DESCRIPTION

Video available at: https://vimeo.com/109853625 Applications which exclusively rely on synchronous data access very often hit a scalability wall when things get slow and their thread pools are exhausted. New paradigms like reactive programming alleviate this and provide extensive toolsets to deal with the ever growing demands of web applications. This talk shows how to build scalable and reactive applications by making use of the brand new Couchbase Java SDK 2.0 and the RxJava library. We will also cover stability patterns to increase failure resiliency to be available, 24/365 be it under unexpected load spikes or server failures.

TRANSCRIPT

Page 1: Reactive Programming with RxJava for Efficient Data Access

Reactive Programming with RxJavafor Efficient Data Access

Ben Christensen | Software Engineer, Netflix

Michael Nitschinger | Software Engineer, Couchbase

Page 2: Reactive Programming with RxJava for Efficient Data Access

RxJava

Reactive Extensions for Async Programming

Page 3: Reactive Programming with RxJava for Efficient Data Access

Reactive Extensions for Async Programming

RxJavahttp://github.com/ReactiveX/RxJavahttp://reactivex.io

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Page 4: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.create(subscriber -> { subscriber.onNext("Hello world!"); subscriber.onCompleted();}).forEach(System.out::println);

Synchronoussingle value

Page 5: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.create(subscriber -> { subscriber.onNext("Hello"); subscriber.onNext("world"); subscriber.onNext("!"); subscriber.onCompleted();}).forEach(System.out::println);

Synchronousmulti-value

Page 6: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.create(subscriber -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Throwable e) { subscriber.onError(e); }}).subscribeOn(Schedulers.io()) .forEach(System.out::println);

Asynchronoussingle valuewith error handling

Page 7: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.create(subscriber -> { int i = 0; while (!subscriber.isUnsubscribed()) { subscriber.onNext(i++); }}).take(10).forEach(System.out::println);

Synchronousmulti-valuewith unsubscribe

Page 8: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.create(subscriber -> { AtomicInteger i = new AtomicInteger(); AtomicLong requested = new AtomicLong(); subscriber.setProducer(r -> { if (requested.getAndAdd(r) == 0) { do { if (subscriber.isUnsubscribed()) { break; } subscriber.onNext(i.incrementAndGet()); } while (requested.decrementAndGet() > 0); } });}).observeOn(Schedulers.newThread()) .take(10).forEach(System.out::println);

Synchronous multi-valued source that thread-hopswith “reactive pull” backpressure

Page 9: Reactive Programming with RxJava for Efficient Data Access

Single Multiple

Sync T getData() Iterable<T> getData()

Async Future<T> getData() Observable<T> getData()

Observable.from(iterable) .observeOn(Schedulers.newThread()) .take(10).forEach(System.out::println);

Synchronous multi-valued source that thread-hopswith “reactive pull” backpressure

Page 10: Reactive Programming with RxJava for Efficient Data Access
Page 11: Reactive Programming with RxJava for Efficient Data Access
Page 12: Reactive Programming with RxJava for Efficient Data Access
Page 13: Reactive Programming with RxJava for Efficient Data Access

13

Abstract Concurrency

©2014 Couchbase, Inc. — Proprietary and Confidential

Page 14: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 15: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 16: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 17: Reactive Programming with RxJava for Efficient Data Access

 Observable<R> b = Observable<T>.flatMap({ T t -> Observable<R> r = ... transform t ...    return r; })

flatMap

Page 18: Reactive Programming with RxJava for Efficient Data Access

 Observable<R> b = Observable<T>.flatMap({ T t -> Observable<R> r = ... transform t ...    return r; })

flatMap

Page 19: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 20: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 21: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 22: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 23: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 24: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 25: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 26: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 27: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 28: Reactive Programming with RxJava for Efficient Data Access

    Observable.zip(a, b, { a, b, -> ... operate on values from both a & b ...      return [a, b]; // i.e. return tuple    })

Page 29: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 30: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 31: Reactive Programming with RxJava for Efficient Data Access
Page 32: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 33: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 34: Reactive Programming with RxJava for Efficient Data Access

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 an observable api:

instead of a blocking api ...

Page 35: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

1

2

34

5

6

Page 36: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

1

2

34

5

6

Page 37: Reactive Programming with RxJava for Efficient Data Access

37

Non-Opinionated Concurrency

©2014 Couchbase, Inc. — Proprietary and Confidential

Page 38: Reactive Programming with RxJava for Efficient Data Access
Page 39: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

Page 40: Reactive Programming with RxJava for Efficient Data Access
Page 41: Reactive Programming with RxJava for Efficient Data Access
Page 42: Reactive Programming with RxJava for Efficient Data Access
Page 43: Reactive Programming with RxJava for Efficient Data Access
Page 44: Reactive Programming with RxJava for Efficient Data Access

public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) { // first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); }).flatMap(data -> { // output as SSE as we get back the data (no waiting until all is done) return response.writeAndFlush(new ServerSentEvent(SimpleJson.mapToJson(data))); });}

1

2

34

6

Page 45: Reactive Programming with RxJava for Efficient Data Access
Page 46: Reactive Programming with RxJava for Efficient Data Access

// first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); })

Decouples Consumption from Production

Page 47: Reactive Programming with RxJava for Efficient Data Access

// first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); })

Decouples Consumption from Production

Page 48: Reactive Programming with RxJava for Efficient Data Access

// first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); })

Decouples Consumption from Production

Page 49: Reactive Programming with RxJava for Efficient Data Access

Decouples Consumption from Production

Page 50: Reactive Programming with RxJava for Efficient Data Access

Decouples Consumption from Production

// first request User object return new UserCommand(request.getQueryParameters().get("userId")).observe().flatMap(user -> { // then fetch personal catalog Observable<Map<String, Object>> catalog = new PersonalizedCatalogCommand(user).observe() .flatMap(catalogList -> { return catalogList.videos().<Map<String, Object>> flatMap(video -> { Observable<Bookmark> bookmark = new BookmarkCommand(video).observe(); Observable<Rating> rating = new RatingsCommand(video).observe(); Observable<VideoMetadata> metadata = new VideoMetadataCommand(video).observe(); return Observable.zip(bookmark, rating, metadata, (b, r, m) -> { return combineVideoData(video, b, r, m); }); }); }); // and fetch social data in parallel Observable<Map<String, Object>> social = new SocialCommand(user).observe().map(s -> { return s.getDataAsMap(); }); // merge the results return Observable.merge(catalog, social); })

1

2

34

5

Page 51: Reactive Programming with RxJava for Efficient Data Access

class VideoService { def Observable<VideoList> getPersonalizedListOfMovies(userId); def Observable<VideoBookmark> getBookmark(userId, videoId); def Observable<VideoRating> getRating(userId, videoId); def Observable<VideoMetadata> getMetadata(videoId);}

Clear API Communicates Potential Cost

Page 52: Reactive Programming with RxJava for Efficient Data Access

Implementation Can Differ

class VideoService { def Observable<VideoList> getPersonalizedListOfMovies(userId); def Observable<VideoBookmark> getBookmark(userId, videoId); def Observable<VideoRating> getRating(userId, videoId); def Observable<VideoMetadata> getMetadata(videoId);}

BIO Network Call

Local Cache CollapsedNetwork Call

Page 53: Reactive Programming with RxJava for Efficient Data Access

class VideoService { def Observable<VideoList> getPersonalizedListOfMovies(userId); def Observable<VideoBookmark> getBookmark(userId, videoId); def Observable<VideoRating> getRating(userId, videoId); def Observable<VideoMetadata> getMetadata(videoId);}

CollapsedNetwork CallCollapsed

Network Call

BIO NIO Network Call

Local Cache

Implementation Can Differ and Change

Page 54: Reactive Programming with RxJava for Efficient Data Access

Retrieval, Transformation, Combination all done in same

declarative manner

Page 55: Reactive Programming with RxJava for Efficient Data Access

Couchbase Java Client 2.0

Reactive from top to bottom

Page 56: Reactive Programming with RxJava for Efficient Data Access

56

Java SDK 2.0

©2014 Couchbase, Inc. — Proprietary and Confidential

It is a complete rewrite compared to 1.* and provides asynchronous & synchronous document oriented APIs.

Page 57: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 57

Couchbase Core IO

Common infrastructure & feature set for all language bindings Message oriented Asynchronous only Low overhead and performance focused Supports Java 6+ (including 8!)

Disruptor RingBuffer for implicit batching and backpressure Netty for high performance IO

Page 58: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 58

The Big Picture

Page 59: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 59

Connecting

Page 60: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 60

From Sync to Async

Page 61: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 61

Connecting Async

Page 62: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 62

Storing a Document

Page 63: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 63

Loading a Document

Page 64: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 64

Querying

Page 65: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 65

Querying

Page 66: Reactive Programming with RxJava for Efficient Data Access

Stability Patterns

Page 67: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 67

Reacting to Failure

Resiliency is key Things will go wrong, so better plan for it Do not aim for QA, aim for production

Do not trust integration points Treat the Database (SDK) as an integration point

The more you sweat in peace, the less you bleed in war.

Page 68: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 68

Useful Reading

Release It! by Michael T. Nygard

Stability Patterns & Antipatterns Capacity planning Operations

Page 69: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 69

Timeouts

The network is unreliable Servers fail The SDK contains bugs

Always specify timeouts and deal with them! The synchronous wrapper defines them for you all the time.

Page 70: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 70

Timeouts: Simple

Page 71: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 71

Timeouts: Synchronous API

Page 72: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 72

Timeouts: Complex Example

Page 73: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 73

Coordinated Retry

Fail fast

Don’t let your system get stuck Fail and backpressure

Retry

immediately won’t help either linear or exponential backoff necessary have a strategy if retry also doesn’t work (Fallbacks!)

Page 74: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 74

Coordinated Retry: Fallback

Page 75: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 75

Coordinated Retry with Delay

Page 76: Reactive Programming with RxJava for Efficient Data Access

©2014 Couchbase, Inc. — Proprietary and Confidential 76

More Patterns

Circuit Breaker

Closed if everything okay Opens once the integration point breaks Fail fast if open Rechecking with half-open

Bulkheads

Isolate failure where possible Don’t let your ship sink!

Page 77: Reactive Programming with RxJava for Efficient Data Access

QA

Thanks!