2019-11-11 08:23:21 +00:00
|
|
|
// Package service provides the broker service client
|
2021-10-27 18:27:04 +03:00
|
|
|
package service // import "go.unistack.org/micro-broker-service/v3"
|
2019-11-11 08:23:21 +00:00
|
|
|
|
|
|
|
import (
|
2021-01-19 19:41:39 +03:00
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2021-10-27 18:27:04 +03:00
|
|
|
pbmicro "go.unistack.org/micro-broker-service/v3/micro"
|
|
|
|
pb "go.unistack.org/micro-broker-service/v3/proto"
|
|
|
|
"go.unistack.org/micro/v3/broker"
|
|
|
|
"go.unistack.org/micro/v3/client"
|
|
|
|
"go.unistack.org/micro/v3/logger"
|
2021-10-27 18:47:36 +03:00
|
|
|
"go.unistack.org/micro/v3/metadata"
|
2019-11-11 08:23:21 +00:00
|
|
|
)
|
|
|
|
|
2023-03-25 22:16:14 +03:00
|
|
|
var _ broker.Broker = &serviceBroker{}
|
|
|
|
|
2021-01-19 19:41:39 +03:00
|
|
|
type serviceBroker struct {
|
2021-10-27 18:47:36 +03:00
|
|
|
client pbmicro.BrokerServiceClient
|
2023-03-25 22:16:14 +03:00
|
|
|
service string
|
2021-01-19 19:41:39 +03:00
|
|
|
opts broker.Options
|
2023-03-25 22:16:14 +03:00
|
|
|
addrs []string
|
|
|
|
init bool
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Address() string {
|
|
|
|
return b.addrs[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Connect(ctx context.Context) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Disconnect(ctx context.Context) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Init(opts ...broker.Option) error {
|
2021-03-24 23:23:53 +03:00
|
|
|
if len(opts) == 0 && b.init {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-19 19:41:39 +03:00
|
|
|
for _, o := range opts {
|
|
|
|
o(&b.opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
var cli client.Client
|
|
|
|
if b.opts.Context != nil {
|
|
|
|
if v, ok := b.opts.Context.Value(clientKey{}).(client.Client); ok && v != nil {
|
|
|
|
cli = v
|
|
|
|
}
|
|
|
|
if v, ok := b.opts.Context.Value(serviceKey{}).(string); ok && v != "" {
|
|
|
|
b.service = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 23:23:53 +03:00
|
|
|
if err := b.opts.Register.Init(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := b.opts.Tracer.Init(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := b.opts.Logger.Init(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := b.opts.Meter.Init(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-01-19 19:41:39 +03:00
|
|
|
if b.service == "" {
|
|
|
|
return fmt.Errorf("missing Service option")
|
|
|
|
}
|
|
|
|
|
|
|
|
if cli == nil {
|
|
|
|
return fmt.Errorf("missing Client option")
|
|
|
|
}
|
|
|
|
|
2021-10-27 18:47:36 +03:00
|
|
|
b.client = pbmicro.NewBrokerServiceClient(b.service, cli)
|
2021-01-19 19:41:39 +03:00
|
|
|
|
2021-03-24 23:26:02 +03:00
|
|
|
b.init = true
|
2021-01-19 19:41:39 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Options() broker.Options {
|
|
|
|
return b.opts
|
|
|
|
}
|
|
|
|
|
2021-10-27 18:47:36 +03:00
|
|
|
func (b *serviceBroker) BatchPublish(ctx context.Context, msgs []*broker.Message, opts ...broker.PublishOption) error {
|
|
|
|
return b.publish(ctx, msgs, opts...)
|
|
|
|
}
|
|
|
|
|
2021-01-19 19:41:39 +03:00
|
|
|
func (b *serviceBroker) Publish(ctx context.Context, topic string, msg *broker.Message, opts ...broker.PublishOption) error {
|
2021-10-27 18:47:36 +03:00
|
|
|
msg.Header.Set(metadata.HeaderTopic, topic)
|
|
|
|
return b.publish(ctx, []*broker.Message{msg}, opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) publish(ctx context.Context, msgs []*broker.Message, opts ...broker.PublishOption) error {
|
|
|
|
for _, msg := range msgs {
|
|
|
|
topic, _ := msg.Header.Get(metadata.HeaderTopic)
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
|
|
|
b.opts.Logger.Trace(ctx, fmt.Sprintf("Publishing to topic %s broker %v", topic, b.addrs))
|
2021-10-27 18:47:36 +03:00
|
|
|
}
|
|
|
|
_, err := b.client.Publish(ctx, &pb.PublishRequest{
|
|
|
|
Topic: topic,
|
|
|
|
Message: &pb.Message{
|
|
|
|
Header: msg.Header,
|
|
|
|
Body: msg.Body,
|
|
|
|
},
|
|
|
|
}, client.WithAddress(b.addrs...))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
2021-10-27 18:47:36 +03:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) BatchSubscribe(ctx context.Context, topic string, handler broker.BatchHandler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {
|
|
|
|
return nil, nil
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) Subscribe(ctx context.Context, topic string, handler broker.Handler, opts ...broker.SubscribeOption) (broker.Subscriber, error) {
|
|
|
|
options := broker.NewSubscribeOptions(opts...)
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
|
|
|
b.opts.Logger.Trace(ctx, fmt.Sprintf("Subscribing to topic %s group %s broker %v", topic, options.Group, b.addrs))
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
stream, err := b.client.Subscribe(ctx, &pb.SubscribeRequest{
|
|
|
|
Topic: topic,
|
|
|
|
Group: options.Group,
|
|
|
|
}, client.WithAddress(b.addrs...), client.WithRequestTimeout(time.Hour))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
sub := &serviceSub{
|
|
|
|
topic: topic,
|
|
|
|
group: options.Group,
|
|
|
|
handler: handler,
|
|
|
|
stream: stream,
|
|
|
|
closed: make(chan bool),
|
|
|
|
options: options,
|
2024-10-16 23:24:23 +03:00
|
|
|
opts: b.opts,
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-sub.closed:
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
|
|
|
b.opts.Logger.Trace(ctx, "Unsubscribed from topic %s", topic)
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
return
|
|
|
|
default:
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
2021-01-19 19:41:39 +03:00
|
|
|
// run the subscriber
|
2024-10-16 23:24:23 +03:00
|
|
|
b.opts.Logger.Trace(ctx, fmt.Sprintf("Streaming from broker %v to topic [%s] group [%s]", b.addrs, topic, options.Group))
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
if err := sub.run(ctx); err != nil {
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
|
|
|
b.opts.Logger.Trace(ctx, fmt.Sprintf("Resubscribing to topic %s broker %v", topic, b.addrs))
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
stream, err := b.client.Subscribe(ctx, &pb.SubscribeRequest{
|
|
|
|
Topic: topic,
|
|
|
|
Group: options.Group,
|
|
|
|
}, client.WithAddress(b.addrs...), client.WithRequestTimeout(time.Hour))
|
|
|
|
if err != nil {
|
2024-10-16 23:24:23 +03:00
|
|
|
if b.opts.Logger.V(logger.TraceLevel) {
|
|
|
|
b.opts.Logger.Trace(ctx, fmt.Sprintf("Failed to resubscribe to topic %s: %v", topic, err))
|
2021-01-19 19:41:39 +03:00
|
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// new stream
|
|
|
|
sub.stream = stream
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return sub, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *serviceBroker) String() string {
|
|
|
|
return "service"
|
2019-11-11 08:23:21 +00:00
|
|
|
}
|
|
|
|
|
2021-01-29 23:01:34 +03:00
|
|
|
func (b *serviceBroker) Name() string {
|
|
|
|
return b.opts.Name
|
|
|
|
}
|
|
|
|
|
2019-11-11 08:23:21 +00:00
|
|
|
func NewBroker(opts ...broker.Option) broker.Broker {
|
2021-01-19 19:41:39 +03:00
|
|
|
options := broker.NewOptions(opts...)
|
|
|
|
|
|
|
|
addrs := options.Addrs
|
|
|
|
if len(addrs) == 0 {
|
|
|
|
addrs = []string{"127.0.0.1:8001"}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &serviceBroker{
|
|
|
|
addrs: addrs,
|
|
|
|
opts: options,
|
|
|
|
}
|
2019-11-11 08:23:21 +00:00
|
|
|
}
|