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" />
  &nbsp;&nbsp;&nbsp;
  <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]

Reply via email to