Skip to content

[POM-leading] Capability proxy - #1200

Open
toinehartman wants to merge 18 commits into
feature/1010-pom-leading-for-dsls/finalfrom
feature/1010-pom-leading-for-dsls/capability-proxy
Open

toinehartman wants to merge 18 commits into
feature/1010-pom-leading-for-dsls/finalfrom
feature/1010-pom-leading-for-dsls/capability-proxy

Conversation

@toinehartman

@toinehartman toinehartman commented Sep 14, 2026

Copy link
Copy Markdown
Member

Improve maintainability and thread-safety of the client router, specifically operations related to (un)registering dynamic capabilities.

Also see:

@toinehartman toinehartman self-assigned this Sep 14, 2026
@toinehartman toinehartman added the enhancement New feature or request label Sep 14, 2026
@toinehartman
toinehartman force-pushed the feature/1010-pom-leading-for-dsls/capability-proxy branch from 8c60749 to 2c24a98 Compare September 14, 2026 15:57
@toinehartman
toinehartman marked this pull request as ready for review September 14, 2026 17:23
@sonarqubecloud

Copy link
Copy Markdown

@DavyLandman DavyLandman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I have some small clarififcation questions and a few improvements to the code.

* The inner map is keyed by registration options, with a list of registrations with those exact options. The first registration in this list is always registered with the actual client, while the others are kept for internal administration.
*/
private final Map<String, CompletableFuture<Map<Object, List<Registration>>>> registrations = new ConcurrentHashMap<>();
private final CapabilityRegistry capabilityRegistry;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: class & field have exact the same name? so capabilties or registry is verbose enough?

* details.
* </p>
*/
class CapabilityRegistry {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this not be a private class?

*
* @param R Result type of tasks
*/
class Scheduler<R> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all these classes (also the helper one) should become private static classes, such that no external class will be tempted to use them.

*
* @param R Result type of tasks
*/
class Scheduler<R> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can rename this to be more specific than schedular? Maybe: MonotonicSchedular or FairSingleThreadExecutor?

Also, can we document why Executors.newSingleThreadExecutor() is not the right fit?

Comment on lines +347 to +348
var toClient = new Registration(UUID.randomUUID().toString(), method, options);
forwardRegistration(toClient).whenCompleteAsync((v, t) -> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: how about we make forwardRegistration take the method and options as parameters and it returns the Registration it just created, such that the v in the completable future can be used by the whenComplete.

if (fromServer == null) {
var t = new IllegalStateException("Cannot unregister a capability for which no registration was sent by a server");
logger.trace("Unregister capability {} ({}). Failed: {}", method, id, t);
result.completeExceptionally(t);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that truly a failure? and not a lost race that is fine?

like if this happens, do we need to debug a problem?

var id = u.getId();

logger.trace("Unregister capability {} ({}): Submitting to scheduler...", method, id);
return scheduler.submit(result -> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after reading this code and how a user needs to think about calling result. before exiting, I'm wondering if maybe the signature should change that the closure should return a completable future? like the arguments is the scheduler and the result is a future? that way no exit out of these functions leads to a hanging future.

// Don't unset `busy` yet. Instead, doing so is the responsibility of the closure on the previous lines
// and should happen only when the task has signaled its completion.
} else {
busy.set(false);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we document in what case can we have a scheduled attemptStartTask and still have an empty task queu?

Comment on lines +490 to +492
var result = new CompletableFuture<R>();
var task = new Task<>(action, result);
tasks.offer(task);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these can be inlined, and the future might be created by the task?

}

public CompletableFuture<R> submit(Consumer<CompletableFuture<R>> action) {
var result = new CompletableFuture<R>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a subtle bug where a future should be connected to an executure, else any next element in the chain won't happen on the executor, but on the global pool.

we've made some classes that work around this issue, maybe those are nice to use?

although if we rewrite this to always return a closure, than we get rid of that problem in this specific class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants