feat(event): run native queue and event plugin simultaneously#6852
feat(event): run native queue and event plugin simultaneously#6852h45hc47 wants to merge 1 commit into
Conversation
| this.triggerConfigList = config.getTriggerConfigList(); | ||
|
|
||
| useNativeQueue = config.isUseNativeQueue(); | ||
| useEventPlugin = StringUtils.hasText(config.getPluginPath()); |
There was a problem hiding this comment.
[SHOULD] @h45hc47, switching the "plugin enabled" condition from !useNativeQueue to "path is non-empty" introduces an upgrade regression: a node currently running with useNativeQueue = true that happens to still have a non-empty path in its config (the old docs said path is ignored when useNativeQueue = true, so such leftover config does exist) boots fine today as native-only; after the upgrade it will try to load that plugin because useEventPlugin = true, and if the plugin zip is missing/invalid, launchEventPlugin returns false -> start() returns false -> Manager.startEventSubscribing() throws TronError(EVENT_SUBSCRIBE_INIT), so the node fails to start outright.
Overall I'd recommend keeping the current behavior (native queue and plugin mutually exclusive); the existing design is fine as-is:
- The "deliver to both" need can be solved cleanly outside the node: enable the native ZMQ queue and run a lightweight consumer that subscribes to ZMQ and persists to MongoDB. The node keeps a single sink and minimal responsibility, instead of coupling dual delivery into the core.
- Mutual exclusivity is a safety property here, not a defect: it keeps plugin/MongoDB failures out of the node, so a failed plugin load or a MongoDB outage cannot affect the block-producing node. This PR removes that isolation (the startup failure above is the direct consequence) and also couples the plugin queue's back-pressure into the block-loading path (
HistoryEventService/BlockEventLoadstart throttling on the plugin queue even when the native queue is on), adding failure surface and coupling to a subsystem that is sensitive to block processing. - The trade-off doesn't pay off: the benefit is a niche scenario that already has a clean external alternative, while the cost is added coupling in a core subsystem, a new failure path that can prevent the node from starting, and the per-trigger overhead of an extra serialization plus dual dispatch on a hot path.
So I'd suggest not merging this for now and keeping the current mutually-exclusive semantics. If there's a strong need later, it should be redone as an explicit opt-in flag that guarantees zero behavior change for existing configs.
What does this PR do?
Makes the native ZMQ message queue and the event plugin (e.g. the MongoDB plugin) two independent event sinks, so a node can publish triggers to both at the same time.
Previously they were mutually exclusive: when
useNativeQueue = true, the plugin'spath/server/dbconfigwere never loaded and only the native queue started; the plugin only ran whenuseNativeQueue = false.Key changes:
Args: always copypath/server/dbconfigintoEventPluginConfig, regardless ofuseNativeQueue.EventPluginLoader: add a separateuseEventPluginflag (derived from a non-empty plugin path).start()launches the plugin first — so the plugin's listeners exist before any topic is registered — and then the native queue. Eachpost*Triggeris dispatched to every active sink;setPluginTopicis null-guarded for the now-possible double trigger-config pass;isBusy()is gated on the plugin being active instead of on the native queue being off.HistoryEventService: honor the plugin's back-pressure (isBusy) during historical sync even when the native queue is enabled, so the plugin queue is not flooded. Native-only pacing is unchanged.config.conf/reference.conf: document thatuseNativeQueueand a pluginpathcan be combined.Why are these changes required?
Operators often want both transports at once: low-latency ZMQ delivery for real-time consumers AND durable persistence in MongoDB for querying and indexing. Today they must pick one. With a single
event.subscribeblock (native queue on + a plugin path set), both now receive every trigger.Example configuration enabling both:
This PR has been tested by:
:commonand:frameworkcompileJavasucceed.EventPluginLoaderTest#testIsBusy— updated for the newuseEventPluginsemantics — PASSED.HistoryEventServiceTest#test— covers the reordered back-pressure path — PASSED.useNativeQueue = trueand a MongoDB plugin path set starts cleanly, writes events to the MongoDB collections, and binds the native ZMQ queue on port 5555 simultaneously.Follow up
A future enhancement could add an explicit
useEventPluginconfig key instead of inferring plugin activation from a non-emptypath.Extra details
In combined mode the trigger-config pass runs once per launcher; this is idempotent (boolean flags and
setTopicoverwrite with the same values). Every trigger is now serialized and dispatched to both sinks, a modest overhead versus single-sink mode. Behavior is unchanged for the two existing single-sink configurations (native-only, or plugin-only).