prashantwason commented on PR #19790:
URL: https://github.com/apache/hudi/pull/19790#issuecomment-6009732921

   Pushed 2216888 and merged master (1c85053, conflicts with #19575 resolved). 
Here is how `DistributedRegistry.register(jsc)` now works:
   
   1. **Already registered with the current context** (`isRegistered()`): 
return `this`.
   2. **Never registered** (`registeredAppId == null`): register `this`, stamp 
`registeredAppId`, return `this`. This is the normal first-time path. I reused 
the `registeredAppId` field from #19575 as the "was registered before" marker 
instead of adding a separate flag; it is still only stamped when this call 
actually registers.
   3. **Stale** (registered before, but its id is no longer in the current 
`AccumulatorContext`, i.e. the previous SparkContext is gone and 
`AccumulatorV2` refuses a second registration):
      - If this instance was already replaced, delegate to the replacement 
(`replacement = replacement.register(jsc)`). So every cache still holding the 
original resolves to the same live accumulator, and a replacement that goes 
stale after *another* restart is replaced in turn and swapped into 
`REGISTRY_MAP` too (the map holds the replacement by then, not the original).
      - Otherwise create a fresh `DistributedRegistry` that **shares** the 
stale instance's `counters` map (no copy), register it, swap it into 
`Registry.REGISTRY_MAP`, and remember it as `replacement`.
   
   What changed versus the previous revision:
   - **Counters are shared, not copied.** Previously the counters were copied 
once at swap time, so anything still holding the stale instance (the metadata 
writer's `registry` field, `HoodieWrapperFileSystem`'s static registries) kept 
adding to an accumulator nobody reports, and those updates were lost. With a 
shared map, those updates land in the counters the replacement reports. 
Executors are unaffected: Spark ships `copy()`, which creates its own map; only 
driver-side instances share.
   - **Staleness is detected explicitly instead of via `catch 
(IllegalStateException)`.** The broad catch also treated unrelated failures 
(e.g. a stopped SparkContext) as staleness and then threw uncaught from the 
second `register`, leaving the caches half-updated. Now any other registration 
failure just propagates.
   - **Tests:** `testRegisterHandlesStaleAccumulator` additionally checks that 
an update through the stale instance is visible in the replacement, and that 
after the replacement itself goes stale, a new registered replacement is 
created, cached, keeps the counters, and is returned to holders of both older 
instances.
   
   `TestDistributedRegistry`, `TestDistributedRegistryUnderTaskRetry` and 
`TestRecordIndexLookupMetrics` pass locally on the merged branch.
   
   @danny0405 @rahil-c could you take another look when you get a chance? 
Thanks!
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to