[ 
https://issues.apache.org/jira/browse/IGNITE-28618?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Alex Abashev updated IGNITE-28618:
----------------------------------
    Description: 
h2. Summary

Receive-side mirror of IGNITE-28520. Same motivation, same mechanism — but for 
the {{finishUnmarshal}} direction.

The post-deserialisation pass already runs on the user-listener-dispatch 
thread: {{GridCacheIoManager.unmarshall}} calls 
{{cacheMsg.finishUnmarshal(cctx, ldr)}} on the dispatch thread before handing 
the message to {{processMessage}}. Just like on the send side, every 
{{GridCacheMessage}} subclass with {{CacheObject}} fields has a hand-written 
{{finishUnmarshal(GridCacheSharedContext, ClassLoader)}} override that walks 
those fields and calls {{co.finishUnmarshal(ctx, ldr)}}. Same maintenance 
hazard: a missed override silently shifts the {{Marshaller.unmarshal}} call 
onto the NIO reader (when something later asks for {{val}} via 
{{valueBytes(ctx)}}).

This ticket adds the symmetric generated method and auto-invoke so coverage is 
structural.

h2. What changes

* {{MessageSerializer}} gets {{default void finishUnmarshalCacheObjects(M msg, 
CacheObjectValueContext ctx, ClassLoader ldr)}} (no-op default).
* {{MessageSerializerGenerator}} emits {{finishUnmarshalCacheObjects}} on every 
concrete serializer with at least one traversable {{@Order}} field, with 
recursion into nested {{Message}} types via 
{{*_SER.finishUnmarshalCacheObjects(...)}}; map traversal walks both keys and 
values.
* {{GridCacheIoManager.unmarshall}} adds 
{{finishUnmarshalGeneratedCacheObjects(cacheMsg, ldr)}} *before* the existing 
{{cacheMsg.finishUnmarshal(cctx, ldr)}} (legacy code may rely on {{val}} being 
already populated for tx-key hashing / validation, so auto-invoke runs first). 
Helper gated the same way as the send-side: {{instanceof GridCacheIdMessage}}, 
context from the outer message's {{cacheId}}.
* Hand-written {{finishUnmarshal(GridCacheSharedContext, ClassLoader)}} 
overrides are removed where the body was a pure {{@Order}}-CO traversal — same 
set as the send-side cleanup:
** {{GridCacheTtlUpdateRequest}}, {{GridDhtForceKeysRequest}}, 
{{GridNearUnlockRequest}}, {{GridDhtUnlockRequest}}, 
{{GridDistributedLockRequest}}, {{GridDistributedLockResponse}}, 
{{GridDhtAtomicUpdateResponse}}, {{GridDhtAtomicNearResponse}}, 
{{GridNearGetRequest}}.
** Also dropped: {{ret.finishUnmarshal(cctx, ldr)}} call inside 
{{GridNearAtomicUpdateResponse.finishUnmarshal}} (covered by nested-message 
recursion).
* {{GridCacheReturn.finishUnmarshal}} delegates the {{CacheObject}} traversal 
to the generated {{GridCacheReturnSerializer.finishUnmarshalCacheObjects}} 
(mirror of the existing {{prepareMarshal}} bridge); the post-traversal 
binary-unwrapping ({{unwrapBinaryIfNeeded}} of {{cacheObj}} and 
{{invokeResCol}}, building the {{CacheInvokeResult}} map into {{v}}) stays 
inline — it is not part of the serializer contract.

h2. Out of scope

* Send-side migration is IGNITE-28520; this ticket only mirrors it.
* Extending auto-invoke beyond {{GridCacheIdMessage}} for either direction — 
IGNITE-ZZZZZ.

h2. Acceptance criteria

* {{GridCacheIoManager.unmarshall}} invokes 
{{finishUnmarshalGeneratedCacheObjects(cacheMsg, ldr)}} for every 
{{GridCacheIdMessage}} subclass with a non-{{null}} {{cacheObjectContext}}, 
before the legacy {{finishUnmarshal}} hook.
* {{MessageProcessorTest}} green with regenerated fixtures (each fixture now 
has both {{prepareMarshalCacheObjects}} and {{finishUnmarshalCacheObjects}}).
* Same targeted-suite gating as IGNITE-28520; in addition: 
{{IgniteCacheQueryMultiThreadedSelfTest}}, 
{{GridCacheReturnValueTransferSelfTest}} cover both directions on the same flow.
* TC-bot possible-blockers — no real regressions on read paths.

  was:
h2. Summary

Receive-side mirror of IGNITE-28520. Move the generic post-deserialisation 
{{CacheObject.finishUnmarshal}} traversal off the NIO worker by adding 
{{finishUnmarshalCacheObjects}} to {{MessageSerializer}} and auto-invoking it 
from {{GridCacheIoManager.unmarshall}} on the user-listener-dispatch thread, 
before the message is handed to {{processMessage}}.

After this lands the receive path looks like:

# {{ser.finishUnmarshalCacheObjects(msg, cacheObjCtx, ldr)}} — new auto-invoked 
traversal of {{@Order}}-annotated {{CacheObject}} / nested {{Message}} fields;
# {{cacheMsg.finishUnmarshal(cctx, ldr)}} — existing hand-written hook 
(legacy), runs after.

The same ordering rationale as send-side: legacy may rely on {{val}} being 
already populated (for tx-key hashing, validation, etc.), so auto-invoke must 
run first.

h2. Scope

* Add {{default void finishUnmarshalCacheObjects(M msg, CacheObjectValueContext 
ctx, ClassLoader ldr)}} to {{MessageSerializer}} (no-op default).
* {{MessageSerializerGenerator}}: emit symmetric 
{{finishUnmarshalCacheObjects}} method (with {{@Override}}) on every serializer 
with traversable {{@Order}} fields; recurse via per-class 
{{*_SER.finishUnmarshalCacheObjects(...)}}; map traversal walks both sides (key 
+ value).
* {{GridCacheIoManager.unmarshall}}: add 
{{finishUnmarshalGeneratedCacheObjects(cacheMsg, ldr)}} call before 
{{cacheMsg.finishUnmarshal(cctx, ldr)}}; helper gated on {{instanceof 
GridCacheIdMessage}} mirror of the prepare-side.
* Phase 2 cleanup: where a {{GridCacheMessage}} subclass 
{{finishUnmarshal(GridCacheSharedContext, ClassLoader)}} override is a pure 
{{@Order}}-CO traversal, drop it. Mirror list from IGNITE-28520:
** {{GridCacheTtlUpdateRequest}}, {{GridDhtForceKeysRequest}}, 
{{GridNearUnlockRequest}}, {{GridDhtUnlockRequest}}, 
{{GridDistributedLockRequest}}, {{GridDistributedLockResponse}}, 
{{GridDhtAtomicUpdateResponse}}, {{GridDhtAtomicNearResponse}}, 
{{GridNearGetRequest}}, {{GridNearAtomicUpdateResponse.finishUnmarshal}} — line 
{{ret.finishUnmarshal(cctx, ldr)}}.
* Update {{GridCacheReturn.finishUnmarshal}} to delegate the {{CacheObject}} 
traversal to the generated 
{{GridCacheReturnSerializer.finishUnmarshalCacheObjects}} (mirror of current 
{{prepareMarshal}} bridge); the post-traversal binary-unwrapping 
({{unwrapBinaryIfNeeded}} of {{cacheObj}} and {{invokeResCol}}, building the 
{{CacheInvokeResult}} map into {{v}}) stays inline — it is not part of the 
serializer contract.

h2. Out of scope

* The send-side migration is IGNITE-28520; this ticket only mirrors it for the 
receive side.
* Extending auto-invoke beyond {{GridCacheIdMessage}} for either direction — 
IGNITE-ZZZZZ.

h2. Acceptance criteria

* {{GridCacheIoManager.unmarshall}} invokes the new helper for 
{{GridCacheIdMessage}} subclasses, before the legacy {{finishUnmarshal}} call.
* {{MessageProcessorTest}} green with regenerated fixtures (each fixture now 
has both {{prepareMarshalCacheObjects}} and {{finishUnmarshalCacheObjects}}).
* Same targeted-suite gating as IGNITE-28520; in addition: 
{{IgniteCacheQueryMultiThreadedSelfTest}}, 
{{GridCacheReturnValueTransferSelfTest}} cover both directions.


> Move finishUnmarshal out of NIO communication thread
> ----------------------------------------------------
>
>                 Key: IGNITE-28618
>                 URL: https://issues.apache.org/jira/browse/IGNITE-28618
>             Project: Ignite
>          Issue Type: Sub-task
>            Reporter: Alex Abashev
>            Priority: Major
>
> h2. Summary
> Receive-side mirror of IGNITE-28520. Same motivation, same mechanism — but 
> for the {{finishUnmarshal}} direction.
> The post-deserialisation pass already runs on the user-listener-dispatch 
> thread: {{GridCacheIoManager.unmarshall}} calls 
> {{cacheMsg.finishUnmarshal(cctx, ldr)}} on the dispatch thread before handing 
> the message to {{processMessage}}. Just like on the send side, every 
> {{GridCacheMessage}} subclass with {{CacheObject}} fields has a hand-written 
> {{finishUnmarshal(GridCacheSharedContext, ClassLoader)}} override that walks 
> those fields and calls {{co.finishUnmarshal(ctx, ldr)}}. Same maintenance 
> hazard: a missed override silently shifts the {{Marshaller.unmarshal}} call 
> onto the NIO reader (when something later asks for {{val}} via 
> {{valueBytes(ctx)}}).
> This ticket adds the symmetric generated method and auto-invoke so coverage 
> is structural.
> h2. What changes
> * {{MessageSerializer}} gets {{default void finishUnmarshalCacheObjects(M 
> msg, CacheObjectValueContext ctx, ClassLoader ldr)}} (no-op default).
> * {{MessageSerializerGenerator}} emits {{finishUnmarshalCacheObjects}} on 
> every concrete serializer with at least one traversable {{@Order}} field, 
> with recursion into nested {{Message}} types via 
> {{*_SER.finishUnmarshalCacheObjects(...)}}; map traversal walks both keys and 
> values.
> * {{GridCacheIoManager.unmarshall}} adds 
> {{finishUnmarshalGeneratedCacheObjects(cacheMsg, ldr)}} *before* the existing 
> {{cacheMsg.finishUnmarshal(cctx, ldr)}} (legacy code may rely on {{val}} 
> being already populated for tx-key hashing / validation, so auto-invoke runs 
> first). Helper gated the same way as the send-side: {{instanceof 
> GridCacheIdMessage}}, context from the outer message's {{cacheId}}.
> * Hand-written {{finishUnmarshal(GridCacheSharedContext, ClassLoader)}} 
> overrides are removed where the body was a pure {{@Order}}-CO traversal — 
> same set as the send-side cleanup:
> ** {{GridCacheTtlUpdateRequest}}, {{GridDhtForceKeysRequest}}, 
> {{GridNearUnlockRequest}}, {{GridDhtUnlockRequest}}, 
> {{GridDistributedLockRequest}}, {{GridDistributedLockResponse}}, 
> {{GridDhtAtomicUpdateResponse}}, {{GridDhtAtomicNearResponse}}, 
> {{GridNearGetRequest}}.
> ** Also dropped: {{ret.finishUnmarshal(cctx, ldr)}} call inside 
> {{GridNearAtomicUpdateResponse.finishUnmarshal}} (covered by nested-message 
> recursion).
> * {{GridCacheReturn.finishUnmarshal}} delegates the {{CacheObject}} traversal 
> to the generated {{GridCacheReturnSerializer.finishUnmarshalCacheObjects}} 
> (mirror of the existing {{prepareMarshal}} bridge); the post-traversal 
> binary-unwrapping ({{unwrapBinaryIfNeeded}} of {{cacheObj}} and 
> {{invokeResCol}}, building the {{CacheInvokeResult}} map into {{v}}) stays 
> inline — it is not part of the serializer contract.
> h2. Out of scope
> * Send-side migration is IGNITE-28520; this ticket only mirrors it.
> * Extending auto-invoke beyond {{GridCacheIdMessage}} for either direction — 
> IGNITE-ZZZZZ.
> h2. Acceptance criteria
> * {{GridCacheIoManager.unmarshall}} invokes 
> {{finishUnmarshalGeneratedCacheObjects(cacheMsg, ldr)}} for every 
> {{GridCacheIdMessage}} subclass with a non-{{null}} {{cacheObjectContext}}, 
> before the legacy {{finishUnmarshal}} hook.
> * {{MessageProcessorTest}} green with regenerated fixtures (each fixture now 
> has both {{prepareMarshalCacheObjects}} and {{finishUnmarshalCacheObjects}}).
> * Same targeted-suite gating as IGNITE-28520; in addition: 
> {{IgniteCacheQueryMultiThreadedSelfTest}}, 
> {{GridCacheReturnValueTransferSelfTest}} cover both directions on the same 
> flow.
> * TC-bot possible-blockers — no real regressions on read paths.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to