pubsub

package
v1.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 13 Imported by: 0

README

Google Cloud Pub/Sub Factory (v2)

Overview

Builds a cloud.google.com/go/pubsub/v2 client from Boost config: API options, gRPC options and OpenTelemetry. v2 is the default Pub/Sub version of Boost; the v1 factory (../v1) stays for apps that pin version: v1.

Features

  • Client from config: NewClient reads boost.factory.gcp.pubsub.*
  • Custom config path or options: NewClientWithConfigPath, NewClientWithOptions
  • gRPC plugins: any clientgrpc.Plugin adds dial and call options
  • OpenTelemetry: gRPC traces and metrics plus Pub/Sub tracing, on by default
  • Logging: the client creation is logged through wrapper/log

Choosing the version

The fx modules pick the factory by boost.factory.gcp.pubsub.version: v2 (default) or v1. Any other value fails the boot. The publisher driver and the function adapter have their own version keys, also v2 by default:

Key Selects
boost.factory.gcp.pubsub.version the *pubsub.Client of fx/modules/factory/.../pubsub
boost.wrapper.publisher.driver.pubsub.version the publisher.Driver of fx/modules/wrapper/publisher/...
boost.bootstrap.function.adapter.pubsub.version the @Function adapter of fx/modules/bootstrap/function/...

To stay on v1, set the three keys to v1.

Usage

Basic Usage
package main

import (
    "context"

    gpubsub "cloud.google.com/go/pubsub/v2"
    "github.com/xgodev/boost"
    "github.com/xgodev/boost/factory/contrib/cloud.google.com/pubsub/v2"
    "github.com/xgodev/boost/wrapper/log"
)

func main() {
    boost.Start()

    ctx := context.Background()

    client, err := pubsub.NewClient(ctx)
    if err != nil {
        log.Fatalf("failed to create Pub/Sub client: %v", err)
    }
    defer client.Close()

    publisher := client.Publisher("my-topic")
    defer publisher.Stop()

    id, err := publisher.Publish(ctx, &gpubsub.Message{
        Data: []byte("Hello, Pub/Sub!"),
    }).Get(ctx)
    if err != nil {
        log.Fatalf("failed to publish message: %v", err)
    }

    log.Infof("published message with ID: %s", id)
}
Custom Configuration Path
client, err := pubsub.NewClientWithConfigPath(ctx, "myapp.pubsub")

The path must have the same keys as the default root; pubsub.ConfigAdd(path) registers them with their defaults.

Custom Options
options, err := pubsub.NewOptions()
if err != nil {
    log.Fatalf("failed to load options: %v", err)
}

options.APIOptions.ProjectID = "my-gcp-project"
options.Otel.Enabled = false

client, err := pubsub.NewClientWithOptions(ctx, options)
Using Plugins
import (
    clientgrpc "github.com/xgodev/boost/factory/contrib/google.golang.org/grpc/v1/client"
    "github.com/xgodev/boost/factory/contrib/google.golang.org/grpc/v1/client/plugins/native/compressor"
)

client, err := pubsub.NewClient(ctx, compressor.Register)

A plugin is a clientgrpc.Plugin: func(ctx context.Context) ([]grpc.DialOption, []grpc.CallOption).

Configuration Parameters

All keys live under boost.factory.gcp.pubsub.

Key Description Default
version Pub/Sub version the fx modules use: v1 or v2 v2
otel.enabled gRPC OpenTelemetry traces/metrics and Pub/Sub tracing true
apiOptions.* project, credentials, endpoint, scopes (api/v0) application default credentials
grpcOptions.* message sizes, keepalive, windows (grpc/v1) gRPC defaults

Example: Publishing and Subscribing

v2 splits data and admin calls: Publisher/Subscriber send and receive, TopicAdminClient/SubscriptionAdminClient create and delete resources.

package main

import (
    "context"
    "errors"
    "fmt"
    "time"

    gpubsub "cloud.google.com/go/pubsub/v2"
    "cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
    "github.com/xgodev/boost"
    "github.com/xgodev/boost/factory/contrib/cloud.google.com/pubsub/v2"
    "github.com/xgodev/boost/wrapper/log"
)

func main() {
    boost.Start()

    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    client, err := pubsub.NewClient(ctx)
    if err != nil {
        log.Fatalf("failed to create client: %v", err)
    }
    defer client.Close()

    topic := fmt.Sprintf("projects/%s/topics/my-topic", client.Project())
    if _, err := client.TopicAdminClient.CreateTopic(ctx, &pubsubpb.Topic{Name: topic}); err != nil {
        log.Fatalf("failed to create topic: %v", err)
    }

    sub := fmt.Sprintf("projects/%s/subscriptions/my-subscription", client.Project())
    if _, err := client.SubscriptionAdminClient.CreateSubscription(ctx, &pubsubpb.Subscription{
        Name:               sub,
        Topic:              topic,
        AckDeadlineSeconds: 20,
    }); err != nil {
        log.Fatalf("failed to create subscription: %v", err)
    }

    publisher := client.Publisher(topic)
    defer publisher.Stop()

    id, err := publisher.Publish(ctx, &gpubsub.Message{
        Data:       []byte("Hello, Pub/Sub!"),
        Attributes: map[string]string{"origin": "boost-example"},
    }).Get(ctx)
    if err != nil {
        log.Fatalf("failed to publish message: %v", err)
    }
    log.Infof("published message with ID: %s", id)

    rctx, stop := context.WithCancel(ctx)
    err = client.Subscriber(sub).Receive(rctx, func(_ context.Context, msg *gpubsub.Message) {
        log.Infof("received message: %s %v", msg.Data, msg.Attributes)
        msg.Ack()
        stop()
    })
    if err != nil && !errors.Is(err, context.Canceled) {
        log.Fatalf("failed to receive messages: %v", err)
    }
}

Best Practices

  1. Project ID: set apiOptions.projectID in production
  2. Authentication: service account with the minimum Pub/Sub roles
  3. Stop publishers: Publisher.Stop() flushes pending messages
  4. Ack deadline: match it to the processing time of a message
  5. Admin calls: create topics and subscriptions in provisioning, not on every boot

References

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConfigAdd

func ConfigAdd(path string)

ConfigAdd registers shared API and gRPC configs under the given path.

func NewClient

func NewClient(ctx context.Context, plugins ...clientgrpc.Plugin) (*pubsub.Client, error)

NewClient creates a Pub/Sub client using default configuration.

func NewClientWithConfigPath

func NewClientWithConfigPath(ctx context.Context, path string, plugins ...clientgrpc.Plugin) (*pubsub.Client, error)

NewClientWithConfigPath creates a Pub/Sub client from a specific config path.

func NewClientWithOptions

func NewClientWithOptions(ctx context.Context, o *Options, plugins ...clientgrpc.Plugin) (*pubsub.Client, error)

NewClientWithOptions constructs a Pub/Sub client from Options.

Types

type Options

type Options struct {
	APIOptions  apiv1.Options  `config:"apiOptions"`
	GRPCOptions grpcv1.Options `config:"grpcOptions"`
	Otel        OtelOptions    `config:"otel"`
}

Options holds shared API/gRPC options for Pub/Sub.

func NewOptions

func NewOptions() (*Options, error)

NewOptions loads Options from the default root.

func NewOptionsWithPath

func NewOptionsWithPath(path string) (*Options, error)

NewOptionsWithPath loads Options from the specified path.

type OtelOptions

type OtelOptions struct {
	Enabled bool
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL