Files
enkly-ai/services/agent/internal/infrastructure/grpcclients/clients.go
enkly 79ce8dc4c0
Some checks failed
Go CI Pipeline / build_and_test (push) Failing after 22m0s
Init Project
2026-10-30 18:06:55 +01:00

83 lines
2.7 KiB
Go

// Package grpcclients dials every other bounded context the agent
// service's saga needs and exposes each as its generated client
// interface. One file, one place to see the agent service's entire
// synchronous fan-out — see ARCHITECTURE.md's context map diagram.
package grpcclients
import (
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
billingv1 "enkly/gen/billing/v1"
conversationv1 "enkly/gen/conversation/v1"
knowledgev1 "enkly/gen/knowledge/v1"
workspacev1 "enkly/gen/workspace/v1"
)
// Clients bundles every gRPC client connection the agent service holds
// open for the lifetime of the process (one connection each, reused
// across requests — grpc.ClientConn is safe for concurrent use and
// multiplexes calls over HTTP/2 itself, so there's no pool to manage).
type Clients struct {
Workspace workspacev1.WorkspaceServiceClient
Knowledge knowledgev1.KnowledgeServiceClient
Billing billingv1.BillingServiceClient
Conversation conversationv1.ConversationServiceClient
conns []*grpc.ClientConn
}
// Dial connects to every peer service at startup. Addrs are host:port
// (e.g. "workspace:9004"); see cmd/server/main.go for the env vars that
// supply them. Fails fast — the agent service cannot do anything
// useful without all four peers, so there's no point starting the gRPC
// server if one is unreachable (docker compose's restart policy
// handles the retry loop).
func Dial(workspaceAddr, knowledgeAddr, billingAddr, conversationAddr string) (*Clients, error) {
c := &Clients{}
dial := func(addr string) (*grpc.ClientConn, error) {
// Workspace responses can carry a full file's bytes/content
// (uploads, downloads, large reads) — match the server-side
// limit raised in services/workspace/cmd/server/main.go.
conn, err := grpc.NewClient(addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(24<<20), grpc.MaxCallSendMsgSize(24<<20)))
if err != nil {
return nil, fmt.Errorf("dial %s: %w", addr, err)
}
c.conns = append(c.conns, conn)
return conn, nil
}
wsConn, err := dial(workspaceAddr)
if err != nil {
return nil, err
}
kConn, err := dial(knowledgeAddr)
if err != nil {
return nil, err
}
bConn, err := dial(billingAddr)
if err != nil {
return nil, err
}
cConn, err := dial(conversationAddr)
if err != nil {
return nil, err
}
c.Workspace = workspacev1.NewWorkspaceServiceClient(wsConn)
c.Knowledge = knowledgev1.NewKnowledgeServiceClient(kConn)
c.Billing = billingv1.NewBillingServiceClient(bConn)
c.Conversation = conversationv1.NewConversationServiceClient(cConn)
return c, nil
}
func (c *Clients) Close() {
for _, conn := range c.conns {
_ = conn.Close()
}
}