I have a Go application, where I create a Pub/Sub client and then I create a subscriber receiving from a topic/subscription I've created locally using a local Docker gcloud emulator container. Everything works fine when the emulator is running - I can publish and subscribe just fine. However, when I kill the container and then start the subscriber app again, I see no errors, and the subscriber's Receive function hangs indefinitely, presumably doing retries over and over again.
I can ensure the client can actually connect to the Pub/Sub server by calling SubscriptionAdminClient.GetSubscription() function and adding a timeout to the context, but I'm not convinced this is necessary or the correct way.
Here is the code from the last iteration:
package my_pubsub
import (
"context"
"fmt"
"cloud.google.com/go/pubsub/v2" // v2.0.0
"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)
type Client struct {
client *pubsub.Client
}
func NewClient(ctx context.Context) (*Client, error) {
cl, err := pubsub.NewClient(ctx, "my-project")
if err != nil {
return nil, err
}
_, err = cl.SubscriptionAdminClient.GetSubscription(ctx, &pubsubpb.GetSubscriptionRequest{
Subscription: "my-subscription",
})
if err != nil {
return nil, fmt.Errorf("failed to get subscription: %w", err)
}
return &Client{
client: cl,
}, nil
}
And in my main function:
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()
// this will time out if the emulator isn't running
client, err := my_pubsub.NewClient(ctx)
if err != nil {
panic(fmt.Errorf("failed to create pubsub client: %w", err))
}
defer client.Close()
sub := client.Subscriber("my-subscription")
ctx2, cancel2 := context.WithCancel(context.Background())
go func() {
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
<-sigchan
cancel2()
client.Close()
}()
err := sub.Receive(ctx2, func(ctx context.Context, msg *pubsub.Message){
// do stuff
})
if err != nil {
panic(err(
}
In this example, the GetSubscription() times out after 10 seconds and I get:
panic: failed to create pubsub client: failed to get subscription: context deadline exceeded
Is there a better way to achieve this?
SubscriptionAdminClient.GetSubscriptionis appropriate. You could alsoTopicAdminClient.ListTopics(...).Next()which is similarly lightweight.NewClientis lazy and so there's no request against the service without methods like these. Unfortunately, Google's underlying gRPC services don't implement public health-checking and so there's no generic mechanism either.