close
Skip to content

refactor(sdk): refactor Go SDK client#1916

Merged
spetz merged 42 commits into
apache:masterfrom
chengxilo:golang-sdk-refactor-new-client
Jul 4, 2025
Merged

refactor(sdk): refactor Go SDK client#1916
spetz merged 42 commits into
apache:masterfrom
chengxilo:golang-sdk-refactor-new-client

Conversation

@chengxilo
Copy link
Copy Markdown
Contributor

@chengxilo chengxilo commented Jun 26, 2025


Edited in July 2, 2025 (GMT-4), to reflect the latest change.

Description

What I did

  1. Refactored the Go SDK client creation logic using the option pattern.

  2. Updated the client interface and TCP client methods to align closely with the Rust SDK:

    • Replaced struct-based parameters with explicit argument lists.
    • Used pointers to represent optional arguments.
    • Edited some return type to align with rust sdk.
  3. Changed all related tests to reflect the updated interface and logic.

Future work

The goal of this PR is to align the API surface and usage pattern with the Rust SDK — not to fully implement every internal behavior. Since there are some logic not implemented yet, I add some TODO in those part.


Some explanation (Outdated, kept for history)

What I did

  1. refactor logic for building new Go SDK client using builder pattern
  2. I changed some function to make them align with Rust SDK ( not only their name, I also edited part of their output)
  3. I updated the tests.

Why we need to refactor it.

( I copied the message I sent in discord a few days ago here)
Since currently, the golang sdk is very out dated and when we create a client the
in rust when we create client:

let client = IggyClientBuilder::new()
        .with_tcp()
        .with_server_address(get_tcp_server_addr())
        .build()?;

While in golang we create client:

factory := iggy.IggyClientFactory{}
msgStream, _ := factory.CreateMessageStream(iggcon.IggyConfiguration{
    BaseAddress: "vm:8090",
    Protocol:    "tcp",
})

Since the Rust SDK is considered the primary or canonical implementation, it makes sense for other language SDKs to follow its design principles closely — including using the same repository name and similar function names. Clearly, the current Go SDK does not meet this requirement: its function names don’t clearly describe their purpose, and the overall design pattern feels less elegant.

My solution

So what I did is to read the rust sdk source code and ... almost directly ported its logic to Go. I want to explain why I decided not to use the option pattern discussed earlier with @haze518, even though the option pattern is commonly considered best practice in Go. At first, I choose to follow the example of https://github.com/nats-io/nats.go/blob/main/nats.go#L867 . It's elegent, but it would not work so well in our use case, since we need to support tcp/http/quic three different protocol and they have different options.
Here is a simplified example showing the potential issue:

package main

type Options struct {
	protocol string
	aTcpOpt bool // a TCP-specific option
	aHttpOpt bool // a HTTP-specific option
}
type Option func(*Options)

func WithTcp(opts *Options) {
	opts.protocol = "tcp"
}
func WithHttp(opts *Options) {
	opts.protocol = "http"
}
func WithATcpOpt(opts *Options) {
	opts.aTcpOpt = true
}
func WithAHttpOpt(opts *Options) {
	opts.aHttpOpt = true
}
func New(opts ...Option) {
	options := &Options{
		protocol: "tcp",
		aTcpOpt:  false,
		aHttpOpt: false,
	}
	for _, opt := range opts {
		opt(options)
	}
	// ... build the client with option
}

func main() {
	New(WithTcp, WithAHttpOpt, WithATcpOpt) // user may add a http option when they are using tcp
}

So, I think it is not a good choice as I don't know how to solve this problem while using option pattern. But if we use builder pattern, it allows us to control and constrain users’ choices more effectively, preventing invalid combinations and leading to a cleaner, safer API.
so currently, after this pr, the usage of it would be:

func main() {
    cli, err := iggycli.NewIggyClientBuilder().WithTcp().WithServerAddress("127.0.0.1:8090").Build()
    if err != nil {
        panic(err)
    }
    // use cli
}

Comment thread foreign/go/samples/consumer/consumer.go Outdated
Comment thread foreign/go/iggycli/iggy_client.go Outdated
Comment thread foreign/go/iggycli/client_builder.go Outdated
@chengxilo chengxilo changed the title refactor(sdk): refactor logic for building new Go SDK client using builder pattern and edited some function to align with Rust SDK refactor(sdk): refactor logic for building new Go SDK client and edited some function to align with Rust SDK Jun 29, 2025
@chengxilo chengxilo force-pushed the golang-sdk-refactor-new-client branch from 279db43 to fe32d0b Compare June 29, 2025 21:41
@chengxilo chengxilo marked this pull request as draft June 29, 2025 22:41
…) logic

- Refactored `GetConsumerGroup` and `GetConsumerGroups` functions in `Client`
- Renamed `iggcon.ConsumerKind`, since `ConsumerGroup` should be used as the element type in the `GetConsumerGroups` response
- Update the test files.
- Add TODO in DeserializeToConsumerGroupDetails. The implementation should be done in the future.
@chengxilo chengxilo changed the title refactor(sdk): refactor logic for building new Go SDK client and edited some function to align with Rust SDK [WIP] refactor(sdk): refactor Go SDK client interface and tcp implementation Jul 1, 2025
@chengxilo chengxilo changed the title [WIP] refactor(sdk): refactor Go SDK client interface and tcp implementation [WIP] refactor(sdk): refactor Go SDK client Jul 1, 2025
@chengxilo chengxilo changed the title [WIP] refactor(sdk): refactor Go SDK client refactor Go SDK client Jul 2, 2025
@chengxilo chengxilo changed the title refactor Go SDK client refactor(sdk): refactor Go SDK client Jul 2, 2025
@chengxilo
Copy link
Copy Markdown
Contributor Author

chengxilo commented Jul 3, 2025

All function signatures and return types have been updated. Required arguments are passed directly, while optional arguments are represented as pointer values. I try to limit the scope of changes in this PR to function signatures and their usage logic, as this pr is already too huge. However, I had to modify some functions—mainly in the serialization layer—to align with the updated argument and return value structure. For more detail. Please check the comments I provided in review.

Comment thread foreign/go/binary_serialization/binary_request_serializer.go
Comment thread foreign/go/binary_serialization/binary_response_deserializer.go
Comment thread foreign/go/binary_serialization/binary_response_deserializer.go
Comment thread foreign/go/binary_serialization/log_in_request_serializer.go
Comment thread foreign/go/contracts/consumer.go
Comment thread foreign/go/tcp/tcp_user_managament.go
@chengxilo chengxilo marked this pull request as ready for review July 3, 2025 03:59
@chengxilo chengxilo requested a review from haze518 July 3, 2025 03:59
@spetz spetz merged commit 82e35db into apache:master Jul 4, 2025
19 checks passed
hageshiame pushed a commit to hageshiame/iggy that referenced this pull request Nov 7, 2025
- Refactored the Go SDK client creation logic using the option pattern.

- Updated the client interface and TCP client methods to align closely with the Rust SDK:
   - Replaced struct-based parameters with explicit argument lists.
   - Used pointers to represent optional arguments.
   - Edited some return type to align with rust SDK.

- Changed all related tests to reflect the updated interface and logic.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants