package waymaker import ( "context" "fmt" waymaker_cache "git.awesomike.com/pub/waymaker-client/go/genpb/cache" waymaker_collections "git.awesomike.com/pub/waymaker-client/go/genpb/collections" waymaker_kv "git.awesomike.com/pub/waymaker-client/go/genpb/kv" pb "git.awesomike.com/pub/waymaker-client/go/genpb/locks" waymaker_sketches "git.awesomike.com/pub/waymaker-client/go/genpb/sketches" waymaker_streams "git.awesomike.com/pub/waymaker-client/go/genpb/streams" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) // Client is a connected waymaker client. It holds a *grpc.ClientConn and // exposes per-subsystem entry points. Client is safe to use from multiple // goroutines. // // Client is cheap to copy — the underlying gRPC channel is reference-counted. type Client struct { conn *grpc.ClientConn } // Connect dials a single waymaker server and returns a Client. The target // must be a valid gRPC target (e.g. "localhost:8818"). // // Connection is lazy: Connect returns immediately after resolving the address. // Use grpc.WithBlock() in opts if you need to confirm reachability at dial // time. func Connect(ctx context.Context, target string, opts ...grpc.DialOption) (*Client, error) { defaults := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), } opts = append(defaults, opts...) conn, err := grpc.NewClient(target, opts...) if err != nil { return nil, fmt.Errorf("waymaker: dial %q: %w", target, err) } return &Client{conn: conn}, nil } // ConnectMulti dials multiple waymaker servers with round-robin load // balancing. Requests are distributed across endpoints and automatically // rerouted when one is unreachable — the right shape for a clustered // deployment. Requires at least one target. // // Note: the current implementation dials the first endpoint only. A full // static-resolver-based multi-endpoint implementation can be added without // breaking the public surface. func ConnectMulti(ctx context.Context, targets []string, opts ...grpc.DialOption) (*Client, error) { if len(targets) == 0 { return nil, invalidErr("ConnectMulti requires at least one target") } return Connect(ctx, targets[0], opts...) } // Close closes the underlying gRPC connection. Subsequent calls on the // Client will fail. func (c *Client) Close() error { return c.conn.Close() } // --- per-subsystem gRPC client constructors (unexported) --- func (c *Client) locksClient() pb.WaymakerServiceClient { return pb.NewWaymakerServiceClient(c.conn) } func (c *Client) streamsClient() waymaker_streams.WaymakerStreamsServiceClient { return waymaker_streams.NewWaymakerStreamsServiceClient(c.conn) } func (c *Client) kvClient() waymaker_kv.WaymakerKvServiceClient { return waymaker_kv.NewWaymakerKvServiceClient(c.conn) } func (c *Client) collectionsClient() waymaker_collections.WaymakerCollectionsServiceClient { return waymaker_collections.NewWaymakerCollectionsServiceClient(c.conn) } func (c *Client) sketchesClient() waymaker_sketches.WaymakerSketchesServiceClient { return waymaker_sketches.NewWaymakerSketchesServiceClient(c.conn) } func (c *Client) cacheClient() waymaker_cache.WaymakerCacheServiceClient { return waymaker_cache.NewWaymakerCacheServiceClient(c.conn) }