GitHub user knyk-dev added a comment to the discussion: [DISCUSS][GSoC 2026] Proposal for GSOC-316: Enhance Seata-Go Multi-Registry & seata-ctl
<p align="center"><strong><sub>INCUBATOR APACHE SEATA - GOOGLE SUMMER OF CODE</sub></strong></p> --- <table> <tr> <td width="58%" valign="top"> <h1>Incubator Apache Seata<br />GSoC Contributor<br />Proposal</h1> <br /> <p> <img src="https://i.imgur.com/WWSRrf6.png" width="360" alt="Apache Seata logo" /> <img src="https://i.imgur.com/wyBocud.png" width="170" alt="Google Summer of Code logo" /> </p> </td> <td width="42%" valign="top"> <p><strong>Summary</strong></p> <p>This project implements production-ready registry adapters (Nacos, ZK, Consul, and Redis) for Seata-Go and upgrades seata-ctl with an interactive TUI for simplified troubleshooting.</p> <p> <strong>Owner:</strong> [email protected]<br /> <strong>Contributor:</strong> Zhifan Cui<br /> (<a href="https://github.com/knyk-dev">github: knyk-dev</a>)<br /> <strong>Mentor:</strong> Thun Guo<br /> ([email protected])<br /> <strong>Status:</strong> <strong>For Review</strong><br /> <strong>Created:</strong> 2026/03/25<br /> <strong>Proof of Concept Repository:</strong><br /> <a href="https://github.com/knyk-dev/gsoc26-seata-poc">https://github.com/knyk-dev/gsoc26-seata-poc</a> </p> </td> </tr> </table> # Project Abstract Apache Seata-Go serves as the Go implementation of the Seata distributed transaction framework. Currently, the infrastructure layer of Seata-Go lacks the variety of registry adapters that are available in the Java version, and the operational toolchain, seata-ctl, is still in its early stages. This project aims to bridge the gap by: - Implementing high-performance adapters for Nacos, ZooKeeper, Consul, and Redis; - Developing a staged, TUI-driven diagnostic pipeline for seata-ctl to simplify transaction troubleshooting; - Establishing a benchmarking suite to ensure infrastructure stability under high-concurrency scenarios. # Background & Problem Statement ## Current Status This section is based on prototype work and code exploration in incubator-seata-go and incubator-seata-ctl, reflecting the actual implementation gap beyond the initial project page description. Before this effort, Seata-Go still lagged behind Java Seata at the service-discovery layer. Existing paths covered only part of the deployment space, while common production setups rely on Nacos, ZooKeeper, Consul, or Redis. At the same time, seata-ctl still lacked a clear troubleshooting path from a failed transaction to the exact failing layer. ## The Identified Need Beyond simply expanding the adapter and command sets, ensuring correct behavior under real operational constraints remains the core challenge. - **Registry semantics are fundamentally different.** Nacos is callback-based, ZooKeeper depends on watch mechanics over ephemeral nodes, Consul uses long polling, and Redis requires a hybrid of pub/sub and periodic refresh. A single abstraction is easy to sketch, but correctness across all four backends is not; - **Java compatibility matters at the boundary.** Service-group mapping, path layout, key format, cluster naming, and address encoding must match Java Seata. Without this alignment, mixed Java/Go deployments are prone to silent lookup failures, effectively masking the underlying errors. - **Long-lived lifecycle management is easy to get wrong.** The discovery code has to survive malformed config, duplicate close, callback failure, stale cache, repeated watcher creation, reconnections, and shutdown ordering without drifting away from the actual registry state; - **Diagnostics cut across several failure domains.** A transaction issue may come from connectivity, authentication, API-version mismatch, missing tables, wrong schema, or lock-state inconsistencies. A useful seata-ctl workflow has to separate those causes and keep table, JSON, and YAML output stable enough for both humans and automation. ## Alignment First, Literal Porting Second Java Seata serves as the compatibility baseline, while the internal Go architecture will adapt to Go-native paradigms. The externally visible behavior should stay aligned with Java, but the internal realization should still respect Go's own runtime model. In practice, that means matching Java on semantics while allowing Go-specific choices for goroutine structure, cache refresh, shutdown handling, and error propagation. The primary metric for this project is interoperability, superseding strict adherence to Java's internal implementations. ## Performance Perspective The goal is simple: keep warm, look up cheap, and ensure first-ready latency is dominated by the registry backend, minimizing client-side bookkeeping overhead. I have already prepared a local benchmark harness for the Nacos and ZooKeeper discovery paths. On the current PoC prototype (Ubuntu 22.04/amd64, i7-13700H, 5 benchmark runs), the client-side normalization overhead is already quite small: | Target | Configuration | Time (ns/op) | Memory (B/op) | Allocations (allocs/op) | | --- | --- | ---: | ---: | ---: | | **Nacos server-address parsing** | single endpoint | 129.8 | 80 | 2 | | **Nacos server-address parsing** | three endpoints | 589.9 | 384 | 3 | | **ZooKeeper endpoint parse** | single endpoint | 236.3 | 72 | 5 | | **ZooKeeper endpoint parse** | three endpoints | 612.8 | 216 | 11 | Table 1. Client-side normalization overhead on the local PoC prototype (Environment: Ubuntu 22.04/amd64, Intel Core i7-13700H, 5 benchmark runs) These numbers confirm that parsing introduces negligible overhead. The primary engineering complexity lies in watching semantics: Nacos uses long-lived callbacks with full snapshots, while ZooKeeper relies on one-shot ExistsW/ChildrenW watches that must be re-registered. That is why Phase I should focus on first-ready latency, watcher re-registration, and correctness under refresh pressure. ## What to Reuse vs. Replace - **Reusable foundations:** the existing pkg/discovery abstraction in Seata-Go, the session/login flow in seata-ctl, and the current Seata console API surface where available; - **New work still required:** registry-specific watch and parsing logic, config normalization, Java-compatible naming behavior, negative-path tests, full-chain diagnostic checks, transaction and lock inspection, stable structured output, and a TUI refresh model consistent with the noninteractive path; - **Main conclusion:** GSOC-316 prioritizes interoperability and system resilience under failure conditions over simply maximizing the feature count. The project is valuable because it makes Seata-Go usable in heterogeneous production environments and makes seata-ctl useful when something is already going wrong. # Technical Design & Implementation ## Architecture Overview The implementation is split into two parts, but they share the same design goal: make Seata-Go easier to deploy in mixed production environments and make failures easier to diagnose once the system is running. On the SDK side, the main path is `seatago.yml -> InitRegistryWithError -> registry adapter -> local address cache -> TM/RM lookup`. On the tooling side, the main path is `CLI command -> session/auth -> diagnose or transaction query service -> Seata console API / DB probe -> table/json/yaml or TUI`. These features inherently interconnect, serving as two ends of the same operational lifecycle: service discovery decides whether the client can locate the right TC node, and seata-ctl decides how quickly an operator can explain a failure when that process breaks. The compatibility baseline is Java Seata. Registry naming, service-group mapping, cluster identity, address format, and console API behavior should remain aligned with Java so that mixed Java/Go deployments behave predictably. Internal implementation details do not need to be ported literally. Go has different strengths around goroutines, cache ownership, lifecycle management, and error propagation, so the internal design should stay idiomatic as long as the externally visible behavior remains compatible. <p align="center"> <img src="https://i.imgur.com/abdJk40.png" width="672" alt="Overall architecture of the GSOC-316 delivery" /> </p> <p align="center"><em>Figure 1. Overall architecture of the GSOC-316 delivery</em></p> ## Multi-Registry Support in Incubator-seata-go The registry side should expose one stable discovery boundary to the rest of the client. ServiceConfig is responsible for transaction-group mapping and cluster resolution. RegistryConfig holds backend-specific configuration such as namespace, group, root path, watch interval, key prefix, authentication, and connection options. InitRegistryWithError then normalizes those settings, validates the chosen registry type, and returns one RegistryService interface to the rest of Seata-Go. This shared boundary keeps the call site simple, but the backend implementations are intentionally different because the registries themselves work differently. - **Nacos** should subscribe to Java-compatible application/group/cluster coordinates and update the local cache through callback-driven refresh. - **ZooKeeper** should watch Seata's Java-compatible node layout and rebuild state from ephemeral node changes, including reconnect and watch re-registration cases. - **Consul** should use a long-poll model based on WaitIndex, plus health filtering and service-tag constraints, so the client does not treat unhealthy instances as available. - **Redis** should combine pub/sub with periodic scan repair. Pub/sub keeps refresh responsive; periodic scanning prevents the client from drifting permanently if a notification is missed. The implementation should not forward raw registry state directly to the lookup path. Every adapter should normalize backend-specific data into the same in-memory model before exposing it to the client. That allows the lookup path to stay cheap in steady state and keeps registry-specific edge cases isolated inside the adapter layer. Several failure cases need to be handled explicitly because they are common in long-running discovery code: - Invalid or incomplete registry config should fail early during initialization; - Malformed instance addresses will be proactively filtered to prevent cache pollution; - Duplicate refresh goroutines or duplicate watcher registration should be prevented; - Empty push events should not wipe out valid state by accident; - Repeated Close() calls should be safe and idempotent. This is also where alignment with Java needs a careful interpretation. Achieving semantic compatibility takes precedence over literal code parity. If Java Seata expects a certain service-group mapping rule or path layout, Seata-Go must match it. If Go can implement the same behavior with a cleaner ownership model for refresh loops and cache rebuilds, that is a better outcome than forcing a line-by-line port. <p align="center"> <img src="https://i.imgur.com/RUeM4gb.png" width="557" alt="Registry refresh model and shared local cache" /> </p> <p align="center"><em>Figure 2. Registry refresh model and shared local cache</em></p> ## Diagnose Pipeline in Incubator-seata-ctl To avoid the opacity of a single-probe approach, the diagnostic examination executes as a transparent, staged pipeline. A transaction problem can come from several independent layers: wrong CLI config, basic TCP failure, authentication failure, partial console API compatibility, unreachable metadata DB, or missing transaction tables. Those cases need to be separated because the operator action is different in each case. The command therefore runs a fixed sequence of checks: 1. Validate required configuration and flag combinations; 2. Verify TCP reachability to the target Seata server; 3. Perform login and require token acquisition as the success condition; 4. Probe /status, /globalSession/query, and /globalLock/query; 5. Test metadata DB connectivity for MySQL or PostgreSQL; 6. Validate the schema of global_table, branch_table, lock_table, and distributed_lock. Each stage should emit a structured result with PASS, WARN, FAIL, or SKIP, plus raw details that can be reused by table, JSON, and YAML output. This matters for compatibility handling. For example, an older console API may return 404 for globalLock while still supporting the other endpoints. Specific compatibility warnings must trigger these edge cases to prevent a generic failure state from masking the underlying issue. <p align="center"> <img src="https://i.imgur.com/aKMPKAS.png" width="215" alt="Staged diagnose pipeline in seata-ctl" /> </p> <p align="center"><em>Figure 3. Staged diagnose pipeline in seata-ctl</em></p> ## Transaction Inspection and Interactive Workflow The second half of seata-ctl focuses on shortening the path from symptoms to evidence. To eliminate the need for manually composing console API calls, the tool introduces three focused command paths: - Transaction query for filtered transaction listing, status filtering, pagination, and time-window inspection; - Transactions show for XID-level drill-down, including optional branch information; - A transaction lock for lock-row inspection is keyed by XID, with additional resource, branch, or table filters when needed. These commands should share one normalization layer between the HTTP client and the renderer. That shared model is important for two reasons. - It keeps field names and result structure stable across tables, JSON, and YAML. - The TUI reuses the core operational data model, preventing the architectural drift associated with maintaining a secondary representation, which becomes harder to test and easier to drift from the command-line path. The TUI itself should stay thin. It does not need a separate backend or special-purpose data source. It should reuse the same authenticated session, query layer, and normalized transaction or lock models as the non-interactive commands. Its additional responsibility is presentation logic: periodic refresh, manual refresh, cached-frame fallback on request failure, and small operator hints, such as suggesting the next transaction lock query from the current transaction view. <p align="center"> <img src="https://i.imgur.com/94xlVd3.png" width="442" alt="PoC rendering of the staged diagnostic pipeline using Bubbletea" /> </p> <p align="center"><em>Figure 4: The PoC rendering of the staged diagnostic pipeline using Bubbletea. (This interactive dashboard replaces the legacy flat CLI commands).</em></p> This design makes the implementation easier to understand. Command mode and TUI mode see the same backend state, exercise the same compatibility logic, and differ mainly in how the result is rendered and refreshed. <p align="center"> <img src="https://i.imgur.com/i6W694O.png" width="624" alt="Transaction inspection and TUI refresh flow" /> </p> <p align="center"><em>Figure 5. Transaction inspection and TUI refresh flow</em></p> ## Compatibility, Performance, and Validation ### Compatibility Interoperability and operational correctness serve as the primary evaluation metrics, outweighing sheer feature count. The most important compatibility checks are the following: - Transaction-group mapping and cluster resolution behave the same way as Java Seata; - Registry path, key layout, and address parsing stay compatible with the Java server side; - Seata-ctl handles different console API profiles predictably, especially partial support cases; - Structured outputs remain stable enough for automation and repeated operational use. ### Performance Performance should also be judged in the right places. The key target is not to outperform Java discovery in every microbenchmark. The more realistic target is: - Low overhead in config parse and registry initialization; - First-ready latency that is dominated by the backend registry rather than avoidable client-side work; - Cheap warm lookup once the local cache is built; - Predictable behavior under high-concurrency lookup and frequent refresh. ### Validation That leads naturally to the validation plan: - Unit tests for initialization, lookup, refresh logic, malformed input, callback error branches, and idempotent shutdown; - Integration tests covering the supported registries and both MySQL and PostgreSQL diagnosis paths; - Compatibility tests against older and newer Seata console API behaviors; - Benchmarks for cold start, first-ready, repeated lookup, and concurrent lookup under steady-state cache usage. Correctness under failure is part of the design target from the start. That is the standard needed for this project to genuinely deliver practical production value beyond theoretical completeness. # Code Affected The implementation of this proposal will systematically upgrade the infrastructure and diagnostic layers across two repositories. Specific modifications include: 1. **apache/incubator-seata-go (SDK Registry & Discovery Layer):** - pkg/discovery/\*.go: While initial stubs for multiple registries exist (e.g., consul.go, redis.go, zk.go), they lack unified watcher semantics, connection backoff strategies, and full data-race safety. This proposal will heavily refactor these files, standardizing them against the base. go and configure. go to ensure production-grade stability under high concurrency; - model/config.go: Extending the global configuration structures to natively parse and validate multi-registry parameters (e.g., Auth tokens, TLS certs). 2. **apache/incubator-seata-ctl (Diagnostic Tool Layer):** - action/diagnose/ (New): Introducing a completely new directory for the staged diagnostic pipeline and the Bubbletea-based Terminal UI (TUI), cleanly separated from existing flat operational commands (action/k8s/, action/try/, etc.); - seata/api.go & seata/txn.go: Enhancing the internal RPC client wrappers to securely fetch active XID locks and transaction states directly from the Seata TC Server for TUI rendering. # Related Work Java Seata establishes the operational baseline for distributed transaction coordination, supported by production-tested adapters for all mainstream registries. In contrast, while Seata-Go provides Etcd and Nacos support, its adapters for ZooKeeper, Consul, and Redis remain either incomplete or lack the unified registry watcher semantics required to handle edge cases like node flapping or hash-ring rebuilds. Modern cloud-native CLIs (e.g., istioctl, kubectl debug) have standardized interactive, multi-stage diagnostics as a core operational requirement. Currently, seata-ctl provides functional but isolated commands (e.g., basic try or k8s deployments) without an interactive diagnostic layer. The proposed TUI-driven staged pipeline (Config -> TCP -> Auth -> DB Probes) aligns seata-ctl's diagnostic capabilities with modern operational standards. | Feature / Capability | Current Seata-Go | Java Seata (Baseline) | Cloud-Native CLIs (`istioctl` / `dubboctl`) | Proposed Solution (GSOC-316) | | --- | --- | --- | --- | --- | | Nacos / ZK / Consul / Redis Support | Partial (Nacos/Etcd only) | ✅ Full Support | ✅ Full Support | ✅ Full Native Go Support | | Registry Watcher Abstraction | Fragmented | ✅ Unified | ✅ Unified | ✅ Unified (Fixing Data Races) | | Transaction State Insight (XID) | ❌ Missing | ✅ Supported via API | N/A | ✅ Supported via RPC Probes | | Staged Env Validation (DB/TCP) | ❌ Missing | Partial | ✅ Advanced | ✅ Fully Automated Pipeline | | Interactive Terminal UI (TUI) | ❌ Flat CLI | ❌ No TUI | Partial | ✅ Rich Interactive Dashboard | Table 2.Feature & Limitation Comparison # Pre-proposal Milestone: Functional PoC & Prior Contributions ## Local Proof-of-Concept & Benchmarking I have already developed a functional MVP featuring the Bubbletea TUI diagnostic pipeline and refactored ZK/Nacos adapters. Validated by baseline benchmarks, the core logic achieves an **82.2% unit test coverage**, proving its immediate production readiness. **Proof of Concept Repository**: <https://github.com/knyk-dev/gsoc26-seata-poc> ## Prior Contributions Through patching key concurrency and networking bugs, I have familiarized myself with Seata-Go's internal architecture: - \[Merged\] PR #1053 (CI resource saving) : Infrastructure optimization; (<https://github.com/apache/incubator-seata-go/pull/1053>) - \[Merged\] PR #1070 (RPC Serialization): Fixed RpcMessage.HeadMap data loss in decodeHeapMap where empty-string values caused keys to be silently dropped during byte-decoding; (<https://github.com/apache/incubator-seata-go/pull/1070>) - \[Merged\] PR #1081 (Concurrency): Fixed data races in consistent hash load-balancing by replacing unsafe RLock usage with atomic write-lock swaps, validated via -race tests; (<https://github.com/apache/incubator-seata-go/pull/1081>) - \[Merged\] PR #1083 (Transaction Lifecycle): Fixed AT mode connection pollution by enforcing Rollback() on execution errors, preventing unfinished local transactions from leaking into connection pools. (<https://github.com/apache/incubator-seata-go/pull/1083>) - \[Merged\] PR #1091 (TCC Resource Manager): Replaced panic-based TCC fallback paths with explicit LockQuery/UnregisterResource behavior, aligning with Seata Java semantics. (<https://github.com/apache/incubator-seata-go/pull/1091>) # Schedule of Deliverables ([timeline](https://developers.google.com/open-source/gsoc/timeline)) ## Week 1 -- Week 5 (Phase I: Registry Infrastructure Alignment) **Week 1-2:** Leveraging my local PoC to accelerate development, the initial phase focuses on migrating and hardening the ZK/Nacos adapters into the upstream apache/incubator-seata-go. Replace local data-race mitigations (developed during PoC phase) with standard Apache thread-safe watcher semantics. **Week 3-4:** Implementation of Consul and Redis adapters. Standardizing registry-specific config structures. **Week 5:** Integration with Seata NamingServer and bug fixing for Go-Java interoperability. ## Week 6 - Week 10 (Phase II: seata-ctl & Diagnostic Insight) **Week 6-7:** Core logic for the diagnose command (Environment self-check & DB structure validation). **Week 8-9:** Transaction state insight (XID queries & Resource lock inspection) via RPC. **Week 10:** TUI (Terminal UI) integration and user-friendly interaction polish. ## Week 11 - Week 12 (Hardening & Community Output) **Week 11:** Integration testing across MySQL/PostgreSQL and Stress testing for registry node changes. **Week 12:** Documentation, Technical Articles, and Final Evaluation. ## Deliverables (Quantifiable) - **Code:** 4 Registry Adapters + Enhanced seata-ctl binary. - **Testing:** >80% Unit Test coverage + 4 Integration test suites. - **Performance:** A benchmark report comparing Nacos/ZK/Consul overhead in Seata-Go. - **Docs:** Official "Troubleshooting Guide" and "Registry Configuration Guide". # About Me ## Zhifan Cui (github: [https://github.com/knyk-dev](https://github.com/knyk-dev)) I am a Master's student in Computer Science at the University of Wollongong, passionate about open-source middleware and distributed transaction architectures. ## Current focus - Go backend engineering. - Distributed systems, concurrency, networking, and database-backed service design. ## Relevant Production Background - Gained Java internship experience while working on a payment middleware platform. - Worked on making sure orders are unique across different channels, using Redis to prevent duplicate actions and control callback issues, retrying local messages for notifications that happen asynchronously, and automating the process of checking payments against third-party channels. - This is a business scenario that maps naturally to Seata-style distributed transaction coordination. ## Prior Experience with Open Source ## **Cross-language framework and infrastructure work** - Contributed to both Casbin (Go) and jCasbin (Java), with direct experience keeping equivalent framework features aligned across two language implementations. - Added shared RBAC cycle-detection support across the Go and Java codebases, and also worked on surrounding framework infrastructure such as generic RoleManager cleanup, logger and benchmark improvements, and DynamoDB adapter optimization. Selected commit history: Casbin: [https://github.com/apache/casbin/commits?author=knyk-dev](https://github.com/apache/casbin/commits?author=knyk-dev) jCasbin: [https://github.com/apache/casbin-jcasbin/commits?author=knyk-dev](https://github.com/apache/casbin-jcasbin/commits?author=knyk-dev) jCasbin DynamoDB adapter: [https://github.com/apache/casbin-jcasbin-dynamodb-adapter/commits?author=knyk-dev](https://github.com/apache/casbin-jcasbin-dynamodb-adapter/commits?author=knyk-dev) ## **Go ecosystem contributions** - Fixed issues in golang/net and golang/tools, including an http2 nil panic and an invalid modernize rewrite. (<https://go-review.googlesource.com/c/tools/+/746060> and <https://go-review.googlesource.com/c/net/+/746180>) - Also proposed an allocation reduction for net/netip text unmarshalling in the Go review system (<https://go-review.googlesource.com/c/go/+/747840>). ## Why Incubator Apache Seata? - Prior work with Redis, Kafka-based asynchronous pipelines, WebSocket streaming, backend consistency checks, and cross-language framework alignment. - GSOC-316 is a strong match for both my experience and my interests. GitHub link: https://github.com/apache/incubator-seata-go/discussions/1109#discussioncomment-16711037 ---- This is an automatically sent email for [email protected]. To unsubscribe, please send an email to: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
