Aias00 opened a new issue, #7993: URL: https://github.com/apache/shenyu/issues/7993
## Feature Request Introduce optional DAG-based **plugin orchestration** while preserving the existing `ShenyuPlugin.execute(exchange, chain)` contract. This proposal concerns the gateway processing pipeline (authentication, transformations, resilience, proxying and response handling). HTTP/RPC API aggregation, backend method composition and business workflows are out of scope. ## Problem The gateway currently executes a globally ordered plugin list. `ShenyuWebHandler` sorts plugins using synchronized `PluginData.sort` or `getOrder()`, and a request-local chain cursor advances through that list. Plugins can skip, short-circuit, decorate the exchange, or wrap downstream execution. Different request classes may need different plugin paths, while numeric ordering does not express mandatory dependencies or wrapper scopes. ## Proposed scope Phase 1 supports explicit dependency constraints, conditional exclusive branches and convergence of mutually exclusive paths. Each request traverses one serial path. Existing plugins retain their own selector/rule matching and configuration; graph conditions choose processing paths rather than replace those selectors/rules. Do not introduce parallel execution, fan-out/fan-in, duplicate same-plugin invocations on one path, arbitrary executable scripts, or a universal workflow engine in this phase. Existing linear-chain mode remains the default and migration path. ## Architecture `Admin graph definition -> existing sync transport extensions -> gateway validation/compiler -> immutable execution plan -> request-local graph execution -> existing plugins`. Suggested boundaries: graph DTOs in `shenyu-common`; a focused graph runtime module depending on plugin API/base; integration in `shenyu-web`; graph lifecycle in admin; a dedicated graph subscriber and configuration group in the data-sync layer. Final module and protocol names are subject to review. ### Model and compiler Use versioned graph definitions containing `schemaVersion`, namespace/deployment binding, graph identity, revision, content hash, entry node and nodes. Initial node types are PLUGIN, CHOICE and END. Plugin nodes bind installed plugins by name and have one successor; CHOICE uses structured conditions, deterministic first-match priority and a required default target. Validate cycles, dangling references, reachability, missing/incompatible plugins, resource limits, duplicate same-plugin execution on a reachable path, and explicit plugin requirements. Dependency-only configurations can produce an ordinary sorted chain. Numeric sort can seed migration drafts; it must not silently override explicit graph edges. Dependency order alone does not capture middleware wrapper scopes. Define and validate the scope of tracing, resilience and response-related plugins. Do not assume all plugins can safely move across branches merely because the graph is acyclic. Decide whether to enforce a structured common prefix/suffix for initial supported graphs during the compatibility audit. ### Preserve middleware semantics The continuation passed to a plugin executes its selected successor, rather than advancing a shared global cursor. Preserve skip, selector/rule misses, short-circuiting, decorated exchanges, downstream `then`/`transform`/error handling, cancellation and resource cleanup. Do not flatten plugin calls into `A.then(B)`. Preserve the existing construction-time semantics of plugin `before/after`; introduce separate asynchronous node/graph telemetry. Audit downstream invocation and resubscription behavior before defining repeat-call restrictions: do not silently add `cache()` or break existing retrying plugins. Preserve `ShenyuPluginChain.fork()` for internal dispatch: independent execution state, same structural plan snapshot, entry restart and conditions evaluated against the child exchange. Internal-dispatch recursion needs explicit limits. For exclusive branches `choice -> A/B -> C`, only one branch runs and C is entered once. No parallel join scheduler is required. ### Configuration and lifecycle Use immutable published revisions, monotonic activation ordering and atomic replacement of successfully compiled plans. Each request holds one topology snapshot. A topology snapshot does **not** automatically freeze selector/rule/plugin caches; document this limitation and define invalidation behavior. Handle plugin enable/disable, removal, replacement and extension loading. Mandatory security dependencies must fail closed for new requests when unavailable; preserving an old topology must not bypass an explicit disable. Defer unloading plugin resources until active references are released. Extend full/incremental sync, reconnect recovery, deletion, admin cluster forwarding and digest refresh. Initially support WebSocket and HTTP with explicit capability/version negotiation. Reject graph enablement for unsupported transports or gateway versions rather than silently ignoring it. Distinguish admin publication from instance activation. Expose received/pending/active/rejected state and useful compile failures. Rollback publishes old content under a new revision. Invalid candidates retain the last valid plan, except where dependency invalidation makes that plan unsafe. Cold start without the required plan must not silently execute an unrelated default chain. Never restart a failed in-flight graph through the legacy chain: that can duplicate upstream calls and side effects. ### Administration and rollout Store drafts and immutable revisions; use optimistic draft updates and transactional publication with durable delivery/reconciliation. Start with a structured/JSON editor, validation, read-only topology and instance status. Visual drag-and-drop editing is optional follow-up work. Provide linear-chain import, disabled-by-default activation, explicit namespace/deployment binding and a pre-execution operational switch back to legacy mode. Do not bypass mandatory authentication through graph configuration; make graph editing a privileged operation. ## Acceptance criteria - Equivalent linear graphs preserve existing plugin behavior and response ownership. - Exclusive branching and convergence are deterministic and do not duplicate calls. - Compatibility tests cover Sentinel-style wrappers, response writers/decorators, short circuits, rule misses, internal dispatch, subscription/cancellation and long-lived responses. - Invalid publications and unavailable mandatory dependencies cannot activate unsafe execution. - Version changes, reorder/replay, reconnect and rollback are tested end to end. - Compare throughput, P99 and allocation against the equivalent legacy chain; agree regression thresholds from a reproducible baseline rather than claim unmeasured gains. - Document supported plugins, constraints, transport/version support and operational recovery. ## Alternatives Keep numeric sorting only: smallest change, but cannot express request-dependent paths. Replace all plugin interfaces with task nodes: breaks established middleware semantics. Compose backend APIs: a separate feature with different identity, security and resource concerns; excluded here. ## Implementation tracking Child tasks and dependency order will be linked below. This is a proposal for community review, not an assertion that the design has been accepted. -- 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]
