SlideShare a Scribd company logo
1 of 58
Introduction to ParSeq
To make asynchronous Java easier
Synchronous
● Result is ready when method returns
● What about methods void e.g.
void deletePerson(Long id)
● Unchecked exception (or it’s lack) is part of a
result
● Error handling through optional try-catch
mechanism
Person fetchPerson(Long id)
2
Asynchronous
● Result may be ready long after method
returns
● There must be a way to access result e.g.
using Callback or Promise
● Custom error handling
void fetchPerson(Long id, Callback callback)
void Promise<Person> fetchPerson(Long id)
3
Synchronous
fetch wait processBodyThread 1 fetch wait processBody
String googleBody = fetchBody("http://www.google.com"); //wait
processBody(googleBody);
String bingBody = fetchBody("http://www.bing.com"); //wait
processBody(bingBody);
time
waitThread 1 wait
In reality:
4
other tasks
Asynchronous
Task.par(
fetchBody("http://www.google.com").andThen(this::processBody),
fetchBody("http://www.bing.com").andThen(this::processBody)
);
fetch
wait
processBody
Thread 1 fetch
wait
processBodyThread 2
other tasks
time
5
Challenges
● Accidental complexity, unreadable code e.g.
doAsync1(function () {
doAsync2(function () {
doAsync3(function () {
doAsync4(function () {
...
})
})
})
6
Challenges
● Indeterminism
○ n! many orders in which all asynchronous operations
can finish
○ Difficult to test
○ No “current state”
● Debugging
○ State of the art is println() sprinkled around
○ No meaningful stack trace
7
Challenges
● Thread safety
○ Synchronized, locks, volatile, atomic, j.u.c.*
○ Immutability
○ 3rd party libraries
○ Thinking about Java Memory Model
○ Thread safety does not mean atomicity
8
Challenges
● Often requires all-async
//fetching Alice and Bob asynchronously
fetchPerson(aliceId, handleAliceCallback);
fetchPerson(bobId, handleBobCallback);
// hmmm... now what?
9
Core concepts: Promise<T>
● Represents state of an asynchronous
operation
● Possible states: completed (resolved),
uncompleted (unresolved)
● Container for a result of an asynchronous
operation
● Result of completed Promise<T> is either
value of type T or an exception 10
Core concepts: Task<T>
● Main abstraction and building block in
ParSeq, represents asynchronous operation
● Main ingredient of a Task<T> is a clojure
that (synchronously) returns a Promise<T>,
as if Task<T> had void Promise<T> run(...)
● Clojure starts asynchronous operation and
returns a Promise that represents the state
of that operation 11
Core concepts: Task<T>
Callable<Promise<String>> callable = () -> {
SettablePromise<String> promise = Promises.settable();
return promise;
};
● Closest construct in pure Java is a
Callable<Promise<T>>
Task<String> task = Task.async(name, () -> {
SettablePromise<String> promise = Promises.settable();
return promise;
}); 12
Core concepts: Task<T>
Callable<Promise<String>> callable = () -> {
SettablePromise<String> promise = Promises.settable();
return promise;
};
● Closest construct in pure Java is a
Callable<Promise<T>>
Task<String> task = Task.async(name, () -> {
SettablePromise<String> promise = Promises.settable();
return promise;
});
clojure
13
Core concepts: Task<T>
public <T> Promise<Response<T>> sendRequest(Request<T> request,
RequestContext requestContext) {
SettablePromise<Response<T>> promise = Promises.settable();
_restClient.sendRequest(request, requestContext,
new PromiseCallbackAdapter<T>(promise));
return promise;
}
Task<Response<T>> task =
Task.async(name, () -> sendRequest(request, requestContext));
● Real example from ParSeqRestClient
14
Core concepts: Task<T>
public <T> Promise<Response<T>> sendRequest(Request<T> request,
RequestContext requestContext) {
SettablePromise<Response<T>> promise = Promises.settable();
_restClient.sendRequest(request, requestContext,
new PromiseCallbackAdapter<T>(promise));
return promise;
}
Task<Response<T>> task =
Task.async(name, () -> sendRequest(request, requestContext));
● Real example from ParSeqRestClient
clojure
15
Core concepts: Task<T>
time
● Example execution of tasks
○ clojure synchronously returns a Promise<T>
○ Promise is completed at some point in the future
clojure
execution
Promise
completion
16
Properties of Tasks
● Tasks are lazy - creating a Task instance
does not automatically run it
● Task runs at most once
● Tasks are immutable - all Task.* methods
return new Tasks
● Programming with Tasks comes down to
creating new Tasks that depend on existing
ones (composition) 17
Creating Tasks from scratch
● Usually there is no need to create Task from
scratch using Task.async(...), instead use
existing library e.g.
_parseqRestClient.createTask(...)
● If there is a need to create a Task from
scratch use Task.async(...), don’t extend
BaseTask class
18
Parallel Composition
● Task.par(t1, t2, …)
Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo)
19
Parallel Composition
● Task.par(t1, t2, …)
Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo)
time
20
Parallel Composition
● Task.par(t1, t2, …)
Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo)
time
clojure
execution
Promise
completion
21
Sequential Composition
● Do something after Task (it’s Promise) is completed
Task<String> seq = fetchBing.andThen("seq", fetchGoogle);
22
Sequential Composition
● Do something after Task (it’s Promise) is completed
Task<String> seq = fetchBing.andThen("seq", fetchGoogle);
time
23
Sequential Composition
● Do something after Task (it’s Promise) is completed
Task<String> seq = fetchBing.andThen("seq", fetchGoogle);
time
clojure
execution
Promise
completion
24
ParSeq API: map
● Transforms result of a task
Task<String> name = Task.value("Jaroslaw");
Task<Integer> length = name.map(String::length);
25
ParSeq API: flatMap
● Runs Task that depends on result of previous Task
● fetchCompany() invoked after fetchPerson() completes
public Task<Company> fetchCompany(int id) {...}
public Task<Person> fetchPerson(int id) {...}
Task<Person> personTask = fetchPerson(id);
Task<Company> companyTask =
personTask.flatMap(person ->
fetchCompany(person.getCompanyId()));
vs
Task<Task<Company>> companyTask =
personTask.map(person ->
fetchCompany(person.getCompanyId()));
26
Exceptions handling
● All exceptions are automatically propagated
Task<Integer> fetchAndLength =
fetch404Url("http://www.google.com/idontexist")
.map("length", String::length);
● Clojures can throw checked and unchecked exceptions
fetchBody("http://www.bing.com")
.andThen(s -> { throw new IOException(); });
27
Exceptions handling
● Task API has methods to handle exceptions, equivalent
to try-catch for synchronous methods, e.g. recover()
Task<Integer> fetchAndLength =
fetch404Url("http://www.google.com/idontexist")
.recover("default", t -> "")
.map("length", s -> s.length());
28
Exceptions handling
● Exceptions can be handled explicitly, see methods
toTry(), transform()
● Try<T> interface has only two implementation:
Success<T> and Failure<T>
Task<Try<String>> tryFetch =
fetch404Url("http://www.google.com/idontexist")
.toTry();
29
withTimeout
● Fails Task if it is not completed within specified amount
of time
Task<String> fetchWithTimeout =
fetchUrl("http://www.google.com")
.withTimeout(15, TimeUnit.MILLISECONDS);
30
withTimeout
● Fails Task if it is not completed within specified amount
of time
Task<String> fetchWithTimeout =
fetchUrl("http://www.google.com")
.withTimeout(15, TimeUnit.MILLISECONDS);
time
31
ParSeq API
● ParSeq API is declarative
● Focus on “what” not “how”
● Task<T> interface does not have run() method
32
ParSeq programming model
● Express everything by composing and
transforming Tasks
● End up with one Task (Plan) that is passed
to ParSeq Engine for execution
● Rest.li implements this idea
@RestMethod.Get
public Task<Greeting> get(final Long id) {
// rest.li resource implementation
} 33
ParSeq execution model
● ParSeq Engine provides the following
guarantees:
○ Rules expressed in ParSeq API are followed e.g.
first.andThen(second) - “second” will run after “first”
is completed
○ All clojures are executed sequentially, such that
clojure of a previous Task in a sequence “happens
before” clojure of a next Task (“happens before” in
the Java Memory Model sense)
34
Clojures are executed sequentially
● All operations passed to Task.* API are
executed within a Task’s clojure
Task<Integer> length =
fetchBody("http://www.google.com")
.map("length", String::length);
time
35
Clojures are executed sequentially
● All operations passed to Task.* API are
executed within a clojure
Task<Integer> length =
fetchBody("http://www.google.com")
.map("length", String::length);
time
clojure
36
Clojures are executed sequentially
● All operations passed to Task.* API are
automatically thread safe and atomic
● No need to be concerned about:
○ Synchronized, locks, volatile, atomic, j.u.c.*
○ Immutability
○ 3rd party libraries
○ Thinking about Java Memory Model
○ Thread safety does not mean atomicity
37
Clojures are executed sequentially
● Example: find top N Candidates (synchronous)
PriorityQueue<Candidate> topCandidates = new PriorityQueue<>();
void considerCandidate(Candidate candidate) {
topCandidates.add(candidate);
if (topCandidates.size() > N) {
topCandidates.remove();
}
}
38
Clojures are executed sequentially
● Example: find top N Candidates (asynchronous)
Task<Candidate> fetchCandidate(Long Id) {...}
Task<?> considerCandidate(Long id) {
return fetchCandidate(id)
.andThen(this::considerCandidate);
}
● Using thread safe PriorityQueue is not enough
● No need to test concurrency aspect 39
Clojures are executed sequentially
Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo)
time
● Task.par(t1, t2, …) example
40
Clojures are executed sequentially
41
Clojures are executed sequentially
Task.par(
Task.callable("1000th prime", () -> nthPrime(1000)),
Task.callable("1000th prime", () -> nthPrime(1000)),
Task.callable("1000th prime", () -> nthPrime(1000))
);
● Task.par(t1, t2, …) example
time
42
Clojures are executed sequentially
● Does it mean that ParSeq is single threaded?
● No
Task.par(
fetchBody("http://www.google.com").andThen(this::processBody),
fetchBody("http://www.bing.com").andThen(this::processBody)
);
43
Clojures are executed sequentially
● Does it mean that ParSeq is single threaded?
● No
time
other tasks
other tasks
wait
processBodyThread 1
wait
Thread 2
fetch
fetch processBody
44
other tasks
Clojures are executed sequentially
● Does it mean that ParSeq is single threaded?
● No
other tasks
wait
processBodyThread 1
wait
Thread 2
time
fetch
happens
before
fetch processBody
happens
before
45
Clojures are executed sequentially
● In order to perform well ParSeq requires
developer’s cooperation. In clojures avoid:
○ blocking e.g. JDBC calls, Thread.sleep(), ...
○ CPU intensive operations
46
Blocking
● Blocking API e.g. Voldemort, JDBC
● CPU intensive computation
● Offload operation to external Executor
Task.blocking(String name,
Callable<? extends T> callable,
Executor executor)
● Supports multiple executors
● Executors management is outside ParSeq 47
Automatic cancellation
● Task abstraction borrows ideas from functional
programming, think: Task ~ function call
○ Task is lazy, only runs when needed
○ Task is immutable
○ It’s purpose is to calculate a result
○ Task runs at most once
○ Once result is known, everything that is still not
completed (for some reason) can be cancelled because
it can’t affect result
48
Automatic cancellation
Task<String> google = fetchBody("http://www.google.com");
Task<String> yahoo = fetchBody("http://www.yahoo.com");
Task<String> bing = fetchBody("http://www.~#fdcm x 0eirw.com");
Task<Integer> sumLengths =
Task.par(google.map("length", String::length),
yahoo.map("length", String::length),
bing.map("length", String::length))
.map("sum", (g, y, b) -> g + y + b);
49
Automatic cancellation
50
Tracing
● Trace is information about what happened
after calling Engine.run()
● Tracing is always enabled for all tasks
● Allows reasoning about what happened
● Includes timing information, exceptions, etc.
● Obtain trace JSON at any time by calling
Task.getTrace().toString()
● Paste JSON at go/tracevis to visualize 51
Tracing best practices
● Add short, meaningful description to every
task
HttpClient.get(url).task()
.map("getBody", response -> response.getResponseBody())
.map("length", s -> s.length());
52
Tasks Fusion
● Sequence of synchronous transformations
can be optimized and executed as a chain of
method calls
Task<Integer> length =
HttpClient.get("http://www.google.com").task()
.map("getBody", Response::getResponseBody)
.map("length", s -> s.length());
53
Batching
● Allows automatic batching of individual
asynchronous operations without affecting
code readability
54
Unit testing
● Use BaseEngineTest as a base class for a
unit test
○ Initialization and shutdown of Engine
○ Lot of helper methods
● Log trace for the tested Task
55
Best Practices
● Focus on readable, clean code
○ Split code into small, unit-testable methods that may
return Task<T>
○ Prefer method handles over lambdas
○ Limit length of lambda code blocks to few lines
○ Don’t mix functional APIs inside lambda code block
e.g. Java Stream map() and Java Optional map()
with ParSeq map()
56
Upcoming feature
● Automatic batching of GET / BATCH_GET
requests in ParSeqRestClient
● Configurable timeouts in ParSeqRestClient
● Automatic logging traces of failed plans
● Sending sample of traces to kafka for
analysis e.g. finding bottlenecks,
regressions, thread blocking, …
● ParSeq “Collections” 57
Reference
● https://github.com/linkedin/parseq/wiki
● http://linkedin.github.io/parseq/javadoc/latest
58

More Related Content

What's hot

Introduction to Storm
Introduction to Storm Introduction to Storm
Introduction to Storm
Chandler Huang
 

What's hot (20)

Asynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka StreamsAsynchronous stream processing with Akka Streams
Asynchronous stream processing with Akka Streams
 
Performance Tuning RocksDB for Kafka Streams’ State Stores
Performance Tuning RocksDB for Kafka Streams’ State StoresPerformance Tuning RocksDB for Kafka Streams’ State Stores
Performance Tuning RocksDB for Kafka Streams’ State Stores
 
Introduction to Storm
Introduction to Storm Introduction to Storm
Introduction to Storm
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Saga pattern and event sourcing with kafka
Saga pattern and event sourcing with kafkaSaga pattern and event sourcing with kafka
Saga pattern and event sourcing with kafka
 
One sink to rule them all: Introducing the new Async Sink
One sink to rule them all: Introducing the new Async SinkOne sink to rule them all: Introducing the new Async Sink
One sink to rule them all: Introducing the new Async Sink
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
Completable future
Completable futureCompletable future
Completable future
 
ITLC HN 14 - Bizweb Microservices Architecture
ITLC HN 14  - Bizweb Microservices ArchitectureITLC HN 14  - Bizweb Microservices Architecture
ITLC HN 14 - Bizweb Microservices Architecture
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
 
Hearts Of Darkness - a Spring DevOps Apocalypse
Hearts Of Darkness - a Spring DevOps ApocalypseHearts Of Darkness - a Spring DevOps Apocalypse
Hearts Of Darkness - a Spring DevOps Apocalypse
 
Introduction and Overview of Apache Kafka, TriHUG July 23, 2013
Introduction and Overview of Apache Kafka, TriHUG July 23, 2013Introduction and Overview of Apache Kafka, TriHUG July 23, 2013
Introduction and Overview of Apache Kafka, TriHUG July 23, 2013
 
Study Notes: Google Percolator
Study Notes: Google PercolatorStudy Notes: Google Percolator
Study Notes: Google Percolator
 
Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
 
JPA Best Practices
JPA Best PracticesJPA Best Practices
JPA Best Practices
 
Introduction to react_js
Introduction to react_jsIntroduction to react_js
Introduction to react_js
 
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
 
AngularJs presentation
AngularJs presentation AngularJs presentation
AngularJs presentation
 
Introduction to Spring Cloud
Introduction to Spring Cloud           Introduction to Spring Cloud
Introduction to Spring Cloud
 

Similar to Introduction to ParSeq: to make asynchronous java easier

Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async future
slicejs
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
knight1128
 
CompletableFuture
CompletableFutureCompletableFuture
CompletableFuture
koji lin
 

Similar to Introduction to ParSeq: to make asynchronous java easier (20)

The evolution of java script asynchronous calls
The evolution of java script asynchronous callsThe evolution of java script asynchronous calls
The evolution of java script asynchronous calls
 
Advanced patterns in asynchronous programming
Advanced patterns in asynchronous programmingAdvanced patterns in asynchronous programming
Advanced patterns in asynchronous programming
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming hero
 
Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022Leverage CompletableFutures to handle async queries. DevNexus 2022
Leverage CompletableFutures to handle async queries. DevNexus 2022
 
Scheduling tasks the human way - Brad Wood - ITB2021
Scheduling tasks the human way -  Brad Wood - ITB2021Scheduling tasks the human way -  Brad Wood - ITB2021
Scheduling tasks the human way - Brad Wood - ITB2021
 
Leveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyLeveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results Asynchrhonously
 
Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async future
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
동기화 시대를 뛰어넘는 비동기 프로그래밍
동기화 시대를 뛰어넘는 비동기 프로그래밍동기화 시대를 뛰어넘는 비동기 프로그래밍
동기화 시대를 뛰어넘는 비동기 프로그래밍
 
CompletableFuture
CompletableFutureCompletableFuture
CompletableFuture
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOS
 
Scala Future & Promises
Scala Future & PromisesScala Future & Promises
Scala Future & Promises
 
Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgaria
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
Flink Forward Berlin 2017: Maciek Próchniak - TouK Nussknacker - creating Fli...
Flink Forward Berlin 2017: Maciek Próchniak - TouK Nussknacker - creating Fli...Flink Forward Berlin 2017: Maciek Próchniak - TouK Nussknacker - creating Fli...
Flink Forward Berlin 2017: Maciek Próchniak - TouK Nussknacker - creating Fli...
 
function* - ES6, generators, and all that (JSRomandie meetup, February 2014)
function* - ES6, generators, and all that (JSRomandie meetup, February 2014)function* - ES6, generators, and all that (JSRomandie meetup, February 2014)
function* - ES6, generators, and all that (JSRomandie meetup, February 2014)
 

Recently uploaded

Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
amitlee9823
 
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Kandungan 087776558899
 
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
dollysharma2066
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 

Recently uploaded (20)

Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
 
2016EF22_0 solar project report rooftop projects
2016EF22_0 solar project report rooftop projects2016EF22_0 solar project report rooftop projects
2016EF22_0 solar project report rooftop projects
 
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night StandCall Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
Call Girls In Bangalore ☎ 7737669865 🥵 Book Your One night Stand
 
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar  ≼🔝 Delhi door step de...
Call Now ≽ 9953056974 ≼🔝 Call Girls In New Ashok Nagar ≼🔝 Delhi door step de...
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
 
Thermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - VThermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - V
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.ppt
 
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Ramesh Nagar Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
 
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
Employee leave management system project.
Employee leave management system project.Employee leave management system project.
Employee leave management system project.
 
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
FULL ENJOY Call Girls In Mahipalpur Delhi Contact Us 8377877756
 
Unit 1 - Soil Classification and Compaction.pdf
Unit 1 - Soil Classification and Compaction.pdfUnit 1 - Soil Classification and Compaction.pdf
Unit 1 - Soil Classification and Compaction.pdf
 
Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024
 
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
Hazard Identification (HAZID) vs. Hazard and Operability (HAZOP): A Comparati...
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
 

Introduction to ParSeq: to make asynchronous java easier

  • 1. Introduction to ParSeq To make asynchronous Java easier
  • 2. Synchronous ● Result is ready when method returns ● What about methods void e.g. void deletePerson(Long id) ● Unchecked exception (or it’s lack) is part of a result ● Error handling through optional try-catch mechanism Person fetchPerson(Long id) 2
  • 3. Asynchronous ● Result may be ready long after method returns ● There must be a way to access result e.g. using Callback or Promise ● Custom error handling void fetchPerson(Long id, Callback callback) void Promise<Person> fetchPerson(Long id) 3
  • 4. Synchronous fetch wait processBodyThread 1 fetch wait processBody String googleBody = fetchBody("http://www.google.com"); //wait processBody(googleBody); String bingBody = fetchBody("http://www.bing.com"); //wait processBody(bingBody); time waitThread 1 wait In reality: 4
  • 6. Challenges ● Accidental complexity, unreadable code e.g. doAsync1(function () { doAsync2(function () { doAsync3(function () { doAsync4(function () { ... }) }) }) 6
  • 7. Challenges ● Indeterminism ○ n! many orders in which all asynchronous operations can finish ○ Difficult to test ○ No “current state” ● Debugging ○ State of the art is println() sprinkled around ○ No meaningful stack trace 7
  • 8. Challenges ● Thread safety ○ Synchronized, locks, volatile, atomic, j.u.c.* ○ Immutability ○ 3rd party libraries ○ Thinking about Java Memory Model ○ Thread safety does not mean atomicity 8
  • 9. Challenges ● Often requires all-async //fetching Alice and Bob asynchronously fetchPerson(aliceId, handleAliceCallback); fetchPerson(bobId, handleBobCallback); // hmmm... now what? 9
  • 10. Core concepts: Promise<T> ● Represents state of an asynchronous operation ● Possible states: completed (resolved), uncompleted (unresolved) ● Container for a result of an asynchronous operation ● Result of completed Promise<T> is either value of type T or an exception 10
  • 11. Core concepts: Task<T> ● Main abstraction and building block in ParSeq, represents asynchronous operation ● Main ingredient of a Task<T> is a clojure that (synchronously) returns a Promise<T>, as if Task<T> had void Promise<T> run(...) ● Clojure starts asynchronous operation and returns a Promise that represents the state of that operation 11
  • 12. Core concepts: Task<T> Callable<Promise<String>> callable = () -> { SettablePromise<String> promise = Promises.settable(); return promise; }; ● Closest construct in pure Java is a Callable<Promise<T>> Task<String> task = Task.async(name, () -> { SettablePromise<String> promise = Promises.settable(); return promise; }); 12
  • 13. Core concepts: Task<T> Callable<Promise<String>> callable = () -> { SettablePromise<String> promise = Promises.settable(); return promise; }; ● Closest construct in pure Java is a Callable<Promise<T>> Task<String> task = Task.async(name, () -> { SettablePromise<String> promise = Promises.settable(); return promise; }); clojure 13
  • 14. Core concepts: Task<T> public <T> Promise<Response<T>> sendRequest(Request<T> request, RequestContext requestContext) { SettablePromise<Response<T>> promise = Promises.settable(); _restClient.sendRequest(request, requestContext, new PromiseCallbackAdapter<T>(promise)); return promise; } Task<Response<T>> task = Task.async(name, () -> sendRequest(request, requestContext)); ● Real example from ParSeqRestClient 14
  • 15. Core concepts: Task<T> public <T> Promise<Response<T>> sendRequest(Request<T> request, RequestContext requestContext) { SettablePromise<Response<T>> promise = Promises.settable(); _restClient.sendRequest(request, requestContext, new PromiseCallbackAdapter<T>(promise)); return promise; } Task<Response<T>> task = Task.async(name, () -> sendRequest(request, requestContext)); ● Real example from ParSeqRestClient clojure 15
  • 16. Core concepts: Task<T> time ● Example execution of tasks ○ clojure synchronously returns a Promise<T> ○ Promise is completed at some point in the future clojure execution Promise completion 16
  • 17. Properties of Tasks ● Tasks are lazy - creating a Task instance does not automatically run it ● Task runs at most once ● Tasks are immutable - all Task.* methods return new Tasks ● Programming with Tasks comes down to creating new Tasks that depend on existing ones (composition) 17
  • 18. Creating Tasks from scratch ● Usually there is no need to create Task from scratch using Task.async(...), instead use existing library e.g. _parseqRestClient.createTask(...) ● If there is a need to create a Task from scratch use Task.async(...), don’t extend BaseTask class 18
  • 19. Parallel Composition ● Task.par(t1, t2, …) Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo) 19
  • 20. Parallel Composition ● Task.par(t1, t2, …) Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo) time 20
  • 21. Parallel Composition ● Task.par(t1, t2, …) Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo) time clojure execution Promise completion 21
  • 22. Sequential Composition ● Do something after Task (it’s Promise) is completed Task<String> seq = fetchBing.andThen("seq", fetchGoogle); 22
  • 23. Sequential Composition ● Do something after Task (it’s Promise) is completed Task<String> seq = fetchBing.andThen("seq", fetchGoogle); time 23
  • 24. Sequential Composition ● Do something after Task (it’s Promise) is completed Task<String> seq = fetchBing.andThen("seq", fetchGoogle); time clojure execution Promise completion 24
  • 25. ParSeq API: map ● Transforms result of a task Task<String> name = Task.value("Jaroslaw"); Task<Integer> length = name.map(String::length); 25
  • 26. ParSeq API: flatMap ● Runs Task that depends on result of previous Task ● fetchCompany() invoked after fetchPerson() completes public Task<Company> fetchCompany(int id) {...} public Task<Person> fetchPerson(int id) {...} Task<Person> personTask = fetchPerson(id); Task<Company> companyTask = personTask.flatMap(person -> fetchCompany(person.getCompanyId())); vs Task<Task<Company>> companyTask = personTask.map(person -> fetchCompany(person.getCompanyId())); 26
  • 27. Exceptions handling ● All exceptions are automatically propagated Task<Integer> fetchAndLength = fetch404Url("http://www.google.com/idontexist") .map("length", String::length); ● Clojures can throw checked and unchecked exceptions fetchBody("http://www.bing.com") .andThen(s -> { throw new IOException(); }); 27
  • 28. Exceptions handling ● Task API has methods to handle exceptions, equivalent to try-catch for synchronous methods, e.g. recover() Task<Integer> fetchAndLength = fetch404Url("http://www.google.com/idontexist") .recover("default", t -> "") .map("length", s -> s.length()); 28
  • 29. Exceptions handling ● Exceptions can be handled explicitly, see methods toTry(), transform() ● Try<T> interface has only two implementation: Success<T> and Failure<T> Task<Try<String>> tryFetch = fetch404Url("http://www.google.com/idontexist") .toTry(); 29
  • 30. withTimeout ● Fails Task if it is not completed within specified amount of time Task<String> fetchWithTimeout = fetchUrl("http://www.google.com") .withTimeout(15, TimeUnit.MILLISECONDS); 30
  • 31. withTimeout ● Fails Task if it is not completed within specified amount of time Task<String> fetchWithTimeout = fetchUrl("http://www.google.com") .withTimeout(15, TimeUnit.MILLISECONDS); time 31
  • 32. ParSeq API ● ParSeq API is declarative ● Focus on “what” not “how” ● Task<T> interface does not have run() method 32
  • 33. ParSeq programming model ● Express everything by composing and transforming Tasks ● End up with one Task (Plan) that is passed to ParSeq Engine for execution ● Rest.li implements this idea @RestMethod.Get public Task<Greeting> get(final Long id) { // rest.li resource implementation } 33
  • 34. ParSeq execution model ● ParSeq Engine provides the following guarantees: ○ Rules expressed in ParSeq API are followed e.g. first.andThen(second) - “second” will run after “first” is completed ○ All clojures are executed sequentially, such that clojure of a previous Task in a sequence “happens before” clojure of a next Task (“happens before” in the Java Memory Model sense) 34
  • 35. Clojures are executed sequentially ● All operations passed to Task.* API are executed within a Task’s clojure Task<Integer> length = fetchBody("http://www.google.com") .map("length", String::length); time 35
  • 36. Clojures are executed sequentially ● All operations passed to Task.* API are executed within a clojure Task<Integer> length = fetchBody("http://www.google.com") .map("length", String::length); time clojure 36
  • 37. Clojures are executed sequentially ● All operations passed to Task.* API are automatically thread safe and atomic ● No need to be concerned about: ○ Synchronized, locks, volatile, atomic, j.u.c.* ○ Immutability ○ 3rd party libraries ○ Thinking about Java Memory Model ○ Thread safety does not mean atomicity 37
  • 38. Clojures are executed sequentially ● Example: find top N Candidates (synchronous) PriorityQueue<Candidate> topCandidates = new PriorityQueue<>(); void considerCandidate(Candidate candidate) { topCandidates.add(candidate); if (topCandidates.size() > N) { topCandidates.remove(); } } 38
  • 39. Clojures are executed sequentially ● Example: find top N Candidates (asynchronous) Task<Candidate> fetchCandidate(Long Id) {...} Task<?> considerCandidate(Long id) { return fetchCandidate(id) .andThen(this::considerCandidate); } ● Using thread safe PriorityQueue is not enough ● No need to test concurrency aspect 39
  • 40. Clojures are executed sequentially Task<?> par3 = Task.par(fetchBing, fetchGoogle, fetchYahoo) time ● Task.par(t1, t2, …) example 40
  • 41. Clojures are executed sequentially 41
  • 42. Clojures are executed sequentially Task.par( Task.callable("1000th prime", () -> nthPrime(1000)), Task.callable("1000th prime", () -> nthPrime(1000)), Task.callable("1000th prime", () -> nthPrime(1000)) ); ● Task.par(t1, t2, …) example time 42
  • 43. Clojures are executed sequentially ● Does it mean that ParSeq is single threaded? ● No Task.par( fetchBody("http://www.google.com").andThen(this::processBody), fetchBody("http://www.bing.com").andThen(this::processBody) ); 43
  • 44. Clojures are executed sequentially ● Does it mean that ParSeq is single threaded? ● No time other tasks other tasks wait processBodyThread 1 wait Thread 2 fetch fetch processBody 44
  • 45. other tasks Clojures are executed sequentially ● Does it mean that ParSeq is single threaded? ● No other tasks wait processBodyThread 1 wait Thread 2 time fetch happens before fetch processBody happens before 45
  • 46. Clojures are executed sequentially ● In order to perform well ParSeq requires developer’s cooperation. In clojures avoid: ○ blocking e.g. JDBC calls, Thread.sleep(), ... ○ CPU intensive operations 46
  • 47. Blocking ● Blocking API e.g. Voldemort, JDBC ● CPU intensive computation ● Offload operation to external Executor Task.blocking(String name, Callable<? extends T> callable, Executor executor) ● Supports multiple executors ● Executors management is outside ParSeq 47
  • 48. Automatic cancellation ● Task abstraction borrows ideas from functional programming, think: Task ~ function call ○ Task is lazy, only runs when needed ○ Task is immutable ○ It’s purpose is to calculate a result ○ Task runs at most once ○ Once result is known, everything that is still not completed (for some reason) can be cancelled because it can’t affect result 48
  • 49. Automatic cancellation Task<String> google = fetchBody("http://www.google.com"); Task<String> yahoo = fetchBody("http://www.yahoo.com"); Task<String> bing = fetchBody("http://www.~#fdcm x 0eirw.com"); Task<Integer> sumLengths = Task.par(google.map("length", String::length), yahoo.map("length", String::length), bing.map("length", String::length)) .map("sum", (g, y, b) -> g + y + b); 49
  • 51. Tracing ● Trace is information about what happened after calling Engine.run() ● Tracing is always enabled for all tasks ● Allows reasoning about what happened ● Includes timing information, exceptions, etc. ● Obtain trace JSON at any time by calling Task.getTrace().toString() ● Paste JSON at go/tracevis to visualize 51
  • 52. Tracing best practices ● Add short, meaningful description to every task HttpClient.get(url).task() .map("getBody", response -> response.getResponseBody()) .map("length", s -> s.length()); 52
  • 53. Tasks Fusion ● Sequence of synchronous transformations can be optimized and executed as a chain of method calls Task<Integer> length = HttpClient.get("http://www.google.com").task() .map("getBody", Response::getResponseBody) .map("length", s -> s.length()); 53
  • 54. Batching ● Allows automatic batching of individual asynchronous operations without affecting code readability 54
  • 55. Unit testing ● Use BaseEngineTest as a base class for a unit test ○ Initialization and shutdown of Engine ○ Lot of helper methods ● Log trace for the tested Task 55
  • 56. Best Practices ● Focus on readable, clean code ○ Split code into small, unit-testable methods that may return Task<T> ○ Prefer method handles over lambdas ○ Limit length of lambda code blocks to few lines ○ Don’t mix functional APIs inside lambda code block e.g. Java Stream map() and Java Optional map() with ParSeq map() 56
  • 57. Upcoming feature ● Automatic batching of GET / BATCH_GET requests in ParSeqRestClient ● Configurable timeouts in ParSeqRestClient ● Automatic logging traces of failed plans ● Sending sample of traces to kafka for analysis e.g. finding bottlenecks, regressions, thread blocking, … ● ParSeq “Collections” 57

Editor's Notes

  1. waiting is eliminated, threads are busy note 1: two threads are involved in execution note 2: req1, req2, process response 1, process response 2 execute sequentially
  2. waiting is eliminated, threads are busy note 1: two threads are involved in execution note 2: req1, req2, process response 1, process response 2 execute sequentially