Skip to content

Track and expose node capabilities per connection - #529

Open
hjohn wants to merge 1 commit into
mainfrom
feature/node-capabilities
Open

hjohn wants to merge 1 commit into
mainfrom
feature/node-capabilities

Conversation

@hjohn

@hjohn hjohn commented Oct 20, 2026 •

Copy link
Copy Markdown

Adds AxonServerConnection.supports(String capability), backed by the capabilities reported in PlatformInfo on every (re)connect in AxonServerManagedChannel.

Lets a client check in advance whether the node it's currently connected to supports an optional RPC/behavior, rather than calling it and reacting to UNIMPLEMENTED. Re-evaluated on every reconnect, so gaining/losing a capability (e.g. after moving to a different cluster node) takes effect immediately rather than being cached for the connection's lifetime.

A redirect is now followed to completion. Previously the client called GetPlatformServer and, on a redirect, simply opened the stream against the node it was pointed at without ever asking it anything. It now re-runs the handshake against each node it is sent to until one answers for itself, with a hop limit. Since every answer reports the capabilities of the node that produced it, the client holds the capabilities of whichever node it ends up on - including when it stops following redirects and stays put, because following one more hop would land it on an unqueried node again.

This happens inside connect(), before the connection is handed out, so there is no window in which the connection is usable with capabilities still unknown, and the set is fixed for as long as that connection holds.

Also exposes the two RPCs that supersede the snapshotted-source path: DcbEventChannel.sourceWithSnapshot and SnapshotChannel.findLastSnapshot. The source(SnapshottedSourceRequest) overload is deprecated, since Axon Server no longer implements the RPC behind it.

Depends on AxonIQ/axon-server-api#80 for PlatformInfo.capabilities, and on AxonIQ/axon-server-api#78 for the new RPCs.

First consumer: AxoniqFramework's AxonServerEventStorageEngine, in a followup PR.

@hjohn
hjohn requested a review from a team as a code owner October 20, 2026 13:56
@hjohn
hjohn requested review from MGathier, m1l4n54v1c and trimoq and removed request for a team October 20, 2026 13:56
@hjohn
hjohn force-pushed the feature/node-capabilities branch from c54da83 to 61dd82a Compare October 20, 2026 14:05
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

* either does not support it, or has not advertised any capabilities at all (e.g. because it predates capability
* negotiation)
*/
boolean supports(String capability);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Where is the list of available capabilities maintained? A hint in the javadoc where to find the list of available capabilities would be helpful for users of that API.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed. We should have some notion of where these are given. A reference back to Axon Server may suffice, that'll likely hint people to check the Reference Guide for this.

@smcvb smcvb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Frankly, I think this is fine as is. We can imagine all kinds of "nice" enumerations of option we'd have, but we (1) wouldn't have the list right now at all and (2) that'll tie us in to potential breaking API changes. By using a String for the capability, we have a lot of flexibility. Granted, I agree with @hatzlj, that some form of listing, somewhere, would be important.

* either does not support it, or has not advertised any capabilities at all (e.g. because it predates capability
* negotiation)
*/
boolean supports(String capability);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed. We should have some notion of where these are given. A reference back to Axon Server may suffice, that'll likely hint people to check the Reference Guide for this.

@hjohn
hjohn force-pushed the feature/node-capabilities branch 2 times, most recently from ac152f9 to 22fdcaa Compare October 26, 2026 14:42

@smcvb smcvb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some minor pointers out of curiosity

}

@Override
@Deprecated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Curious: why deprecate this? I understand it's recommended to use the other, but there's not anything inherently wrong with this API, right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

There is, in 2026.1.x (until we release a fixed version) it will SKIP a potential matching event when using this callback. That's what broke platform for Mitchel. I don't recommend having a mix of fixed and unfixed versions.

* @return the response containing an optional snapshot, events to source a model, and a consistency marker to be
* used when trying to append new events to the event store
* @deprecated superseded by {@link #sourceWithSnapshot(SourceWithSnapshotRequest)}. Axon Server no longer
* implements the RPC behind this method and answers it with {@code UNIMPLEMENTED}; it resumed sourcing one past

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ooow didn't know we would be going the route of dropping the regular source operation. Does @m1l4n54v1c / @MGathier / @trimoq agree with this?

@hjohn hjohn Oct 26, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is not the regular source operation, this is the source with snapshot which is broken and which we disabled in the AF 5.4.1 update. I think it is best to let it be superceded with one that works correctly rather than trying to fix it.

return result.get();
}
/*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is aa...interesting change. Not sure what happened with your commits here, @hjohn.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sorry, you're so fast ;) Didn't even get to check this yet. Will fix.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The line endings were changed. Original had CRLF (which is incorrect).

@hjohn hjohn Oct 26, 2026 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You can toggle showing white space changes in Github (temporarily) with the gear button next to the Submit Review button. With that off, you can see the true diff.

@hjohn
hjohn force-pushed the feature/node-capabilities branch 2 times, most recently from c8b1379 to d65a8ad Compare October 27, 2026 15:58
Adds AxonServerConnection.supports(String capability), backed by the
capabilities reported in PlatformInfo on every (re)connect.

A redirect is now followed to completion: the node we are sent to is
asked for its own PlatformInfo in turn, until one answers for itself.
Previously the client took the redirect on trust and opened the stream
against a node it had never spoken to. Each answer reports the
capabilities of the node that produced it, so whichever node we end up
on we hold its capabilities - including when we stop following redirects
and stay where we are, since following one more hop would land us on an
unqueried node again.

This all happens inside connect(), before the connection is handed out,
so the set is known up front and fixed for as long as it holds.

Also adds DcbEventChannel.sourceWithSnapshot and
SnapshotChannel.findLastSnapshot for the superseding Axon Server RPCs,
and deprecates the source(SnapshottedSourceRequest) overload, whose RPC
is no longer implemented.
@hjohn
hjohn force-pushed the feature/node-capabilities branch from d65a8ad to 34ee892 Compare October 27, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants