gortiz opened a new pull request, #18736:
URL: https://github.com/apache/pinot/pull/18736

   #18458 introduced the `OperatorTypeDescriptor` SPI so plugin jars can 
register custom MSE operator types (ids ≥ 256) and report their stats over the 
`SubmitWithStream` channel. While exercising that SPI from an out-of-tree 
plugin extension we found the plugin path does not work end to end — every 
query whose stages report plugin-typed stats returned `stageStats: {"error": 
"... java.lang.ArithmeticException: / by zero"}`, and on classloader-isolated 
deployments the descriptors were never registered at all.
   
   ## Root causes
   
   1. The broker renders `stageStats` by pairing the flat per-stage stats list 
positionally against the stage's `PlanNode` tree (`InStageStatsTreeBuilder`), 
assuming built-in types at every position. `visitMailboxSend` casts the 
send-position StatMap to the built-in key class; for a plugin type the 
`EnumMap` lookup returns 0, so `Context(parallelism=0)` makes `cpuTimeMs / 
parallelism` throw. Independently, the type-mismatch branch silently drops 
every plugin-typed node, so even without the exception the plugin stats would 
never appear.
   2. `OperatorTypeRegistry` discovers plugin descriptors with the plain 
context-classpath `ServiceLoader`, unlike `PinotRuleSet`, which also walks the 
`PluginManager` plugin classloaders.
   
   ## Fixes
   
   - Stream-mode stages are now rendered **directly from the decoded 
`StageStatsTreeNode`** — the explicit tree shape is exactly what the new wire 
format carries, so no shape re-derivation is needed and plugin types render 
faithfully. Cross-stage nesting (sender stage under its mailbox-receive node) 
is resolved through plan-node ids; the broker reproduces the same pre-order 
numbering the servers use. `PIPELINE_BREAKER` nodes are collapsed so the JSON 
shape stays bit-compatible with the legacy renderer (external tooling parses 
this format). Nodes additionally expose `planNodeIds`.
   - `OperatorTypeRegistry` now walks 
`PluginManager.get().getPluginClassLoaders()` (deduplicated by provider class 
name), matching the `PinotRuleSet` pattern.
   - New `OpChainExecutionContext#getPlanNodeIdMap()` accessor so plugin 
operator trees can register synthetic stats operators for id resolution via the 
existing `recordPlanNodesForOperator`.
   - Defensive fix on the legacy path: `visitMailboxSend` only reads 
`PARALLELISM` from genuine built-in `MAILBOX_SEND` stats and clamps the divisor 
to ≥ 1.
   
   ## Test plan
   
   - [x] New `MultiStageStatsTreeBuilderTest` — explicit-tree rendering with 
plugin-only operator types carrying a plugin-defined `StatMap.Key` enum 
(cross-stage nesting by plan-node id, `PIPELINE_BREAKER` collapse parity, 
legacy-path `/0` regression)
   - [x] `StreamStatsReportingIntegrationTest` — 7/7 (including the 
pipeline-breaker shape tests, which pin JSON parity of the new renderer)
   - [x] `MultiStageStatsTreeEncoderTest` / `MultiStageStatsTreeDecoderTest` / 
`StreamingQuerySessionTest` / `OpChainSchedulerServiceTest` / 
`OperatorTypeRegistryTest` — all green
   - [x] Verified end to end against the out-of-tree plugin extension: 
plugin-typed stages render in `stageStats` with correct cross-stage nesting and 
no errors
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to