You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+47-1Lines changed: 47 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -532,7 +532,53 @@ But before discussing it, it's necessary to explain a difference in each pair of
532
532
2. Methods with `RetryRunnable` and `RetryCallable` are contextual and may dynamically alter their behavior for the given iteration depending on the context passed. The `RetryContext` provides provides all necessary iteration-specific information.
533
533
534
534
535
-
## 9. Contextual Promises
535
+
## 9. Context variables & contextual Promises
536
+
537
+
Ahh, those dreaded `TreadLocal`-s we all hate, love to hate, but, neveretheless, use everywhere. It's quite common to store some contextual data (like authenticated user and current locale) inside `ThreadLocal` variables. Sometimes it's a custom code, sometimes the code from third-party library we can't alter.
538
+
539
+
Typically, we spawn asynchronous code from some thread with well-known characteristics, like HTTP request thread. Here we can easly access contextual information from thread-local variables. However, using thread-local variables from asynchronous code block is hard while it's impossible to predict what thread from the pool will execute the code. It's necessary to capture the context of the one thread and propagate it to threads executing asynchronous code.
540
+
541
+
To solve this issue, there Tascalate Concurrent provides `ContextVar` class, that serves as a proxy over thread-local variable for multi-threaded code. Typical usage scenario is the following:
542
+
543
+
1. Define `ContextualPromiseFactory` holding `ContextVar`-s from existing thread-local variables.
544
+
2. Capture a context of the thread that spawns asynchronous operations.
545
+
3. Convert a `Promise` to context-aware promise.
546
+
```java
547
+
classMyService {
548
+
// Tread-local variables; they are configured by some custom code (irrelevant for Tascalate Concurrent)
log.info("Get data for user "+MyService.CURRENT_PRINCIPAL.name());
569
+
executeHttpRequest(url);
570
+
});
571
+
```
572
+
In example above, after the call to `Promise.as(newContextualPromise)` all of the derrived promises may access contextual information captured in originated thread (i.e. code blocks in thenApply / thenAccept).
573
+
574
+
Worth to mention, that copying contextual variables has certain performance penalty. To stop it at the certain level, just use `Promise.raw()` to undecorate derrived promises (as with any other decorator):
575
+
```java
576
+
Promise<Void> afterHttpRequest =
577
+
httpRequest.raw()
578
+
.thenRun(() -> {
579
+
// MyService.CURRENT_PRINCIPAL, MyService.CURRENT_LOCALE are not available here
580
+
});
581
+
```
536
582
537
583
## 10. Decorators for CompletionStage / CompletableFuture / Promise
0 commit comments