Skip to content

IGNITE-28940 Choose the marshaller by transport, not by message class - #13462

Open
anton-vinogradov wants to merge 17 commits into
apache:masterfrom
anton-vinogradov:ignite-28940
Open

IGNITE-28940 Choose the marshaller by transport, not by message class#13462
anton-vinogradov wants to merge 17 commits into
apache:masterfrom
anton-vinogradov:ignite-28940

Conversation

@anton-vinogradov

Copy link
Copy Markdown
Contributor

The marshaller used for a message's @Marshalled fields was a property of the
message class: @UseBinaryMarshaller decided it, and the factory bound the
chosen marshaller into the generated companion at registration time.

Why that is the wrong place

Binary cannot be used where marshalling cannot afford a cluster-wide class
registration, and that is a property of the call site. The registration is
MarshallerContextImpl#registerClassName -> proposeMapping -> fut.get(),
which waits for discovery, so it must never happen on a discovery thread. Ignite
classes usually skip it thanks to META-INF/classnames.properties, but that list
is not closed under nesting - a plain CacheConfiguration needs types that are
not on it.

The call sites are already separated by transport, and the hand-written half of
the API works this way: MarshallableMessage#marshal(Marshaller) takes the
marshaller as a parameter. Only generated code kept it in a field.

Change

  • Marshaller is now a parameter of MessageMarshaller and MessageMarshalling;
    the generator stops storing it and passes it down to nested messages.
  • Communication call sites pass ctx.marshaller(), discovery call sites pass
    marshallerContext().jdkMarshaller().
  • @UseBinaryMarshaller (60 classes), AbstractMessageFactoryProvider#init and
    both marshaller fields are gone, as is initProvider in IgniteKernal.

Wire format

The format is now a function of the transport, not of the class, so a class that
travels both transports is marshalled differently on each. Deliberate changes:

class change
ErrorMessage, PartitionHashRecord, TransactionsHashRecord jdk -> binary, on the communication leg
BinaryMetadataVersionInfo binary -> jdk, on the discovery leg
StoredCacheData jdk -> binary, on the communication leg (snapshot restore)

StoredCacheData is not in the ticket's list: it was found while reviewing this
change. It carries CacheConfiguration and QueryEntity blobs and reaches
communication through SnapshotRestoreOperationResponse -> SingleNodeMessage,
so the transport rule moves it to binary. Registration is allowed there, and
binary is the smaller of the two for a CacheConfiguration.

BinaryMetadataVersionInfo needed one more fix: the same long-lived instance
from the local metadata cache travels discovery in the data bag and communication
in MetadataResponseMessage, and a marshalled instance keeps its serialized
form. MetadataResponseMessage#metadataVersionInfo now stores a copy, so bytes
of one transport cannot leak into the other.

Verified

MessageProcessorTest (codegen goldens regenerated), IgniteCoreMessagesSerializationTest,
DirectMarshallingMessagesTest, MessageMarshalOnceTest, CompressedMessageTest,
GridIoManagerOrderedUnmarshalFailureTest, DiscoveryUnmarshalVulnerabilityTest,
QueryEntityMessageSerializationTest, LazyServiceConfigurationMessageSerializationTest,
SecurityBasicPermissionSetSerializationTest, TxDeadlockDetectionMessageMarshallingTest,
GridCacheQueryResponseUnmarshalTest, BinaryMetadataRegistrationInsideEntryProcessorTest,
GridCacheAtomicFullApiSelfTest, the continuous-query and p2p suites, and the
calcite PlanExecutionTest / ContinuousExecutionTest /
CalciteCommunicationMessageSerializationTest.

Full build of all modules and the strict checkstyle profile are clean.

🤖 Generated with Claude Code

anton-vinogradov and others added 2 commits August 11, 2026 01:09
The marshaller was picked from the message: @UseBinaryMarshaller on the
class decided it, and the factory bound the chosen one into the generated
companion at registration. But binary cannot be used where marshalling
cannot afford a cluster-wide class registration, and that is a property
of the call site, not of the message: registering waits for discovery, so
a discovery thread must never do it.

The marshaller is now a parameter of MessageMarshaller and
MessageMarshalling, passed down to nested messages by the generated code.
Communication call sites pass ctx.marshaller(), discovery call sites pass
the jdk one. The annotation, the two marshaller fields of the factory
provider and its init() are gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A message instance that travels both transports must not carry bytes of
one into the other: BinaryMetadataVersionInfo lives in the local metadata
cache, goes to discovery in the data bag and to communication in
MetadataResponseMessage, and a marshalled instance keeps its serialized
form. The response now stores a copy.

GridTestUtils.loadMarshaller still asked the generated companion for a
constructor taking a Marshaller, which the generator no longer writes,
and IncrementalSnapshotTest injected an ErrorMessage marshalled with jdk
into a communication message the receiver now reads with binary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
anton-vinogradov and others added 8 commits August 11, 2026 18:14
…t on a discovery thread

Marshalling is done by the sending thread, and a schema-aware marshaller registers unknown class names in the
cluster, which takes a discovery round. On a discovery thread that round never completes - this very thread is
the one to deliver the answer.

ErrorMessage carries an arbitrary user class and travels both transports, so it always uses the JDK marshaller
of the local node. DistributedProcess sends the result of a process from a discovery thread whenever the
process finishes synchronously, so it now hands the send over to the system pool.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… send over to the pool

A coordinator change between the handover and the actual send made the deferred task and the resend of the node
left listener target the same new coordinator, so the result was sent twice. Resolving the coordinator upfront
keeps the former addressing: the deferred send goes to the failed coordinator and is dropped, and the resend
stays the only live one.

The local coordinator branch marshals nothing, so it no longer goes through the pool.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts marshaller

Every caller had to know which marshaller its transport speaks and pass it next to the kernal context the
marshaller came from. Two entry points now name the transport itself: CommunicationMarshalling for the
schema-aware one and DiscoveryMarshalling for the JDK one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…oints

The classes are final and hold static methods only, so nothing can instantiate them anyway.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nsports

The wire form of a @Marshalled field is cached in its companion field, so an instance marshalled by one transport
hands the other transport bytes of a format it does not read. A shared instance crosses transports in
DistributedProcess, which sends the result of a process by communication and then by discovery, and in the binary
metadata cache, whose entries answer requests and travel the data bag at once.

The new @JdkMarshalled tells the generated marshaller to use the JDK marshaller of the local node whatever the
transport speaks, so the cached bytes stay readable by both. It replaces what these classes did by hand: the
private helper of ErrorMessage and the defensive copy of MetadataResponseMessage, both dropped.

PartitionHashRecord kept the cached bytes across java serialization, since its byte fields were not transient
unlike the ones of its neighbours. DistributedProcessMarshalThreadTest covers the guard that keeps a result off
the discovery thread.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ng it off the discovery thread

The result travels both transports, so the marshaller has to be the same on both legs and it has to be the one
that needs no class name registration. @JdkMarshalled on SingleNodeMessage states exactly that, and it covers
every payload of every process, including the ones not written yet.

That makes the discovery thread guard of sendSingleMessage pointless: marshalling the result no longer waits for
a discovery round, so it is safe where master has always done it. The method is back to its former shape, and
with it goes the handover to the pool that reordered the send against the node left resend.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

/runall

@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

/top

@anton-vinogradov

anton-vinogradov commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

/runall


🚀 RunAll queuedbuild 9275680 · live progress & verdict: Ignite PR Checker. The verdict lands here when the run finishes.
🛑 Superseded by a newer /run-all.

@anton-vinogradov

anton-vinogradov commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@anton-vinogradov 🚀 RunAll queuedbuild 9275976 · live progress & verdict: Ignite PR Checker. Your previous run was cancelled — this one supersedes it. The verdict lands here when the run finishes.
🏁 Run finished. ♻️ Auto re-run #3 — 1 suite that failed mid-run, ≈ settled by 05:57 MSK — details in the verdict comment.

Ignite asserts that every test class belongs to a suite, and the check runs before the test chain, so the whole
RunAll stopped at it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

/run-all

@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

@anton-vinogradov that looks like an Ignite PR Checker command — but the checker doesn't know your accounts yet, so nothing was triggered. Everything it does runs under your own accounts (there is no bot); setting that up takes about two minutes:

  1. Log in at https://ignite-pr-checker.is-a.dev with a TeamCity (ci2) access token — create one at ci2 → Profile → Access Tokens.
  2. In settings (⚙) switch on at least one option — Auto re-run blocker suites needs nothing extra — and save your GitHub login in the PR-commands field. That's enough: commands work, the checker acks and narrates from its own account.
  3. The full experience — switch on Comment my runs' verdicts on the GitHub PR with a GitHub personal access token (create one here, classic, public_repo scope): acks and the live run status then come from your own account, plus checkstyle autofix becomes available. Auto-visa all my runs posts the verdict to the IGNITE ticket (needs a JIRA PAT).

Then comment here:

  • /run-all — queue the whole RunAll chain under your TeamCity account (/run-all top — at the top of the build queue);
  • /top — move the run your command started to the top of the queue while it still waits.

Your command comment gets a 🚀 and narrates the run — live ETA, finish, auto re-run waves — and the verdict lands as one comment that updates in place until everything settles. Tokens are stored encrypted, and only while the options are on.

@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

/top

1 similar comment
@anton-vinogradov

Copy link
Copy Markdown
Contributor Author

/top

@anton-vinogradov

anton-vinogradov commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

/runall


🚀 RunAll queuedbuild 9278217 · live progress & verdict: Ignite PR Checker. Your previous run was cancelled — this one supersedes it. The verdict lands here when the run finishes.
🏁 Run finished — analysing; the verdict comment follows.

anton-vinogradov and others added 5 commits August 12, 2026 18:41
Extracting the send was only needed to hand it to the pool from the discovery thread guard, which is gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rshaller in unmarshalNio

The pin belongs to the message, so a subclass has to marshal the inherited fields the same way its parent does.
It did not: CalciteErrorMessage took the marshaller of the transport while ErrorMessage took the JDK one, which
sent an exception through binary on communication where master sent it through jdk.

The nio method emitted the name of the pinned marshaller without declaring it, so a message that combined
@JdkMarshalled with @NioField did not compile at all.

The codegen test now covers both: the fixture carries a @NioField, and a subclass of it checks that the pin
reaches the generated companion of a child.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Documented
@Target(value = TYPE)
@Retention(RUNTIME)
public @interface UseBinaryMarshaller {

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.

Why binary changed on opposite JDK?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Now Discovery uses jdk, Communication - binary, with some exceptions.

* Marshalling of the discovery transport, which speaks the JDK marshaller: a discovery message is marshalled on a
* discovery thread, where waiting for a cluster-wide type registration would never finish.
*/
public final class DiscoveryMarshalling {

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.

Why it is in communication package? Also package managers might be revised

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agree, the package does not fit them. Moving these two means moving MessageMarshalling as well, since they sit next to it and it comes from master, so I would rather do all three in a separate issue than widen this one.

import org.jetbrains.annotations.Nullable;

/** Marshalling of the communication transport, which speaks the schema-aware marshaller. */
public final class CommunicationMarshalling {

@Vladsz83 Vladsz83 Aug 12, 2026

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.

Only minority of the messages requires BinaryMarshaller. Why we use it for all of them? It is able to marshal non-serializable and won't fail where it should. Is it faster than JDKMarshaller? Any proofs? It processes schema. Won't we get any perf. drop on marshalling with it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Measured it. Binary is faster on every payload a message field actually carries, except exceptions, where the two are equal.

Round trip (marshal + unmarshal), corretto-17, 2000 warmup + 20000 iterations, three runs, numbers from the last one:

payload jdk, us/op binary, us/op speedup jdk, bytes binary, bytes
small POJO 6.21 3.43 1.8x 121 40
list of 100 POJOs 57.72 22.24 2.6x 2048 4196
map of 50 String to UUID 14.95 5.38 2.8x 1626 1346
exception with a cause 20.59 24.79 0.83x 2138 2144
CacheConfiguration 27.60 7.60 3.6x 3432 636
QueryEntity 7.74 1.48 5.2x 783 161

Two results are worth reading carefully.

Exceptions are a tie, and that is expected. Throwable declares writeObject, so BinaryUtils.isCustomJavaSerialization sends it to OptimizedMarshaller - the binary format never runs. That is also why ErrorMessage pins jdk in this PR: binary buys nothing there and would only register the class name of every new exception type cluster-wide.

Binary is bigger on a list of equal objects. It writes the schema per object, while jdk writes the class descriptor once and back-references it. On everything else binary is smaller, up to 5x on CacheConfiguration.

The schema processing you asked about is what pays for itself here: it is written per object, but reading does not walk the whole graph.

The benchmark is a throwaway test class, not part of the PR. It builds both marshallers the way tests do - Marshallers.jdk() and createStandaloneBinaryMarshaller() - and times U.unmarshal(marsh, U.marshal(marsh, obj), loader) in a loop. I can attach it if you want to re-run it.

}

MessageMarshalling.unmarshal(e, ctx, cctx.cacheObjectContext(), ldr);
CommunicationMarshalling.unmarshal(e, ctx, cctx.cacheObjectContext(), ldr);

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.

The same. Why Communication marshaling? How do I know it? To me, MessageMarshalling look much better. It will decide what and how to do. Now I need to decide. Let's reconsider.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let's refactor naming, linking to the thread in a separate issue.
This one has another goal.


try {
MessageMarshalling.unmarshal(cacheMsg, cctx.kernalContext(), null, cctx.deploy().globalLoader());
CommunicationMarshalling.unmarshal(cacheMsg, cctx.kernalContext(), null, cctx.deploy().globalLoader());

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.

Same. Why CommunicationMarshalling ? Why if someone puts DiscoveryMarshalling? Is it deprecated, protected?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tests will fail :)

* All changes must be made with the respect of RU rules.
*/
// Travels both transports: by discovery when a cache starts, by communication when a snapshot is restored.
@JdkMarshalled

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.

Even so, why not marshall with the marshaller choosen? Why discovery ort Communication should change marshaller?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The not changing marshallers, they keep it as is with minor fixes, which was luckily passed before.


try {
MessageMarshalling.unmarshal(req, ctx, null, U.resolveClassLoader(clsLdr, ctx.config()));
CommunicationMarshalling.unmarshal(req, ctx, null, U.resolveClassLoader(clsLdr, ctx.config()));

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.

Same. MessageMarshalling looks better. Noone cares which marshalling to call. Just pick up MessageMarshalling. Now we need to know.

boolean loc = ctx.localNodeId().equals(res.nodeId()) && !ctx.config().isMarshalLocalJobs();

if (!loc)
MessageMarshalling.unmarshal(res, ctx, null, U.resolveClassLoader(dep.classLoader(), ctx.config()));

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.

All the others places too. MessageMarshalling looks better. Gets the work of marsahaling type choise incapsulated. Not, exposed to a developer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Possible compatibility issues. Please, check rolling upgrade cases

This PR modifies protected classes (with Order annotation).
Changes to these classes can break rolling upgrade compatibility.

Affected files:

  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/GenericValueMessage.java
  • modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/message/QueryStartRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoUserMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/EventsDataBagItem.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/managers/eventstorage/GridEventStorageResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEntryPredicateAdapter.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictionEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheInvokeDirectResult.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheReturn.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/StoredCacheData.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/BinaryMetadataVersionInfo.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTtlUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridNearUnlockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtUnlockRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/TransactionAttributesAwareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/AtomicApplicationAttributesAwareRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicFullUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateFilterRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateInvokeRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicSingleUpdateRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/NearCacheUpdates.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/UpdateErrors.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtForceKeysRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtForceKeysResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionSupplyMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxKey.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxEntryValueHolder.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxLocksRequest.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/TxLocksResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/PartitionHashRecord.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/TransactionsHashRecord.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerEntry.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerReceiverMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/task/GridTaskResultResponse.java
  • modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceSingleNodeDeploymentResult.java
  • modules/core/src/main/java/org/apache/ignite/internal/util/ErrorMessage.java
  • modules/core/src/main/java/org/apache/ignite/internal/util/distributed/SingleNodeMessage.java
  • modules/core/src/test/java/org/apache/ignite/internal/codegen/MessageProcessorTest.java

@anton-vinogradov

anton-vinogradov commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Ignite PR Checker verdict · RunAll build 9278815 · 147 suites ran, 0 reused

⚠️ This run doesn't cover the PR fully:

  • 1 commit(s) pushed since this run — it tested older code

Everything below is what it did manage to say.

🔎 No blockers found — but the run above can't prove the PR is clean. 22 pre-existing/flaky tests filtered out. Re-run once the above is sorted out.

♻️ Settled after 2 auto re-run wave(s): #1 — early: Control Utility 1; #2 — 1 broken suite(s).

@anton-vinogradov

anton-vinogradov commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Ignite PR Checker verdict · RunAll build 9279430 · 147 suites ran, 0 reused

No blockers — nothing in this run looks caused by this PR. 20 pre-existing/flaky tests filtered out.

♻️ Settled after 1 auto re-run wave(s): #1 — 2 watch suite(s).

try {
return loadMarshaller(msg);
}
catch (RuntimeException ignored) {

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.

Looks too tough. Maybe we need a comment here?

// Marshal eagerly: the heavy partition-map copy lands in the "Full message preparing" stage, and the
// message cached in FinishState is sent to late joiners as is (the send-path marshal-once turns no-op).
MessageMarshalling.marshal(msg, cctx.kernalContext(), null);
CommunicationMarshalling.marshal(msg, cctx.kernalContext(), null);

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.

Refactoring this issue might set us to revert or rewrite this ticket again I'm afraid. We split marshalling type. This is the nase of this ticket

* goes to the coordinator by communication and comes back in the {@link FullMessage} by discovery, while a marshalled
* field caches its wire form for the second leg.
*/
public class DistributedProcessResultMarshallingTest extends GridCommonAbstractTest {

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.

One Test for one @Test? Can we put it in some existing Test?

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.

2 participants