Skip to content

Client.Ready() blocks forever when called after client is already ready #203

@kitimark

Description

@kitimark

Describe the bug

Summary

  • Client.Ready() blocks forever when called after client is already ready
  • Affected: v5.0.3 and earlier
  • Scope: Client.Ready() only; WaitForReady() and listener callbacks work as expected
  • Symptom: Calling Client.Ready() after the client has already become ready returns a channel that never receives, causing goroutines to hang indefinitely
  • Expected: Client.Ready() should resolve immediately (or otherwise deliver a value) even if readiness happened earlier

Steps to reproduce the bug

Minimal program that shows the hang when calling Ready() after the client is already ready.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"

	unleash "github.com/Unleash/unleash-go-sdk/v5"
)

func main() {
	// Mock Unleash server that immediately returns an empty features response.
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/client/features" {
			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(http.StatusOK)
			_, _ = w.Write([]byte(`{}`))
			return
		}
		http.NotFound(w, r)
	}))
	defer srv.Close()

	client, err := unleash.NewClient(
		unleash.WithUrl(srv.URL),
		unleash.WithAppName("app"),
		unleash.WithInstanceId("test"),
		unleash.WithDisableMetrics(true),
	)
	if err != nil {
		panic(err)
	}
	defer client.Close()

	// Ensure the client is ready.
	client.WaitForReady()
	fmt.Println("client is ready")

	// Reproduce: call Ready() AFTER readiness occurred.
	select {
	case <-client.Ready():
		fmt.Println("this should print, but on v5.0.3 and earlier it can hang")
	case <-time.After(100 * time.Millisecond):
		panic("timeout waiting for unleash client to be ready after 100ms")
	}
}

Expected behavior

From reproduce code, the program will panic this message panic: timeout waiting for unleash client to be ready after 100ms

  	// Reproduce: call Ready() AFTER readiness occurred.
  	select {
  	case <-client.Ready():
  		fmt.Println("This should print, but on v5.0.3 it can hang")
  	case <-time.After(100 * time.Millisecond):
  		panic("timeout waiting for unleash client to be ready after 100ms")
  	}

Logs, error output, etc.

Screenshots

No response

Additional context

I will propose the the pull request for workaround fix this issue.

Unleash version

v7.2.0

Subscription type

Open source

Hosting type

Self-hosted

SDK information (language and version)

unleash-client-go v5.0.3 and eariler

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Investigating

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions