Skip to content

Antalya 26.6: Add an Antalya-only protocol version advertised in the ServerHello - #2378

Draft
zvonand wants to merge 6 commits into
antalya-26.6from
feature/antalya-26.6/antalya-protocol-version
Draft

zvonand wants to merge 6 commits into
antalya-26.6from
feature/antalya-26.6/antalya-protocol-version

Conversation

@zvonand

@zvonand zvonand commented Sep 15, 2026

Copy link
Copy Markdown
Member

Upstream ClickHouse bumps protocol versions whenever it changes interserver communication.

It uses separate counters such as DBMS_TCP_PROTOCOL_VERSION for the main TCP protocol and DBMS_CLUSTER_PROCESSING_PROTOCOL_VERSION for cluster-processing messages.

Antalya cannot safely extend those counters, because upstream may later reuse the same next version number for a different feature, creating conflicts after a rebase.

The fix is to leave upstream counters untouched and use one separate DBMS_ANTALYA_PROTOCOL_VERSION for all Antalya-only protocol changes.

Antalya servers advertise it in ServerHello, so Antalya features can evolve independently without protocol-version collisions during rebases.

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):

Add an Antalya-only protocol version advertised in the ServerHello

CI/CD Options

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Unit tests
  • Performance tests
  • Aarch64 tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • CAS (content-addressed storage; Antalya only)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • OAuth (5m)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

Antalya carries wire features that do not exist upstream and rebases onto every
upstream release. An Antalya-only change that takes a slot in
`DBMS_TCP_PROTOCOL_VERSION` or `DBMS_CLUSTER_PROCESSING_PROTOCOL_VERSION` is
renumbered by the next rebase, so the same number comes to mean two different
things in two shipped builds.

`DBMS_ANTALYA_PROTOCOL_VERSION` is a counter in a number space upstream cannot
reach, in its own header rather than in `ProtocolDefines.h`, whose tail is where
every rebase conflicts. `TCPHandler::sendHello` appends " (antalya:N)" to the
`ServerHello` name on every connection; `Connection::receiveHello` strips it and
keeps `min(own, N)`. Version 1 is the advertisement itself, with no payload.

The advertisement is one-directional by necessity. The client writes its `Hello`
before reading anything from the peer, so it cannot gate a marker on what the
peer is, and every field in that packet is one an upstream server acts on:
`client_name` is persisted to `system.query_log` and compared against the Query
packet's `ClientInfo` under `validate_tcp_client_information`, so a marker there
would fail a `remote()` query against any peer that does not strip it with
`CLIENT_INFO_DOES_NOT_MATCH`. `server_name` carries no such role - it is
client-side display text that reaches no system table - which is why the server
is the side that speaks.

A feature that needs the server to learn the client's version will need a new
Antalya-only client packet type sent after the Addendum, gated on the negotiated
version. The Addendum cannot carry it: `TCPHandler::receiveAddendum` reads a
fixed field list and cannot tell a client that wrote an extra field from one that
did not, so it would read bytes that are not there. See
`docs/en/antalya/protocol.md`.

The only effect on an upstream peer is cosmetic: a client that does not strip the
marker displays `ClickHouse (antalya:1)` as the server name.

Covered by `gtest_antalya_protocol` for the marker grammar, `05054` for the
advertisement being independent of the client name, `05053` for no Antalya string
reaching `system.query_log`, and `test_antalya_protocol`, which exercises both
directions against a build that predates the marker.
@zvonand zvonand added port-antalya PRs to be ported to all new Antalya releases antalya-26.6 labels Sep 15, 2026
@github-actions

github-actions Bot commented Sep 15, 2026

Copy link
Copy Markdown

Workflow [PR], commit [f2c8d7c]

@zvonand
zvonand marked this pull request as draft September 16, 2026 13:01
`docs/en/interfaces/specs/NativeProtocol.md` is the canonical description of
the native protocol and the file a third-party client is built against, so the
`ServerHello` `server_name` row now says that an Antalya build appends
" (antalya:N)" and that the suffix may be ignored or stripped. That row is the
whole delta against a file which tracks upstream through every rebase; the
counter itself stays documented in `docs/en/antalya/protocol.md`, which also
records when a future Antalya wire change must grow that delta - when it changes
the layout of a packet the spec describes field by field, because a client that
does not know about an added field cannot parse the stream past it.

The same doc records why the advertisement has no opt-out. `server_name` is a
build-time value any fork may set, so a client cannot treat it as fixed;
`client_name` is the field that reaches `system.query_log` and
`validate_tcp_client_information`, and it is never marked. A per-node switch
would only add a state in which two Antalya nodes that both support a feature
fail to negotiate it because one was configured not to advertise.
Keep only the comments that carry something the code does not: the bump
rule for `DBMS_ANTALYA_PROTOCOL_VERSION`, the marker grammar, the bounded
parse in `parseMarker`, and the sanitization ordering the client depends
on. The rest repeated the code or `docs/en/antalya/protocol.md`.

Drop the tests whose coverage is pinned elsewhere:

- `05054_antalya_protocol_server_hello.py` hand-rolled a native client to
  read the `ServerHello` name, which `gtest_antalya_protocol.cpp` pins at
  the unit level and the integration test proves over a real connection.
- `test_interserver_secret_negotiates`: `TCPHandler::sendHello` has no
  branches, so no kind of connection can skip the marker.
- `test_remote_table_function_sends_a_matching_client_info` and
  `test_client_name_in_query_log_is_untouched` duplicated
  `05053_antalya_protocol_marker.sql`, which runs with
  `validate_tcp_client_information` enabled by `tests/config/install.sh`.
- `test_distributed_cluster_negotiates` asserted the same log line through
  the same code as `test_remote_function_negotiates`.

The integration module needs no server config now, so `configs/` goes with
them.
The same facts were stated up to three times: that the client `Hello` is
never marked, that only the server advertises, that the client caps with
`min(own, server)`. State each once, lead with the wire form, and turn
the rules for a future wire change into a checklist.

Drop the `Scope` section, whose only unique sentence - negotiation is per
hop - moved into the intro, and the paragraph describing a client-to-server
channel that does not exist yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

antalya-26.6 port-antalya PRs to be ported to all new Antalya releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant