by Brad Wood & Luis Majano - Ortus Solutions
In this session, we will explore the concepts of asynchronous and parallel programming with the ColdBox Async Manager and Java’s Completable Futures APIs. We will explore the concept of async computations, async pipelines, exception handling, scheduling and so much more. Pain 💊 medication is not included.
- 📧 Email: [email protected], [email protected]
- 🐦 Twitter:
- 🔗 Site: https://www.ortussolutions.com
- 📖 Docs: https://coldbox.ortusbooks.com/digging-deeper/promises-async-programming
Brad
- Intros, Get to know you, What do you want from the workshop?
Luis
- [√] The NB (non-blocking) movement
- Has made NodeJS shine, but other languages support this as well.
- Movement to more async/parallel computations
- Overall movement to the async world
- [√] Lessons from Callbacks
- Also refered to as Callback hell 🔥
- Example: Callback Hell
- Can make developers cry 😢
- Never ending nesting collection of closures/functions 🕷️
- Callbacks could be called multiple times by the other library.
- Who has been there before? Don't lie! 🤥
- Also refered to as Callback hell 🔥
- [√] Movement to promises
- JavaScript has made this very popular
- To get some sanity back into to development from call back hellfire 🔥
- [√] What is a promise?
- Can have 3 different states:
Resolve
: When completedReject
: Error or something elsePending
: Not executing just yet
- Cancel and Resolve them programmatically
- Two channels of communication Promises Track
Data
Error
- Can have 3 different states:
- [] What about ColdFusion?
- [√]
cfthread
, right?? right? right? 🤔- Great BUUUUUUT for very very very very basic threading
- Easy, but plagued with issues, which makes developers ALSO cry :😢
- No way to choose where it runs (thread pool)
- No concept of returning data, it's up to you to monitor/track/report data
- Hard to manage them (cancel, monitor, pause), you are on your own buddy!
- No functional approaches to coding them
- Managing multiple threads and joining can be cumbersome and terrifying 🧟♀️
- Example: Interceptor State Manager - Process Async All
- [√]
runAsync()
=> Nothing existed until ACF2018/Lucee 5.3- A step up, but not a big step
- Still Many Issues:
- Backed by a custom wrapper to
java.util.concurrent.Future
- Simplistic error handler with no way to recover
- No way to continue executing pipelines after an exception.
- Concept of two tracks is broken!
- No way to choose or reuse the executor to run the sub-sequent
then()
operations. - Lucee actually creates a new
singleThreadExecutor()
for EVERYthen()
operation. - No way to operate on multiple futures at once
- No way to combine/compose futures
- Only works with closures, does not work on actually calling component methods
- Backed by a custom wrapper to
- [√]
{x}map(), {x}each()
parallel processing- Adobe 2021+ & Lucee 5+
- Limited to 50 threads in Adobe, 10 standard edition
- Easy to use
- Not easy to do exception handling, actually, you can't except wrap things in multiple try/catches
- It does short circuit exception handling
- NO Control over it
- It will break out whenever an exception is detected and leave unprocessed items in a collection
- No consistency
- No logging
- Example: Native Parallel Programming
- [√] Asynchronous Programming is NOT Easy!
- [] Concurrency issues / Race conditions
- Know the limitations on shared resources
- Some data structures allow for multiple threads, some don’t, some you need to wrap to make them concurrent
java.util.concurrent package
package
- Read before write
- Locking becomes part of your life, unfortunately
- Atomic operations
- Idempotent operations
- Time stamps
- [] Dealing with multiple threads
cfthread
you have to be the managerrunAsync
you can't be the manager- Sharing data between threads
- [] No more
writedump/aborts
- Logs become your best friend
- ColdBox Debugger Panels: tracers and request profilers
- Easy to spot an asynchronous developers...... They are in the corner, crying! 😭
- [] Concurrency issues / Race conditions
- 🤢 We have three approaches to threading which are extremely simplistic and not very powerful at all.
- [√]
Brad
- [√] 📦 ColdBox Futures are similar to JavaScript Promises but backed by the Java API of
CompletableFuture
- ☕️ JDK 8 Introduced
CompletableFutures
,CompletionStages
, Executors, Lambdas and much more. - 🦄 Java
CompletableFutures
are like JavaScript Promises, but you know Java devs, over complicate things, even names! - We have ported the majority of this functionality to CFML:
ColdBox Futures
- ColdBox, WireBox, CacheBox and LogBox
- Adapted for our dynamic language => many enhancements
- []
AsyncManager
class in charge of all async capabilities- Standalone: create an instance as a singleton
- ColdBox:
async()
helper in handlers/layouts/views/interceptorsAsyncManager@coldbox
orwirebox:asyncManager
Async@coreDelegates
- Functions:
- Create Futures
- Create/Manage Executors
- Create/Manage Schedule Tasks
- [] Intro to Executors ⚡️⚡️⚡️
- What is an executor
- Default Executor is the Fork Join Pool ⑂⟕
- We can customize it and create new ones as well
- [] Creating the Future!! 🚀🚀🚀
- ☕️ JDK 8 Introduced
Luis
- [] 🎩 It's all about that pipeline |||||||
- [√] Java API:
thenApply()
,thenAccept()
,thenRun()
, why? - [] ⚡️ CF API:
then()
andthenRun()
(Easier + Dynamic API)- [] Curiosity:
CompletableFutures
never end! 🦈🌪 This is So Ironic! Sharknado! 🦈🌪
- [] Curiosity:
- ⨠ Magical Pipelines
- 💿 Data Transformations
- ⌚️ Dealing with Timeouts
- ✅ Success on timeout
- ❌ Exception on timeout
- 🔋Checking status
- Pipelines are independent of data
- 💪 Exercise 02
- [√] Java API:
Brad
- [] 😭 Everybody has problems, our code has them too, sometimes...
- Let's review the promises data/error tracks
- [] ❤️🩹 Dealing with Exceptions
- [] 🗄️ Built-in logging - example
- []
handle
methods - both results and exceptions - example
- []
- [] Custom logging
- [] 🏥 Recovering with data - example
- [] 💪 Exercise 03
Luis
- [] ⚡️ Thread of execution
- [] 🏊♂️ Changing the pool
- [] Register many different types of executors/pool
- []
Fixed
: Control the amount of threads, cpu intensive, io intensive - []
Single
: A processing queue FIFO - []
Cached
: Ever expanding demand queue - []
Scheduled
: Scheduled Tasks
- []
- [] 🔋 Checking status reinforcements
- 🔌 [] Shutdowns and awaiting terminations - example
- ☠️ [] Killing tasks? really? How?
- [] 💪 Exercise 04
- [] Register many different types of executors/pool
Brad
- https://www.callicoder.com/java-8-completablefuture-tutorial/
- Combining Futures
- Very much like a
reduce()
operations - Remember this: 1-1 operation
- Very much like a
- Composing Futures
- Monadic design pattern (https://medium.com/thg-tech-blog/monad-design-**pattern**-in-java-3391d4095b3f)
- Hmm: 2-1 Operation, future of futures!
- [] Working with multiple futures
- [] Exercise 05
Brad & Luis
[] What is a scheduler executor [] Options in ColdBox [] ;;
To NOT show full stacktraces on exceptions, then run this in CommandBox
config set showVerboseErrors=false