90 lines
1.8 KiB
Go
Raw Permalink Normal View History

2024-07-11 16:37:26 +08:00
package invoke
import (
"fmt"
"sync"
"time"
2024-12-27 11:13:28 +08:00
2024-07-11 16:37:26 +08:00
"ultone/internal/tool"
2024-12-27 11:13:28 +08:00
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/resolver"
2024-07-11 16:37:26 +08:00
)
const (
2024-12-27 11:13:28 +08:00
SCHEME = "ult"
2024-07-11 16:37:26 +08:00
)
type Client[T any] struct {
domain string
endpoints []string
fn func(grpc.ClientConnInterface) T
opts []grpc.DialOption
cc *grpc.ClientConn
}
func (c *Client[T]) Session() T {
return c.fn(c.cc)
}
2024-12-27 11:13:28 +08:00
var clients = &sync.Map{}
2024-07-11 16:37:26 +08:00
// NewClient
/*
* domain => Example: sonar_search
* endpoints => Example: []string{"sonar_search:8080", "sonar_search:80801"} or []string{"10.10.10.10:32000", "10.10.10.10:32001"}
* fn => Example: system.NewSystemSrvClient
* opts => Example: grpc.WithTransportCredentials(insecure.NewCredentials()),
*/
func NewClient[T any](
domain string,
endpoints []string,
fn func(grpc.ClientConnInterface) T,
opts ...grpc.DialOption,
) (*Client[T], error) {
cached, ok := clients.Load(domain)
if ok {
if client, ok := cached.(*Client[T]); ok {
return client, nil
}
}
resolved := resolver.State{Addresses: make([]resolver.Address, 0)}
locker.Lock()
for _, item := range endpoints {
resolved.Addresses = append(resolved.Addresses, resolver.Address{Addr: item})
}
ips[domain] = resolved
locker.Unlock()
fullAddress := fmt.Sprintf("%s://%s", SCHEME, domain)
opts = append(opts,
grpc.WithResolvers(myBuilder),
grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`),
grpc.WithChainUnaryInterceptor(retryInterceptor(3, 3*time.Second)),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
conn, err := grpc.DialContext(
tool.Timeout(3),
fullAddress,
opts...,
)
if err != nil {
return nil, err
}
c := &Client[T]{
cc: conn,
fn: fn,
}
clients.Store(domain, c)
return c, nil
}