You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							120 lines
						
					
					
						
							3.1 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							120 lines
						
					
					
						
							3.1 KiB
						
					
					
				
								//go:build gocdk
							 | 
						|
								// +build gocdk
							 | 
						|
								
							 | 
						|
								// Package gocdk_pub_sub supports the Go CDK (Cloud Development Kit) PubSub API,
							 | 
						|
								// which in turn supports many providers, including Amazon SNS/SQS, Azure Service Bus,
							 | 
						|
								// Google Cloud PubSub, and RabbitMQ.
							 | 
						|
								//
							 | 
						|
								// In the config, select a provider and topic using a URL. See
							 | 
						|
								// https://godoc.org/gocloud.dev/pubsub and its sub-packages for details.
							 | 
						|
								//
							 | 
						|
								// The Go CDK PubSub API does not support administrative operations like topic
							 | 
						|
								// creation. Create the topic using a UI, CLI or provider-specific API before running
							 | 
						|
								// weed.
							 | 
						|
								//
							 | 
						|
								// The Go CDK obtains credentials via environment variables and other
							 | 
						|
								// provider-specific default mechanisms. See the provider's documentation for
							 | 
						|
								// details.
							 | 
						|
								package gocdk_pub_sub
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"context"
							 | 
						|
									"fmt"
							 | 
						|
									amqp "github.com/rabbitmq/amqp091-go"
							 | 
						|
									"gocloud.dev/pubsub"
							 | 
						|
									_ "gocloud.dev/pubsub/awssnssqs"
							 | 
						|
									"gocloud.dev/pubsub/rabbitpubsub"
							 | 
						|
									"google.golang.org/protobuf/proto"
							 | 
						|
									"net/url"
							 | 
						|
									"path"
							 | 
						|
									"sync"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/glog"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/notification"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/util"
							 | 
						|
									// _ "gocloud.dev/pubsub/azuresb"
							 | 
						|
									_ "gocloud.dev/pubsub/gcppubsub"
							 | 
						|
									_ "gocloud.dev/pubsub/natspubsub"
							 | 
						|
									_ "gocloud.dev/pubsub/rabbitpubsub"
							 | 
						|
									"os"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								func init() {
							 | 
						|
									notification.MessageQueues = append(notification.MessageQueues, &GoCDKPubSub{})
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func getPath(rawUrl string) string {
							 | 
						|
									parsedUrl, _ := url.Parse(rawUrl)
							 | 
						|
									return path.Join(parsedUrl.Host, parsedUrl.Path)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								type GoCDKPubSub struct {
							 | 
						|
									topicURL  string
							 | 
						|
									topic     *pubsub.Topic
							 | 
						|
									topicLock sync.RWMutex
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (k *GoCDKPubSub) GetName() string {
							 | 
						|
									return "gocdk_pub_sub"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (k *GoCDKPubSub) setTopic(topic *pubsub.Topic) {
							 | 
						|
									k.topicLock.Lock()
							 | 
						|
									k.topic = topic
							 | 
						|
									k.topicLock.Unlock()
							 | 
						|
									k.doReconnect()
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (k *GoCDKPubSub) doReconnect() {
							 | 
						|
									var conn *amqp.Connection
							 | 
						|
									k.topicLock.RLock()
							 | 
						|
									defer k.topicLock.RUnlock()
							 | 
						|
									if k.topic.As(&conn) {
							 | 
						|
										go func(c *amqp.Connection) {
							 | 
						|
											<-c.NotifyClose(make(chan *amqp.Error))
							 | 
						|
											c.Close()
							 | 
						|
											k.topicLock.RLock()
							 | 
						|
											k.topic.Shutdown(context.Background())
							 | 
						|
											k.topicLock.RUnlock()
							 | 
						|
											for {
							 | 
						|
												glog.Info("Try reconnect")
							 | 
						|
												conn, err := amqp.Dial(os.Getenv("RABBIT_SERVER_URL"))
							 | 
						|
												if err == nil {
							 | 
						|
													k.setTopic(rabbitpubsub.OpenTopic(conn, getPath(k.topicURL), nil))
							 | 
						|
													break
							 | 
						|
												}
							 | 
						|
												glog.Error(err)
							 | 
						|
												time.Sleep(time.Second)
							 | 
						|
											}
							 | 
						|
										}(conn)
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (k *GoCDKPubSub) Initialize(configuration util.Configuration, prefix string) error {
							 | 
						|
									k.topicURL = configuration.GetString(prefix + "topic_url")
							 | 
						|
									glog.V(0).Infof("notification.gocdk_pub_sub.topic_url: %v", k.topicURL)
							 | 
						|
									topic, err := pubsub.OpenTopic(context.Background(), k.topicURL)
							 | 
						|
									if err != nil {
							 | 
						|
										glog.Fatalf("Failed to open topic: %v", err)
							 | 
						|
									}
							 | 
						|
									k.setTopic(topic)
							 | 
						|
									return nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (k *GoCDKPubSub) SendMessage(key string, message proto.Message) error {
							 | 
						|
									bytes, err := proto.Marshal(message)
							 | 
						|
									if err != nil {
							 | 
						|
										return err
							 | 
						|
									}
							 | 
						|
									k.topicLock.RLock()
							 | 
						|
									defer k.topicLock.RUnlock()
							 | 
						|
									err = k.topic.Send(context.Background(), &pubsub.Message{
							 | 
						|
										Body:     bytes,
							 | 
						|
										Metadata: map[string]string{"key": key},
							 | 
						|
									})
							 | 
						|
									if err != nil {
							 | 
						|
										return fmt.Errorf("send message via Go CDK pubsub %s: %v", k.topicURL, err)
							 | 
						|
									}
							 | 
						|
									return nil
							 | 
						|
								}
							 |