[release-1.10] Azure Service Bus: fix goroutine "explosion" after recovering from failure and many other bugs (#2523)
* Fixed context leak
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Finalize messages in background
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* More tweaks
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Moved a lot more code to the shared implementation package
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Fixed:
- Fixed: if number of messages received in bulk is greater than maxConcurrentHandlers, a deadlock happens
- Fixed: maxRetriableErrorsPerSec was not working
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Some refactorings
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Simplifications
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Avoid checking if topic/queue exists every time we send a message
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Ensuring locks are renewed for all 3 components
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Updated ASB SDK
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Improvements to closing
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Improvements to closing
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Changed context propagation
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Debug logs in cert tests
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Initial delay before renewing locks
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* That last change was actually unnecessary
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* Tweaks
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* More tweaks
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
* 💄
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
---------
Signed-off-by: ItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
parent
9dfe2f40bd
commit
12acf8effe
|
@ -20,7 +20,6 @@ import (
|
|||
"time"
|
||||
|
||||
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
|
||||
backoff "github.com/cenkalti/backoff/v4"
|
||||
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
impl "github.com/dapr/components-contrib/internal/component/azure/servicebus"
|
||||
|
@ -37,7 +36,6 @@ const (
|
|||
type AzureServiceBusQueues struct {
|
||||
metadata *impl.Metadata
|
||||
client *impl.Client
|
||||
timeout time.Duration
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
|
@ -54,7 +52,6 @@ func (a *AzureServiceBusQueues) Init(metadata bindings.Metadata) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.timeout = time.Duration(a.metadata.TimeoutInSec) * time.Second
|
||||
|
||||
a.client, err = impl.NewClient(a.metadata, metadata.Properties)
|
||||
if err != nil {
|
||||
|
@ -71,46 +68,25 @@ func (a *AzureServiceBusQueues) Init(metadata bindings.Metadata) (err error) {
|
|||
}
|
||||
|
||||
func (a *AzureServiceBusQueues) Operations() []bindings.OperationKind {
|
||||
return []bindings.OperationKind{bindings.CreateOperation}
|
||||
return []bindings.OperationKind{
|
||||
bindings.CreateOperation,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AzureServiceBusQueues) Invoke(invokeCtx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
|
||||
sender, err := a.client.GetSender(invokeCtx, a.metadata.QueueName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create a sender for the Service Bus queue: %w", err)
|
||||
}
|
||||
|
||||
msg, err := impl.NewASBMessageFromInvokeRequest(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create message: %w", err)
|
||||
}
|
||||
|
||||
// Send the message
|
||||
ctx, cancel := context.WithTimeout(invokeCtx, a.timeout)
|
||||
defer cancel()
|
||||
err = sender.SendMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
if impl.IsNetworkError(err) {
|
||||
// Force reconnection on next call
|
||||
a.client.CloseSender(a.metadata.QueueName, a.logger)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
func (a *AzureServiceBusQueues) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) {
|
||||
return a.client.PublishBinding(ctx, req, a.metadata.QueueName, a.logger)
|
||||
}
|
||||
|
||||
func (a *AzureServiceBusQueues) Read(subscribeCtx context.Context, handler bindings.Handler) error {
|
||||
func (a *AzureServiceBusQueues) Read(ctx context.Context, handler bindings.Handler) error {
|
||||
// Reconnection backoff policy
|
||||
bo := backoff.NewExponentialBackOff()
|
||||
bo.MaxElapsedTime = 0
|
||||
bo.InitialInterval = time.Duration(a.metadata.MinConnectionRecoveryInSec) * time.Second
|
||||
bo.MaxInterval = time.Duration(a.metadata.MaxConnectionRecoveryInSec) * time.Second
|
||||
bo := a.client.ReconnectionBackoff()
|
||||
|
||||
go func() {
|
||||
logMsg := "queue " + a.metadata.QueueName
|
||||
|
||||
// Reconnect loop.
|
||||
for {
|
||||
sub := impl.NewSubscription(subscribeCtx, impl.SubsriptionOptions{
|
||||
sub := impl.NewSubscription(impl.SubscriptionOptions{
|
||||
MaxActiveMessages: a.metadata.MaxActiveMessages,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
MaxBulkSubCount: nil,
|
||||
|
@ -122,9 +98,13 @@ func (a *AzureServiceBusQueues) Read(subscribeCtx context.Context, handler bindi
|
|||
}, a.logger)
|
||||
|
||||
// Blocks until a successful connection (or until context is canceled)
|
||||
receiver, err := sub.Connect(func() (impl.Receiver, error) {
|
||||
receiver, err := a.client.GetClient().NewReceiverForQueue(a.metadata.QueueName, nil)
|
||||
return &impl.MessageReceiver{Receiver: receiver}, err
|
||||
receiver, err := sub.Connect(ctx, func() (impl.Receiver, error) {
|
||||
a.logger.Debug("Connecting to " + logMsg)
|
||||
r, rErr := a.client.GetClient().NewReceiverForQueue(a.metadata.QueueName, nil)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
return impl.NewMessageReceiver(r), nil
|
||||
})
|
||||
if err != nil {
|
||||
// Realistically, the only time we should get to this point is if the context was canceled, but let's log any other error we may get.
|
||||
|
@ -137,28 +117,18 @@ func (a *AzureServiceBusQueues) Read(subscribeCtx context.Context, handler bindi
|
|||
// ReceiveAndBlock will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// If that occurs, we will log the error and attempt to re-establish the subscription connection until we exhaust the number of reconnect attempts.
|
||||
err = sub.ReceiveBlocking(
|
||||
ctx,
|
||||
a.getHandlerFn(handler),
|
||||
receiver,
|
||||
func() {
|
||||
// Reset the backoff when the subscription is successful and we have received the first message
|
||||
bo.Reset()
|
||||
},
|
||||
impl.ReceiveOptions{
|
||||
BulkEnabled: false, // Bulk is not supported here.
|
||||
},
|
||||
bo.Reset, // Reset the backoff when the subscription is successful and we have received the first message
|
||||
logMsg,
|
||||
)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
a.logger.Error(err)
|
||||
a.logger.Errorf("Error from receiver: %v", err)
|
||||
}
|
||||
|
||||
// Gracefully close the connection (in case it's not closed already)
|
||||
// Use a background context here (with timeout) because ctx may be closed already
|
||||
closeCtx, closeCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
sub.Close(closeCtx)
|
||||
closeCancel()
|
||||
|
||||
// If context was canceled, do not attempt to reconnect
|
||||
if subscribeCtx.Err() != nil {
|
||||
if ctx.Err() != nil {
|
||||
a.logger.Debug("Context canceled; will not reconnect")
|
||||
return
|
||||
}
|
||||
|
@ -166,6 +136,12 @@ func (a *AzureServiceBusQueues) Read(subscribeCtx context.Context, handler bindi
|
|||
wait := bo.NextBackOff()
|
||||
a.logger.Warnf("Subscription to queue %s lost connection, attempting to reconnect in %s...", a.metadata.QueueName, wait)
|
||||
time.Sleep(wait)
|
||||
|
||||
// Check for context canceled again, after sleeping
|
||||
if ctx.Err() != nil {
|
||||
a.logger.Debug("Context canceled; will not reconnect")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -205,6 +181,6 @@ func (a *AzureServiceBusQueues) getHandlerFn(handler bindings.Handler) impl.Hand
|
|||
|
||||
func (a *AzureServiceBusQueues) Close() (err error) {
|
||||
a.logger.Debug("Closing component")
|
||||
a.client.CloseAllSenders(a.logger)
|
||||
a.client.Close(a.logger)
|
||||
return nil
|
||||
}
|
||||
|
|
8
go.mod
8
go.mod
|
@ -9,14 +9,14 @@ require (
|
|||
cloud.google.com/go/storage v1.29.0
|
||||
dubbo.apache.org/dubbo-go/v3 v3.0.3-0.20230118042253-4f159a2b38f3
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid/v2 v2.0.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1
|
||||
|
@ -149,7 +149,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/DataDog/zstd v1.5.0 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.1.0 // indirect
|
||||
|
|
16
go.sum
16
go.sum
|
@ -413,11 +413,11 @@ github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl
|
|||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0 h1:OrKZybbyagpgJiREiIVzH5mV/z9oS4rXqdX7i31DSF0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v0.5.0/go.mod h1:p74+tP95m8830ypJk53L93+BEsjTKY4SKQ75J2NmS5U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3 h1:x1shk+tVZ6kLwIQMn4r+pdz8szo3mA0jd8STmgh+aRk=
|
||||
|
@ -433,8 +433,8 @@ github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 h1:Lg6BW0VPmCwcMl
|
|||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0 h1:X/ePaAG8guM7j5WORT5eEIw7cGUxe9Ah1jEQJKLmmSo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0/go.mod h1:5dog28UP3dd1BnCPFYvyHfsmA+Phmoezt+KWT5cZnyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4 h1:kaZamwZwmUqnECvnPkf1LBRBIFYYCy3E0gKHn/UFSD0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4/go.mod h1:uDLwkzCJMvTrHsvtiVFeAp85hi3W77zvs61wrpc+6ho=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0 h1:2BE/tjVTT4SNWwI3dWiMqX9mt0cImxYoJIXtFeJ72t4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0/go.mod h1:R6+0udeRV8iYSTVuT5RT7If4sc46K5Bz3ZKrmvZQF7U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid/v2 v2.0.0 h1:PcP4TC+0dC85A3i1p7CbD0FyrjnTvzQ3ipgSkJTIb7Y=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid/v2 v2.0.0/go.mod h1:rUn3oBeYkTxIsUzKxtXUPOt1ZO+bVHuZ3m5wauIfUHw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0 h1:BWeAAEzkCnL0ABVJqs+4mYudNch7oFGPtTlSmIWL8ms=
|
||||
|
@ -466,8 +466,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
|
|
@ -21,11 +21,16 @@ import (
|
|||
|
||||
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
|
||||
sbadmin "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/admin"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
azauth "github.com/dapr/components-contrib/internal/authentication/azure"
|
||||
"github.com/dapr/kit/logger"
|
||||
)
|
||||
|
||||
// Type that matches Client.EnsureTopic and Client.EnsureSubscription
|
||||
type ensureFn func(context.Context, string) error
|
||||
|
||||
// Client contains the clients for Service Bus and methods to get senders and to create topics, subscriptions, queues.
|
||||
type Client struct {
|
||||
client *servicebus.Client
|
||||
|
@ -97,8 +102,8 @@ func (c *Client) GetClient() *servicebus.Client {
|
|||
return c.client
|
||||
}
|
||||
|
||||
// GetSenderForTopic returns the sender for a topic, or creates a new one if it doesn't exist
|
||||
func (c *Client) GetSender(ctx context.Context, queueOrTopic string) (*servicebus.Sender, error) {
|
||||
// GetSenderForTopic returns the sender for a queue or topic, or creates a new one if it doesn't exist
|
||||
func (c *Client) GetSender(ctx context.Context, queueOrTopic string, ensureFn ensureFn) (*servicebus.Sender, error) {
|
||||
c.lock.RLock()
|
||||
sender, ok := c.senders[queueOrTopic]
|
||||
c.lock.RUnlock()
|
||||
|
@ -115,6 +120,16 @@ func (c *Client) GetSender(ctx context.Context, queueOrTopic string) (*servicebu
|
|||
return sender, nil
|
||||
}
|
||||
|
||||
// Ensure the queue or topic exists, if needed
|
||||
if ensureFn != nil {
|
||||
// Ensure the queue or topic exists the first time it is referenced
|
||||
// This does nothing if DisableEntityManagement is true
|
||||
err := ensureFn(ctx, queueOrTopic)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the sender
|
||||
sender, err := c.client.NewSender(queueOrTopic, nil)
|
||||
if err != nil {
|
||||
|
@ -128,21 +143,24 @@ func (c *Client) GetSender(ctx context.Context, queueOrTopic string) (*servicebu
|
|||
// CloseSender closes a sender for a queue or topic.
|
||||
func (c *Client) CloseSender(queueOrTopic string, log logger.Logger) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
sender, ok := c.senders[queueOrTopic]
|
||||
if ok && sender != nil {
|
||||
if ok {
|
||||
delete(c.senders, queueOrTopic)
|
||||
}
|
||||
c.lock.Unlock()
|
||||
|
||||
if sender != nil {
|
||||
log.Info("Closing sender: " + queueOrTopic)
|
||||
closeCtx, closeCancel := context.WithTimeout(context.Background(), time.Second)
|
||||
// Log only
|
||||
err := sender.Close(closeCtx)
|
||||
closeCancel()
|
||||
if err != nil {
|
||||
// Log only
|
||||
log.Warnf("Error closing sender %s: %v", queueOrTopic, err)
|
||||
}
|
||||
closeCancel()
|
||||
log.Debug("Closed sender: " + queueOrTopic)
|
||||
}
|
||||
delete(c.senders, queueOrTopic)
|
||||
}
|
||||
|
||||
// CloseAllSenders closes all sender connections.
|
||||
|
@ -174,7 +192,27 @@ func (c *Client) CloseAllSenders(log logger.Logger) {
|
|||
close(workersCh)
|
||||
|
||||
// Clear the map
|
||||
c.senders = make(map[string]*servicebus.Sender)
|
||||
maps.Clear(c.senders)
|
||||
}
|
||||
|
||||
// Close the client and every sender or consumer created by the connnection.
|
||||
func (c *Client) Close(log logger.Logger) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
if c.client != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(c.metadata.TimeoutInSec)*time.Second)
|
||||
err := c.client.Close(ctx)
|
||||
cancel()
|
||||
if err != nil {
|
||||
// log only
|
||||
log.Warnf("Error closing client: %v", err)
|
||||
}
|
||||
c.client = nil
|
||||
}
|
||||
|
||||
// Clear the map of senders
|
||||
maps.Clear(c.senders)
|
||||
}
|
||||
|
||||
// EnsureTopic creates the topic if it doesn't exist.
|
||||
|
@ -340,12 +378,20 @@ func (c *Client) createQueue(parentCtx context.Context, queue string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReconnectionBackoff returns the backoff for reconnecting in a subscription.
|
||||
func (c *Client) ReconnectionBackoff() backoff.BackOff {
|
||||
bo := backoff.NewExponentialBackOff()
|
||||
bo.MaxElapsedTime = 0
|
||||
bo.InitialInterval = time.Duration(c.metadata.MinConnectionRecoveryInSec) * time.Second
|
||||
bo.MaxInterval = time.Duration(c.metadata.MaxConnectionRecoveryInSec) * time.Second
|
||||
return bo
|
||||
}
|
||||
|
||||
func notEqual(a, b *bool) bool {
|
||||
if a == nil && b == nil {
|
||||
return false
|
||||
} else if a == nil || b == nil {
|
||||
return true
|
||||
} else {
|
||||
return *a != *b
|
||||
}
|
||||
return *a != *b
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
|
||||
// GetPubSubHandlerFunc returns the handler function for pubsub messages.
|
||||
func GetPubSubHandlerFunc(topic string, handler pubsub.Handler, log logger.Logger, timeout time.Duration) HandlerFn {
|
||||
emptyResponseItems := []HandlerResponseItem{}
|
||||
// Only the first ASB message is used in the actual handler invocation.
|
||||
return func(ctx context.Context, asbMsgs []*servicebus.ReceivedMessage) ([]HandlerResponseItem, error) {
|
||||
if len(asbMsgs) != 1 {
|
||||
|
@ -22,13 +21,13 @@ func GetPubSubHandlerFunc(topic string, handler pubsub.Handler, log logger.Logge
|
|||
|
||||
pubsubMsg, err := NewPubsubMessageFromASBMessage(asbMsgs[0], topic)
|
||||
if err != nil {
|
||||
return emptyResponseItems, fmt.Errorf("failed to get pubsub message from azure service bus message: %+v", err)
|
||||
return nil, fmt.Errorf("failed to get pubsub message from azure service bus message: %+v", err)
|
||||
}
|
||||
|
||||
handleCtx, handleCancel := context.WithTimeout(ctx, timeout)
|
||||
defer handleCancel()
|
||||
log.Debugf("Calling app's handler for message %s on topic %s", asbMsgs[0].MessageID, topic)
|
||||
return emptyResponseItems, handler(handleCtx, pubsubMsg)
|
||||
return nil, handler(handleCtx, pubsubMsg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
Copyright 2023 The Dapr Authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package servicebus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
|
||||
"github.com/dapr/components-contrib/bindings"
|
||||
"github.com/dapr/components-contrib/internal/utils"
|
||||
contribMetadata "github.com/dapr/components-contrib/metadata"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
"github.com/dapr/kit/logger"
|
||||
"github.com/dapr/kit/retry"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxBulkSubCount = 100
|
||||
defaultMaxBulkPubBytes uint64 = 128 << 10 // 128 KiB
|
||||
)
|
||||
|
||||
// PublishPubSub is used by PubSub components to publish messages. It includes a retry logic that can also cause reconnections.
|
||||
func (c *Client) PublishPubSub(ctx context.Context, req *pubsub.PublishRequest, ensureFn ensureFn, log logger.Logger) error {
|
||||
msg, err := NewASBMessageFromPubsubRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bo := c.publishBackOff(ctx)
|
||||
|
||||
msgID := "nil"
|
||||
if msg.MessageID != nil {
|
||||
msgID = *msg.MessageID
|
||||
}
|
||||
err = retry.NotifyRecover(
|
||||
func() error {
|
||||
// Get the sender
|
||||
sender, rErr := c.GetSender(ctx, req.Topic, ensureFn)
|
||||
if rErr != nil {
|
||||
return fmt.Errorf("failed to create a sender: %w", rErr)
|
||||
}
|
||||
|
||||
// Try sending the message
|
||||
publishCtx, publisCancel := context.WithTimeout(ctx, time.Second*time.Duration(c.metadata.TimeoutInSec))
|
||||
rErr = sender.SendMessage(publishCtx, msg, nil)
|
||||
publisCancel()
|
||||
if rErr != nil {
|
||||
if IsNetworkError(rErr) {
|
||||
// Retry after reconnecting
|
||||
c.CloseSender(req.Topic, log)
|
||||
return rErr
|
||||
}
|
||||
|
||||
if IsRetriableAMQPError(rErr) {
|
||||
// Retry (no need to reconnect)
|
||||
return rErr
|
||||
}
|
||||
|
||||
// Do not retry on other errors
|
||||
return backoff.Permanent(rErr)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
bo,
|
||||
func(err error, _ time.Duration) {
|
||||
log.Warnf("Could not publish Service Bus message (%s). Retrying...: %v", msgID, err)
|
||||
},
|
||||
func() {
|
||||
log.Infof("Successfully published Service Bus message (%s) after it previously failed", msgID)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Too many failed attempts while publishing Service Bus message (%s): %v", msgID, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// PublishPubSubBulk is used by PubSub components to publush bulk messages.
|
||||
func (c *Client) PublishPubSubBulk(ctx context.Context, req *pubsub.BulkPublishRequest, ensureFn ensureFn, log logger.Logger) (pubsub.BulkPublishResponse, error) {
|
||||
// If the request is empty, sender.SendMessageBatch will panic later.
|
||||
// Return an empty response to avoid this.
|
||||
if len(req.Entries) == 0 {
|
||||
log.Warnf("Empty bulk publish request, skipping")
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
}
|
||||
|
||||
// Get the sender
|
||||
sender, err := c.GetSender(ctx, req.Topic, ensureFn)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Create a new batch of messages with batch options.
|
||||
batchOpts := &servicebus.MessageBatchOptions{
|
||||
MaxBytes: utils.GetElemOrDefaultFromMap(req.Metadata, contribMetadata.MaxBulkPubBytesKey, defaultMaxBulkPubBytes),
|
||||
}
|
||||
|
||||
batchMsg, err := sender.NewMessageBatch(ctx, batchOpts)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Add messages from the bulk publish request to the batch.
|
||||
err = UpdateASBBatchMessageWithBulkPublishRequest(batchMsg, req)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Azure Service Bus does not return individual status for each message in the request.
|
||||
err = sender.SendMessageBatch(ctx, batchMsg, nil)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
}
|
||||
|
||||
// PublishBinding is used by binding components to publish messages. It includes a retry logic that can also cause reconnections.
|
||||
// Note this doesn't invoke "EnsureQueue" or "EnsureTopic" because bindings don't do that on publishing.
|
||||
func (c *Client) PublishBinding(ctx context.Context, req *bindings.InvokeRequest, queueOrTopic string, log logger.Logger) (*bindings.InvokeResponse, error) {
|
||||
msg, err := NewASBMessageFromInvokeRequest(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create message: %w", err)
|
||||
}
|
||||
|
||||
bo := c.publishBackOff(ctx)
|
||||
|
||||
msgID := "nil"
|
||||
if msg.MessageID != nil {
|
||||
msgID = *msg.MessageID
|
||||
}
|
||||
|
||||
err = retry.NotifyRecover(
|
||||
func() error {
|
||||
// Get the sender
|
||||
sender, rErr := c.GetSender(ctx, queueOrTopic, nil)
|
||||
if rErr != nil {
|
||||
return fmt.Errorf("failed to create a sender: %w", rErr)
|
||||
}
|
||||
|
||||
// Try sending the message
|
||||
publishCtx, publisCancel := context.WithTimeout(ctx, time.Second*time.Duration(c.metadata.TimeoutInSec))
|
||||
rErr = sender.SendMessage(publishCtx, msg, nil)
|
||||
publisCancel()
|
||||
if rErr != nil {
|
||||
if IsNetworkError(rErr) {
|
||||
// Retry after reconnecting
|
||||
c.CloseSender(queueOrTopic, log)
|
||||
return rErr
|
||||
}
|
||||
|
||||
if IsRetriableAMQPError(rErr) {
|
||||
// Retry (no need to reconnect)
|
||||
return rErr
|
||||
}
|
||||
|
||||
// Do not retry on other errors
|
||||
return backoff.Permanent(rErr)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
bo,
|
||||
func(err error, _ time.Duration) {
|
||||
log.Warnf("Could not publish Service Bus message (%s). Retrying...: %v", msgID, err)
|
||||
},
|
||||
func() {
|
||||
log.Infof("Successfully published Service Bus message (%s) after it previously failed", msgID)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("Too many failed attempts while publishing Service Bus message (%s): %v", msgID, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (c *Client) publishBackOff(ctx context.Context) (bo backoff.BackOff) {
|
||||
ebo := backoff.NewExponentialBackOff()
|
||||
ebo.InitialInterval = time.Duration(c.metadata.PublishInitialRetryIntervalInMs) * time.Millisecond
|
||||
bo = backoff.WithMaxRetries(ebo, uint64(c.metadata.PublishMaxRetries))
|
||||
bo = backoff.WithContext(bo, ctx)
|
||||
return bo
|
||||
}
|
|
@ -43,12 +43,12 @@ type SessionReceiver struct {
|
|||
*azservicebus.SessionReceiver
|
||||
}
|
||||
|
||||
func (s *SessionReceiver) RenewSessionLocks(ctx context.Context, timeoutInSec int) error {
|
||||
func (s *SessionReceiver) RenewSessionLocks(ctx context.Context, timeout time.Duration) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
lockCtx, lockCancel := context.WithTimeout(ctx, time.Second*time.Duration(timeoutInSec))
|
||||
lockCtx, lockCancel := context.WithTimeout(ctx, timeout)
|
||||
defer lockCancel()
|
||||
|
||||
return s.RenewSessionLock(lockCtx, nil)
|
||||
|
@ -62,7 +62,7 @@ type MessageReceiver struct {
|
|||
*azservicebus.Receiver
|
||||
}
|
||||
|
||||
func (m *MessageReceiver) RenewMessageLocks(ctx context.Context, msgs []*azservicebus.ReceivedMessage, timeoutInSec int) error {
|
||||
func (m *MessageReceiver) RenewMessageLocks(ctx context.Context, msgs []*azservicebus.ReceivedMessage, timeout time.Duration) error {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ func (m *MessageReceiver) RenewMessageLocks(ctx context.Context, msgs []*azservi
|
|||
go func(rmsg *azservicebus.ReceivedMessage) {
|
||||
defer wg.Done()
|
||||
|
||||
lockCtx, lockCancel := context.WithTimeout(ctx, time.Second*time.Duration(timeoutInSec))
|
||||
lockCtx, lockCancel := context.WithTimeout(ctx, timeout)
|
||||
defer lockCancel()
|
||||
|
||||
// Renew the lock for the message.
|
||||
|
@ -92,6 +92,9 @@ func (m *MessageReceiver) RenewMessageLocks(ctx context.Context, msgs []*azservi
|
|||
|
||||
errs := []error{}
|
||||
for err := range errChan {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -52,17 +52,17 @@ type Subscription struct {
|
|||
mu sync.RWMutex
|
||||
activeMessages map[int64]*azservicebus.ReceivedMessage
|
||||
activeOperationsChan chan struct{}
|
||||
requireSessions bool // read-only once set
|
||||
requireSessions bool
|
||||
sessionIdleTimeout time.Duration
|
||||
timeout time.Duration
|
||||
lockRenewalInterval time.Duration
|
||||
maxBulkSubCount int
|
||||
retriableErrLimit ratelimit.Limiter
|
||||
retriableErrLimiter ratelimit.Limiter
|
||||
handleChan chan struct{}
|
||||
logger logger.Logger
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
type SubsriptionOptions struct {
|
||||
type SubscriptionOptions struct {
|
||||
MaxActiveMessages int
|
||||
TimeoutInSec int
|
||||
MaxBulkSubCount *int
|
||||
|
@ -71,17 +71,12 @@ type SubsriptionOptions struct {
|
|||
Entity string
|
||||
LockRenewalInSec int
|
||||
RequireSessions bool
|
||||
SessionIdleTimeout time.Duration
|
||||
}
|
||||
|
||||
// NewBulkSubscription returns a new Subscription object.
|
||||
// Parameter "entity" is usually in the format "topic <topicname>" or "queue <queuename>" and it's only used for logging.
|
||||
func NewSubscription(
|
||||
parentCtx context.Context,
|
||||
opts SubsriptionOptions,
|
||||
logger logger.Logger,
|
||||
) *Subscription {
|
||||
ctx, cancel := context.WithCancel(parentCtx)
|
||||
|
||||
func NewSubscription(opts SubscriptionOptions, logger logger.Logger) *Subscription {
|
||||
if opts.MaxBulkSubCount != nil {
|
||||
if *opts.MaxBulkSubCount < 1 {
|
||||
logger.Warnf("maxBulkSubCount must be greater than 0, setting it to 1")
|
||||
|
@ -98,23 +93,23 @@ func NewSubscription(
|
|||
}
|
||||
|
||||
s := &Subscription{
|
||||
entity: opts.Entity,
|
||||
activeMessages: make(map[int64]*azservicebus.ReceivedMessage),
|
||||
timeout: time.Duration(opts.TimeoutInSec) * time.Second,
|
||||
maxBulkSubCount: *opts.MaxBulkSubCount,
|
||||
requireSessions: opts.RequireSessions,
|
||||
logger: logger,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
entity: opts.Entity,
|
||||
activeMessages: make(map[int64]*azservicebus.ReceivedMessage),
|
||||
timeout: time.Duration(opts.TimeoutInSec) * time.Second,
|
||||
lockRenewalInterval: time.Duration(opts.LockRenewalInSec) * time.Second,
|
||||
sessionIdleTimeout: opts.SessionIdleTimeout,
|
||||
maxBulkSubCount: *opts.MaxBulkSubCount,
|
||||
requireSessions: opts.RequireSessions,
|
||||
logger: logger,
|
||||
// This is a pessimistic estimate of the number of total operations that can be active at any given time.
|
||||
// In case of a non-bulk subscription, one operation is one message.
|
||||
activeOperationsChan: make(chan struct{}, opts.MaxActiveMessages/(*opts.MaxBulkSubCount)),
|
||||
}
|
||||
|
||||
if opts.MaxRetriableEPS > 0 {
|
||||
s.retriableErrLimit = ratelimit.New(opts.MaxRetriableEPS)
|
||||
s.retriableErrLimiter = ratelimit.New(opts.MaxRetriableEPS)
|
||||
} else {
|
||||
s.retriableErrLimit = ratelimit.NewUnlimited()
|
||||
s.retriableErrLimiter = ratelimit.NewUnlimited()
|
||||
}
|
||||
|
||||
if opts.MaxConcurrentHandlers > 0 {
|
||||
|
@ -126,18 +121,17 @@ func NewSubscription(
|
|||
}
|
||||
|
||||
// Connect to a Service Bus topic or queue, blocking until it succeeds; it can retry forever (until the context is canceled).
|
||||
func (s *Subscription) Connect(newReceiverFunc func() (Receiver, error)) (Receiver, error) {
|
||||
func (s *Subscription) Connect(ctx context.Context, newReceiverFunc func() (Receiver, error)) (Receiver, error) {
|
||||
// Connections need to retry forever with a maximum backoff of 5 minutes and exponential scaling.
|
||||
config := retry.DefaultConfig()
|
||||
config.Policy = retry.PolicyExponential
|
||||
config.MaxInterval = 5 * time.Minute
|
||||
config.MaxElapsedTime = 0
|
||||
backoff := config.NewBackOffWithContext(s.ctx)
|
||||
backoff := config.NewBackOffWithContext(ctx)
|
||||
|
||||
return retry.NotifyRecoverWithData(
|
||||
func() (Receiver, error) {
|
||||
var receiver Receiver
|
||||
clientAttempt, innerErr := newReceiverFunc()
|
||||
receiver, innerErr := newReceiverFunc()
|
||||
if innerErr != nil {
|
||||
if s.requireSessions {
|
||||
var sbErr *azservicebus.Error
|
||||
|
@ -147,18 +141,10 @@ func (s *Subscription) Connect(newReceiverFunc func() (Receiver, error)) (Receiv
|
|||
}
|
||||
return nil, innerErr
|
||||
}
|
||||
if s.requireSessions {
|
||||
sessionReceiver, ok := clientAttempt.(*SessionReceiver)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected a session receiver, got %T", clientAttempt)
|
||||
}
|
||||
receiver = sessionReceiver
|
||||
} else {
|
||||
msgReciever, ok := clientAttempt.(*MessageReceiver)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected a message receiver, got %T", clientAttempt)
|
||||
}
|
||||
receiver = msgReciever
|
||||
if _, ok := receiver.(*SessionReceiver); !ok && s.requireSessions {
|
||||
return nil, fmt.Errorf("expected a session receiver, got %T", receiver)
|
||||
} else if _, ok := receiver.(*MessageReceiver); !ok && !s.requireSessions {
|
||||
return nil, fmt.Errorf("expected a message receiver, got %T", receiver)
|
||||
}
|
||||
return receiver, nil
|
||||
},
|
||||
|
@ -172,25 +158,46 @@ func (s *Subscription) Connect(newReceiverFunc func() (Receiver, error)) (Receiv
|
|||
)
|
||||
}
|
||||
|
||||
type ReceiveOptions struct {
|
||||
BulkEnabled bool
|
||||
SessionIdleTimeout time.Duration
|
||||
}
|
||||
|
||||
// ReceiveBlocking is a blocking call to receive messages on an Azure Service Bus subscription from a topic or queue.
|
||||
func (s *Subscription) ReceiveBlocking(handler HandlerFn, receiver Receiver, onFirstSuccess func(), opts ReceiveOptions) error {
|
||||
ctx, cancel := context.WithCancel(s.ctx)
|
||||
defer cancel()
|
||||
func (s *Subscription) ReceiveBlocking(parentCtx context.Context, handler HandlerFn, receiver Receiver, onFirstSuccess func(), logMsg string) error {
|
||||
ctx, cancel := context.WithCancel(parentCtx)
|
||||
|
||||
defer func() {
|
||||
// Cancel the context which also stops the lock renewal loop
|
||||
cancel()
|
||||
|
||||
// Close the receiver when we're done
|
||||
s.logger.Debug("Closing message receiver for " + logMsg)
|
||||
closeReceiverCtx, closeReceiverCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
err := receiver.Close(closeReceiverCtx)
|
||||
closeReceiverCancel()
|
||||
if err != nil {
|
||||
// Log errors only
|
||||
s.logger.Warn("Error while closing receiver for " + logMsg)
|
||||
}
|
||||
}()
|
||||
|
||||
// Lock renewal loop
|
||||
go func() {
|
||||
s.logger.Debug("Starting lock renewal loop for " + logMsg)
|
||||
lockErr := s.renewLocksBlocking(ctx, receiver)
|
||||
if lockErr != nil {
|
||||
if !errors.Is(lockErr, context.Canceled) {
|
||||
s.logger.Errorf("Error from lock renewal for %s: %v", logMsg, lockErr)
|
||||
}
|
||||
}
|
||||
s.logger.Debug("Exiting lock renewal loop for " + logMsg)
|
||||
}()
|
||||
|
||||
// Receiver loop
|
||||
for {
|
||||
// This blocks if there are too many active operations already
|
||||
// This is released by the handler, but if the loop ends before it reaches the handler, make sure to release it with `<-s.activeOperationsChan`
|
||||
select {
|
||||
case s.activeOperationsChan <- struct{}{}:
|
||||
// No-op
|
||||
// This blocks if there are too many active operations already
|
||||
// This is released by the handler, but if the loop ends before it reaches the handler, make sure to release it with `<-s.activeOperationsChan`
|
||||
case <-ctx.Done():
|
||||
// Return if context is canceled
|
||||
// Context is canceled or expired; return
|
||||
s.logger.Debugf("Receive context for %s done", s.entity)
|
||||
return ctx.Err()
|
||||
}
|
||||
|
@ -200,17 +207,22 @@ func (s *Subscription) ReceiveBlocking(handler HandlerFn, receiver Receiver, onF
|
|||
// messages. If we do not require sessions then we will block
|
||||
// on the receiver until a message is available or the context
|
||||
// is canceled.
|
||||
var receiverCtx context.Context
|
||||
if s.requireSessions && opts.SessionIdleTimeout > 0 {
|
||||
var receiverCancel context.CancelFunc
|
||||
receiverCtx, receiverCancel = context.WithTimeout(ctx, opts.SessionIdleTimeout)
|
||||
defer receiverCancel()
|
||||
var (
|
||||
receiverCtx context.Context
|
||||
receiverCancel context.CancelFunc
|
||||
)
|
||||
if s.requireSessions && s.sessionIdleTimeout > 0 {
|
||||
// Canceled below after the context is used (we can't defer a cancelation because we're in a loop)
|
||||
receiverCtx, receiverCancel = context.WithTimeout(ctx, s.sessionIdleTimeout)
|
||||
} else {
|
||||
receiverCtx = s.ctx
|
||||
receiverCtx = ctx
|
||||
}
|
||||
|
||||
// This method blocks until we get a message or the context is canceled
|
||||
msgs, err := receiver.ReceiveMessages(receiverCtx, s.maxBulkSubCount, nil)
|
||||
if receiverCancel != nil {
|
||||
receiverCancel()
|
||||
}
|
||||
if err != nil {
|
||||
if err != context.Canceled {
|
||||
s.logger.Errorf("Error reading from %s. %s", s.entity, err.Error())
|
||||
|
@ -220,16 +232,13 @@ func (s *Subscription) ReceiveBlocking(handler HandlerFn, receiver Receiver, onF
|
|||
return err
|
||||
}
|
||||
|
||||
l := len(msgs)
|
||||
if l == 0 {
|
||||
if len(msgs) == 0 {
|
||||
// We got no message, which is unusual too
|
||||
// Treat this as error
|
||||
s.logger.Warn("Received 0 messages from Service Bus")
|
||||
<-s.activeOperationsChan
|
||||
// Return an error to force the Service Bus component to try and reconnect.
|
||||
return errors.New("received 0 messages from Service Bus")
|
||||
} else if l > 1 {
|
||||
// We are requesting one message only; this should never happen
|
||||
s.logger.Errorf("Expected one message from Service Bus, but received %d", l)
|
||||
}
|
||||
|
||||
// Invoke only once
|
||||
|
@ -238,11 +247,12 @@ func (s *Subscription) ReceiveBlocking(handler HandlerFn, receiver Receiver, onF
|
|||
onFirstSuccess = nil
|
||||
}
|
||||
|
||||
s.logger.Debugf("Received messages: %d; current active operations usage: %d/%d", l, len(s.activeOperationsChan), cap(s.activeOperationsChan))
|
||||
s.logger.Debugf("Received messages: %d; current active operations usage: %d/%d", len(msgs), len(s.activeOperationsChan), cap(s.activeOperationsChan))
|
||||
|
||||
skipProcessing := false
|
||||
for _, msg := range msgs {
|
||||
if err = s.addActiveMessage(msg); err != nil {
|
||||
err = s.addActiveMessage(msg)
|
||||
if err != nil {
|
||||
// If we cannot add the message then sequence number is not set, this must
|
||||
// be a bug in the Azure Service Bus SDK so we will log the error and not
|
||||
// handle the message. The message will eventually be retried until fixed.
|
||||
|
@ -258,187 +268,164 @@ func (s *Subscription) ReceiveBlocking(handler HandlerFn, receiver Receiver, onF
|
|||
continue
|
||||
}
|
||||
|
||||
runHandlerFn := func(hctx context.Context) {
|
||||
msg := msgs[0]
|
||||
|
||||
// Invoke the handler to process the message
|
||||
_, err = handler(hctx, msgs)
|
||||
|
||||
// This context is used for the calls to service bus to finalize (i.e. complete/abandon) the message.
|
||||
// If we fail to finalize the message, this message will eventually be reprocessed (at-least once delivery).
|
||||
// This uses a background context in case ctx has been canceled already.
|
||||
finalizeCtx, finalizeCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
defer finalizeCancel()
|
||||
|
||||
if err != nil {
|
||||
// Log the error only, as we're running asynchronously
|
||||
s.logger.Errorf("App handler returned an error for message %s on %s: %s", msg.MessageID, s.entity, err)
|
||||
s.AbandonMessage(finalizeCtx, receiver, msg)
|
||||
return
|
||||
}
|
||||
|
||||
s.CompleteMessage(finalizeCtx, receiver, msg)
|
||||
}
|
||||
|
||||
bulkRunHandlerFn := func(hctx context.Context) {
|
||||
resps, err := handler(hctx, msgs)
|
||||
|
||||
// This context is used for the calls to service bus to finalize (i.e. complete/abandon) the message.
|
||||
// If we fail to finalize the message, this message will eventually be reprocessed (at-least once delivery).
|
||||
// This uses a background context in case ctx has been canceled already.
|
||||
finalizeCtx, finalizeCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
defer finalizeCancel()
|
||||
|
||||
if err != nil {
|
||||
// Handle the error and mark messages accordingly.
|
||||
// Note, the order of the responses match the order of the messages.
|
||||
for i, resp := range resps {
|
||||
if resp.Error != nil {
|
||||
// Log the error only, as we're running asynchronously.
|
||||
s.logger.Errorf("App handler returned an error for message %s on %s: %s", msgs[i].MessageID, s.entity, resp.Error)
|
||||
s.AbandonMessage(finalizeCtx, receiver, msgs[i])
|
||||
} else {
|
||||
s.CompleteMessage(finalizeCtx, receiver, msgs[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// No error, so we can complete all messages.
|
||||
for _, msg := range msgs {
|
||||
s.CompleteMessage(finalizeCtx, receiver, msg)
|
||||
}
|
||||
}
|
||||
|
||||
if opts.BulkEnabled {
|
||||
s.handleAsync(s.ctx, msgs, bulkRunHandlerFn)
|
||||
} else {
|
||||
s.handleAsync(s.ctx, msgs, runHandlerFn)
|
||||
}
|
||||
// Handle the messages in background
|
||||
go s.handleAsync(ctx, msgs, handler, receiver)
|
||||
}
|
||||
}
|
||||
|
||||
// Close the receiver and stops watching for new messages.
|
||||
func (s *Subscription) Close(closeCtx context.Context) {
|
||||
s.logger.Debugf("Closing subscription to %s", s.entity)
|
||||
s.cancel()
|
||||
}
|
||||
|
||||
type LockRenewalOptions struct {
|
||||
RenewalInSec int
|
||||
TimeoutInSec int
|
||||
}
|
||||
|
||||
func (s *Subscription) RenewLocksBlocking(ctx context.Context, receiver Receiver, opts LockRenewalOptions) error {
|
||||
func (s *Subscription) renewLocksBlocking(ctx context.Context, receiver Receiver) error {
|
||||
if receiver == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
shouldRenewLocks := opts.RenewalInSec > 0
|
||||
if !shouldRenewLocks {
|
||||
s.logger.Debugf("Lock renewal for %s disabled", s.entity)
|
||||
if s.lockRenewalInterval <= 0 {
|
||||
s.logger.Info("Lock renewal for %s disabled", s.entity)
|
||||
return nil
|
||||
}
|
||||
|
||||
t := time.NewTicker(time.Second * time.Duration(opts.RenewalInSec))
|
||||
t := time.NewTicker(s.lockRenewalInterval)
|
||||
defer t.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
s.logger.Infof("Context canceled while renewing locks for %s", s.entity)
|
||||
return nil
|
||||
case <-t.C:
|
||||
// Check if the context is still valid
|
||||
if ctx.Err() != nil {
|
||||
s.logger.Infof("Context canceled while renewing locks for %s", s.entity)
|
||||
return nil //nolint:nilerr
|
||||
}
|
||||
if s.requireSessions {
|
||||
sessionReceiver := receiver.(*SessionReceiver)
|
||||
if err := sessionReceiver.RenewSessionLocks(ctx, opts.TimeoutInSec); err != nil {
|
||||
s.logger.Warnf("Error renewing session locks for %s: %s", s.entity, err)
|
||||
}
|
||||
s.logger.Debugf("Renewed session %s locks for %s", sessionReceiver.SessionID(), s.entity)
|
||||
s.doRenewLocksSession(ctx, receiver.(*SessionReceiver))
|
||||
} else {
|
||||
// Snapshot the messages to try to renew locks for.
|
||||
s.mu.RLock()
|
||||
msgs := make([]*azservicebus.ReceivedMessage, len(s.activeMessages))
|
||||
var i int
|
||||
for _, m := range s.activeMessages {
|
||||
msgs[i] = m
|
||||
i++
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
if len(msgs) == 0 {
|
||||
s.logger.Debugf("No active messages require lock renewal for %s", s.entity)
|
||||
continue
|
||||
}
|
||||
msgReceiver := receiver.(*MessageReceiver)
|
||||
if err := msgReceiver.RenewMessageLocks(ctx, msgs, opts.TimeoutInSec); err != nil {
|
||||
s.logger.Warnf("Error renewing message locks for %s: %s", s.entity, err)
|
||||
}
|
||||
s.logger.Debugf("Renewed message locks for %s", s.entity)
|
||||
s.doRenewLocks(ctx, receiver.(*MessageReceiver))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleAsync handles messages from azure service bus asynchronously.
|
||||
// runHandlerFn is responsible for calling the message handler function
|
||||
// and marking messages as complete/abandon.
|
||||
func (s *Subscription) handleAsync(ctx context.Context, msgs []*azservicebus.ReceivedMessage, runHandlerFn func(ctx context.Context)) {
|
||||
go func() {
|
||||
var (
|
||||
consumeToken bool
|
||||
takenConcurrentHandler bool
|
||||
)
|
||||
func (s *Subscription) doRenewLocks(ctx context.Context, msgReceiver *MessageReceiver) {
|
||||
// Snapshot the messages to try to renew locks for.
|
||||
s.mu.RLock()
|
||||
msgs := make([]*azservicebus.ReceivedMessage, len(s.activeMessages))
|
||||
var i int
|
||||
for _, m := range s.activeMessages {
|
||||
msgs[i] = m
|
||||
i++
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
defer func() {
|
||||
for _, msg := range msgs {
|
||||
// Release a handler if needed
|
||||
if takenConcurrentHandler {
|
||||
<-s.handleChan
|
||||
s.logger.Debugf("Released message handle for %s on %s", msg.MessageID, s.entity)
|
||||
}
|
||||
if len(msgs) == 0 {
|
||||
s.logger.Debugf("No active messages require lock renewal for %s", s.entity)
|
||||
return
|
||||
}
|
||||
|
||||
// If we got a retriable error (app handler returned a retriable error, or a network error while connecting to the app, etc) consume a retriable error token
|
||||
// We do it here, after the handler has been released but before removing the active message (which would allow us to retrieve more messages)
|
||||
if consumeToken {
|
||||
s.logger.Debugf("Taking a retriable error token")
|
||||
before := time.Now()
|
||||
_ = s.retriableErrLimit.Take()
|
||||
s.logger.Debugf("Resumed after pausing for %v", time.Since(before))
|
||||
}
|
||||
err := msgReceiver.RenewMessageLocks(ctx, msgs, s.timeout)
|
||||
if err != nil {
|
||||
s.logger.Warnf("Error renewing message locks for %s: %v", s.entity, err)
|
||||
} else {
|
||||
s.logger.Debugf("Renewed message locks for %s", s.entity)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the message from the map of active ones
|
||||
s.removeActiveMessage(msg.MessageID, *msg.SequenceNumber)
|
||||
}
|
||||
func (s *Subscription) doRenewLocksSession(ctx context.Context, sessionReceiver *SessionReceiver) {
|
||||
err := sessionReceiver.RenewSessionLocks(ctx, s.timeout)
|
||||
if err != nil {
|
||||
s.logger.Warnf("Error renewing session locks for %s: %v", s.entity, err)
|
||||
} else {
|
||||
s.logger.Debugf("Renewed session %s locks for %s", sessionReceiver.SessionID(), s.entity)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove an entry from activeOperationsChan to allow processing more messages
|
||||
<-s.activeOperationsChan
|
||||
}()
|
||||
// handleAsync handles messages from azure service bus and is meant to be called in a goroutine (go s.handleAsync).
|
||||
func (s *Subscription) handleAsync(ctx context.Context, msgs []*azservicebus.ReceivedMessage, handler HandlerFn, receiver Receiver) {
|
||||
var (
|
||||
consumeToken bool
|
||||
takenConcurrentHandler bool
|
||||
)
|
||||
|
||||
for _, msg := range msgs {
|
||||
// If handleChan is non-nil, we have a limit on how many handler we can process
|
||||
if cap(s.handleChan) > 0 {
|
||||
s.logger.Debugf("Taking message handle for %s on %s", msg.MessageID, s.entity)
|
||||
select {
|
||||
// Context is done, so we will stop waiting
|
||||
case <-ctx.Done():
|
||||
s.logger.Debugf("Message context done for %s on %s", msg.MessageID, s.entity)
|
||||
return
|
||||
// Blocks until we have a handler available
|
||||
case s.handleChan <- struct{}{}:
|
||||
takenConcurrentHandler = true
|
||||
s.logger.Debugf("Taken message handle for %s on %s", msg.MessageID, s.entity)
|
||||
}
|
||||
// Invoke this at the end of the execution to release all taken tokens
|
||||
defer func() {
|
||||
// Release a handler if needed
|
||||
if takenConcurrentHandler {
|
||||
<-s.handleChan
|
||||
s.logger.Debugf("Released message handle for %s on %s", msgs[0].MessageID, s.entity)
|
||||
}
|
||||
|
||||
// If we got a retriable error (app handler returned a retriable error, or a network error while connecting to the app, etc) consume a retriable error token
|
||||
// We do it here, after the handler has been released but before removing the active message (which would allow us to retrieve more messages)
|
||||
if consumeToken {
|
||||
if s.logger.IsOutputLevelEnabled(logger.DebugLevel) {
|
||||
s.logger.Debugf("Taking a retriable error token")
|
||||
before := time.Now()
|
||||
_ = s.retriableErrLimiter.Take()
|
||||
s.logger.Debugf("Resumed after pausing for %v", time.Since(before))
|
||||
} else {
|
||||
_ = s.retriableErrLimiter.Take()
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke the handler to process the message.
|
||||
runHandlerFn(ctx)
|
||||
for _, msg := range msgs {
|
||||
// Remove the message from the map of active ones
|
||||
s.removeActiveMessage(msg.MessageID, *msg.SequenceNumber)
|
||||
}
|
||||
|
||||
// Remove an entry from activeOperationsChan to allow processing more messages
|
||||
<-s.activeOperationsChan
|
||||
}()
|
||||
|
||||
// If handleChan is non-nil, we have a limit on how many handler we can process
|
||||
// Note that in log messages we only log the message ID of the first one in a batch, if there are more than one
|
||||
if cap(s.handleChan) > 0 {
|
||||
s.logger.Debugf("Taking message handle for %s on %s", msgs[0].MessageID, s.entity)
|
||||
select {
|
||||
// Context is done, so we will stop waiting
|
||||
case <-ctx.Done():
|
||||
s.logger.Debugf("Message context done for %s on %s", msgs[0].MessageID, s.entity)
|
||||
return
|
||||
// Blocks until we have a handler available
|
||||
case s.handleChan <- struct{}{}:
|
||||
takenConcurrentHandler = true
|
||||
s.logger.Debugf("Taken message handle for %s on %s", msgs[0].MessageID, s.entity)
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke the handler to process the message.
|
||||
resps, err := handler(ctx, msgs)
|
||||
if err != nil {
|
||||
// Errors here are from the app, so consume a retriable error token
|
||||
consumeToken = true
|
||||
|
||||
// If we have a response with 0 items (or a nil response), it means the handler was a non-bulk one
|
||||
if len(resps) == 0 {
|
||||
// Log the error only, as we're running asynchronously
|
||||
s.logger.Errorf("App handler returned an error for message %s on %s: %s", msgs[0].MessageID, s.entity, err)
|
||||
finalizeCtx, finalizeCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
s.AbandonMessage(finalizeCtx, receiver, msgs[0])
|
||||
finalizeCancel()
|
||||
return
|
||||
}
|
||||
|
||||
// Handle the errors on bulk messages and mark messages accordingly.
|
||||
// Note, the order of the responses match the order of the messages.
|
||||
for i, resp := range resps {
|
||||
// This context is used for the calls to service bus to finalize (i.e. complete/abandon) the message.
|
||||
// If we fail to finalize the message, this message will eventually be reprocessed (at-least once delivery).
|
||||
// This uses a background context in case ctx has been canceled already.
|
||||
finalizeCtx, finalizeCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
if resp.Error != nil {
|
||||
// Log the error only, as we're running asynchronously.
|
||||
s.logger.Errorf("App handler returned an error for message %s on %s: %s", msgs[i].MessageID, s.entity, resp.Error)
|
||||
s.AbandonMessage(finalizeCtx, receiver, msgs[i])
|
||||
} else {
|
||||
s.CompleteMessage(finalizeCtx, receiver, msgs[i])
|
||||
}
|
||||
finalizeCancel()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// No error, so we can complete all messages.
|
||||
for _, msg := range msgs {
|
||||
finalizeCtx, finalizeCancel := context.WithTimeout(context.Background(), s.timeout)
|
||||
s.CompleteMessage(finalizeCtx, receiver, msg)
|
||||
finalizeCancel()
|
||||
}
|
||||
}
|
||||
|
||||
// AbandonMessage marks a messsage as abandoned.
|
||||
|
@ -451,13 +438,6 @@ func (s *Subscription) AbandonMessage(ctx context.Context, receiver Receiver, m
|
|||
// Log only
|
||||
s.logger.Warnf("Error abandoning message %s on %s: %s", m.MessageID, s.entity, err.Error())
|
||||
}
|
||||
|
||||
// If we're here, it means we got a retriable error, so we need to consume a retriable error token before this (synchronous) method returns
|
||||
// If there have been too many retriable errors per second, this method slows the consumer down
|
||||
s.logger.Debugf("Taking a retriable error token")
|
||||
before := time.Now()
|
||||
_ = s.retriableErrLimit.Take()
|
||||
s.logger.Debugf("Resumed after pausing for %v", time.Since(before))
|
||||
}
|
||||
|
||||
// CompleteMessage marks a message as complete.
|
||||
|
@ -482,7 +462,7 @@ func (s *Subscription) addActiveMessage(m *azservicebus.ReceivedMessage) error {
|
|||
if !s.requireSessions {
|
||||
s.logger.Warnf("Message %s with sequence number %d has a session ID but the subscription is not configured to require sessions", m.MessageID, *m.SequenceNumber)
|
||||
}
|
||||
logSuffix = fmt.Sprintf(" with session id %s", *m.SessionID)
|
||||
logSuffix = " with session id " + *m.SessionID
|
||||
}
|
||||
s.logger.Debugf("Adding message %s with sequence number %d to active messages on %s%s", m.MessageID, *m.SequenceNumber, s.entity, logSuffix)
|
||||
s.mu.Lock()
|
||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
|||
package servicebus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/kit/logger"
|
||||
|
@ -68,7 +67,7 @@ func TestNewSubscription(t *testing.T) {
|
|||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
sub := NewSubscription(
|
||||
context.Background(), SubsriptionOptions{
|
||||
SubscriptionOptions{
|
||||
MaxActiveMessages: 1000,
|
||||
TimeoutInSec: 1,
|
||||
MaxBulkSubCount: tc.maxBulkSubCountParam,
|
||||
|
|
|
@ -16,17 +16,13 @@ package queues
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
|
||||
impl "github.com/dapr/components-contrib/internal/component/azure/servicebus"
|
||||
"github.com/dapr/components-contrib/internal/utils"
|
||||
contribMetadata "github.com/dapr/components-contrib/metadata"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
"github.com/dapr/kit/logger"
|
||||
"github.com/dapr/kit/retry"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -38,14 +34,12 @@ type azureServiceBus struct {
|
|||
metadata *impl.Metadata
|
||||
client *impl.Client
|
||||
logger logger.Logger
|
||||
features []pubsub.Feature
|
||||
}
|
||||
|
||||
// NewAzureServiceBusQueues returns a new implementation.
|
||||
func NewAzureServiceBusQueues(logger logger.Logger) pubsub.PubSub {
|
||||
return &azureServiceBus{
|
||||
logger: logger,
|
||||
features: []pubsub.Feature{pubsub.FeatureMessageTTL},
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,118 +58,16 @@ func (a *azureServiceBus) Init(metadata pubsub.Metadata) (err error) {
|
|||
}
|
||||
|
||||
func (a *azureServiceBus) Publish(ctx context.Context, req *pubsub.PublishRequest) error {
|
||||
msg, err := impl.NewASBMessageFromPubsubRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ebo := backoff.NewExponentialBackOff()
|
||||
ebo.InitialInterval = time.Duration(a.metadata.PublishInitialRetryIntervalInMs) * time.Millisecond
|
||||
bo := backoff.WithMaxRetries(ebo, uint64(a.metadata.PublishMaxRetries))
|
||||
bo = backoff.WithContext(bo, ctx)
|
||||
|
||||
msgID := "nil"
|
||||
if msg.MessageID != nil {
|
||||
msgID = *msg.MessageID
|
||||
}
|
||||
return retry.NotifyRecover(
|
||||
func() (err error) {
|
||||
// Ensure the queue exists the first time it is referenced
|
||||
// This does nothing if DisableEntityManagement is true
|
||||
// Note that the parameter is called "Topic" but we're publishing to a queue
|
||||
err = a.client.EnsureQueue(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the sender
|
||||
var sender *servicebus.Sender
|
||||
sender, err = a.client.GetSender(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try sending the message
|
||||
publishCtx, publisCancel := context.WithTimeout(ctx, time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
err = sender.SendMessage(publishCtx, msg, nil)
|
||||
publisCancel()
|
||||
if err != nil {
|
||||
if impl.IsNetworkError(err) {
|
||||
// Retry after reconnecting
|
||||
a.client.CloseSender(req.Topic, a.logger)
|
||||
return err
|
||||
}
|
||||
|
||||
if impl.IsRetriableAMQPError(err) {
|
||||
// Retry (no need to reconnect)
|
||||
return err
|
||||
}
|
||||
|
||||
// Do not retry on other errors
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
bo,
|
||||
func(err error, _ time.Duration) {
|
||||
a.logger.Warnf("Could not publish service bus message (%s). Retrying...: %v", msgID, err)
|
||||
},
|
||||
func() {
|
||||
a.logger.Infof("Successfully published service bus message (%s) after it previously failed", msgID)
|
||||
},
|
||||
)
|
||||
return a.client.PublishPubSub(ctx, req, a.client.EnsureQueue, a.logger)
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) BulkPublish(ctx context.Context, req *pubsub.BulkPublishRequest) (pubsub.BulkPublishResponse, error) {
|
||||
// If the request is empty, sender.SendMessageBatch will panic later.
|
||||
// Return an empty response to avoid this.
|
||||
if len(req.Entries) == 0 {
|
||||
a.logger.Warnf("Empty bulk publish request, skipping")
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
}
|
||||
|
||||
// Ensure the queue exists the first time it is referenced
|
||||
// This does nothing if DisableEntityManagement is true
|
||||
// Note that the parameter is called "Topic" but we're publishing to a queue
|
||||
err := a.client.EnsureQueue(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Get the sender
|
||||
sender, err := a.client.GetSender(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Create a new batch of messages with batch options.
|
||||
batchOpts := &servicebus.MessageBatchOptions{
|
||||
MaxBytes: utils.GetElemOrDefaultFromMap(req.Metadata, contribMetadata.MaxBulkPubBytesKey, defaultMaxBulkPubBytes),
|
||||
}
|
||||
|
||||
batchMsg, err := sender.NewMessageBatch(ctx, batchOpts)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Add messages from the bulk publish request to the batch.
|
||||
err = impl.UpdateASBBatchMessageWithBulkPublishRequest(batchMsg, req)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Azure Service Bus does not return individual status for each message in the request.
|
||||
err = sender.SendMessageBatch(ctx, batchMsg, nil)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
return a.client.PublishPubSubBulk(ctx, req, a.client.EnsureQueue, a.logger)
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) Subscribe(subscribeCtx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
|
||||
func (a *azureServiceBus) Subscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
|
||||
sub := impl.NewSubscription(
|
||||
subscribeCtx, impl.SubsriptionOptions{
|
||||
impl.SubscriptionOptions{
|
||||
MaxActiveMessages: a.metadata.MaxActiveMessages,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
MaxBulkSubCount: nil,
|
||||
|
@ -188,24 +80,13 @@ func (a *azureServiceBus) Subscribe(subscribeCtx context.Context, req pubsub.Sub
|
|||
a.logger,
|
||||
)
|
||||
|
||||
receiveAndBlockFn := func(receiver impl.Receiver, onFirstSuccess func()) error {
|
||||
return sub.ReceiveBlocking(
|
||||
impl.GetPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second),
|
||||
receiver,
|
||||
onFirstSuccess,
|
||||
impl.ReceiveOptions{
|
||||
BulkEnabled: false, // Bulk is not supported in regular Subscribe.
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return a.doSubscribe(subscribeCtx, req, sub, receiveAndBlockFn)
|
||||
return a.doSubscribe(ctx, req, sub, impl.GetPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second))
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) BulkSubscribe(subscribeCtx context.Context, req pubsub.SubscribeRequest, handler pubsub.BulkHandler) error {
|
||||
func (a *azureServiceBus) BulkSubscribe(ctx context.Context, req pubsub.SubscribeRequest, handler pubsub.BulkHandler) error {
|
||||
maxBulkSubCount := utils.GetIntValOrDefault(req.BulkSubscribeConfig.MaxMessagesCount, defaultMaxBulkSubCount)
|
||||
sub := impl.NewSubscription(
|
||||
subscribeCtx, impl.SubsriptionOptions{
|
||||
impl.SubscriptionOptions{
|
||||
MaxActiveMessages: a.metadata.MaxActiveMessages,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
MaxBulkSubCount: &maxBulkSubCount,
|
||||
|
@ -218,80 +99,71 @@ func (a *azureServiceBus) BulkSubscribe(subscribeCtx context.Context, req pubsub
|
|||
a.logger,
|
||||
)
|
||||
|
||||
receiveAndBlockFn := func(receiver impl.Receiver, onFirstSuccess func()) error {
|
||||
return sub.ReceiveBlocking(
|
||||
impl.GetBulkPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second),
|
||||
receiver,
|
||||
onFirstSuccess,
|
||||
impl.ReceiveOptions{
|
||||
BulkEnabled: true, // Bulk is supported in BulkSubscribe.
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return a.doSubscribe(subscribeCtx, req, sub, receiveAndBlockFn)
|
||||
return a.doSubscribe(ctx, req, sub, impl.GetBulkPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second))
|
||||
}
|
||||
|
||||
// doSubscribe is a helper function that handles the common logic for both Subscribe and BulkSubscribe.
|
||||
// The receiveAndBlockFn is a function should invoke a blocking call to receive messages from the topic.
|
||||
func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
||||
req pubsub.SubscribeRequest, sub *impl.Subscription, receiveAndBlockFn func(impl.Receiver, func()) error,
|
||||
func (a *azureServiceBus) doSubscribe(
|
||||
ctx context.Context,
|
||||
req pubsub.SubscribeRequest,
|
||||
sub *impl.Subscription,
|
||||
handlerFn impl.HandlerFn,
|
||||
) error {
|
||||
// Does nothing if DisableEntityManagement is true
|
||||
err := a.client.EnsureQueue(subscribeCtx, req.Topic)
|
||||
err := a.client.EnsureQueue(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Reconnection backoff policy
|
||||
bo := backoff.NewExponentialBackOff()
|
||||
bo.MaxElapsedTime = 0
|
||||
bo.InitialInterval = time.Duration(a.metadata.MinConnectionRecoveryInSec) * time.Second
|
||||
bo.MaxInterval = time.Duration(a.metadata.MaxConnectionRecoveryInSec) * time.Second
|
||||
|
||||
onFirstSuccess := func() {
|
||||
// Reset the backoff when the subscription is successful and we have received the first message
|
||||
bo.Reset()
|
||||
}
|
||||
bo := a.client.ReconnectionBackoff()
|
||||
|
||||
go func() {
|
||||
logMsg := fmt.Sprintf("subscription %s to queue %s", a.metadata.ConsumerID, req.Topic)
|
||||
|
||||
// Reconnect loop.
|
||||
for {
|
||||
// Blocks until a successful connection (or until context is canceled)
|
||||
receiver, err := sub.Connect(func() (impl.Receiver, error) {
|
||||
receiver, err := a.client.GetClient().NewReceiverForQueue(req.Topic, nil)
|
||||
return &impl.MessageReceiver{Receiver: receiver}, err
|
||||
receiver, err := sub.Connect(ctx, func() (impl.Receiver, error) {
|
||||
a.logger.Debug("Connecting to " + logMsg)
|
||||
r, rErr := a.client.GetClient().NewReceiverForQueue(req.Topic, nil)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
return impl.NewMessageReceiver(r), nil
|
||||
})
|
||||
if err != nil {
|
||||
// Realistically, the only time we should get to this point is if the context was canceled, but let's log any other error we may get.
|
||||
if errors.Is(err, context.Canceled) {
|
||||
a.logger.Errorf("Could not instantiate subscription to queue %s", req.Topic)
|
||||
a.logger.Error("Could not instantiate subscription " + logMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// receiveAndBlockFn will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// ReceiveBlocking will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// If that occurs, we will log the error and attempt to re-establish the subscription connection until we exhaust the number of reconnect attempts.
|
||||
err = receiveAndBlockFn(receiver, onFirstSuccess)
|
||||
// Reset the backoff when the subscription is successful and we have received the first message
|
||||
err = sub.ReceiveBlocking(ctx, handlerFn, receiver, bo.Reset, logMsg)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
a.logger.Error(err)
|
||||
}
|
||||
|
||||
// Gracefully close the connection (in case it's not closed already)
|
||||
// Use a background context here (with timeout) because ctx may be closed already
|
||||
closeCtx, closeCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
sub.Close(closeCtx)
|
||||
closeCancel()
|
||||
|
||||
// If context was canceled, do not attempt to reconnect
|
||||
if subscribeCtx.Err() != nil {
|
||||
if ctx.Err() != nil {
|
||||
a.logger.Debug("Context canceled; will not reconnect")
|
||||
return
|
||||
}
|
||||
|
||||
wait := bo.NextBackOff()
|
||||
a.logger.Warnf("Subscription to topic %s lost connection, attempting to reconnect in %s...", req.Topic, wait)
|
||||
a.logger.Warnf("Subscription to queue %s lost connection, attempting to reconnect in %s...", req.Topic, wait)
|
||||
time.Sleep(wait)
|
||||
|
||||
// Check for context canceled again, after sleeping
|
||||
if ctx.Err() != nil {
|
||||
a.logger.Debug("Context canceled; will not reconnect")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -299,10 +171,12 @@ func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
|||
}
|
||||
|
||||
func (a *azureServiceBus) Close() (err error) {
|
||||
a.client.CloseAllSenders(a.logger)
|
||||
a.client.Close(a.logger)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) Features() []pubsub.Feature {
|
||||
return a.features
|
||||
return []pubsub.Feature{
|
||||
pubsub.FeatureMessageTTL,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,13 @@ package topics
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
|
||||
impl "github.com/dapr/components-contrib/internal/component/azure/servicebus"
|
||||
"github.com/dapr/components-contrib/internal/utils"
|
||||
contribMetadata "github.com/dapr/components-contrib/metadata"
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
"github.com/dapr/kit/logger"
|
||||
"github.com/dapr/kit/retry"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -38,14 +34,12 @@ type azureServiceBus struct {
|
|||
metadata *impl.Metadata
|
||||
client *impl.Client
|
||||
logger logger.Logger
|
||||
features []pubsub.Feature
|
||||
}
|
||||
|
||||
// NewAzureServiceBusTopics returns a new pub-sub implementation.
|
||||
func NewAzureServiceBusTopics(logger logger.Logger) pubsub.PubSub {
|
||||
return &azureServiceBus{
|
||||
logger: logger,
|
||||
features: []pubsub.Feature{pubsub.FeatureMessageTTL},
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,111 +58,11 @@ func (a *azureServiceBus) Init(metadata pubsub.Metadata) (err error) {
|
|||
}
|
||||
|
||||
func (a *azureServiceBus) Publish(ctx context.Context, req *pubsub.PublishRequest) error {
|
||||
msg, err := impl.NewASBMessageFromPubsubRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ebo := backoff.NewExponentialBackOff()
|
||||
ebo.InitialInterval = time.Duration(a.metadata.PublishInitialRetryIntervalInMs) * time.Millisecond
|
||||
bo := backoff.WithMaxRetries(ebo, uint64(a.metadata.PublishMaxRetries))
|
||||
bo = backoff.WithContext(bo, ctx)
|
||||
|
||||
msgID := "nil"
|
||||
if msg.MessageID != nil {
|
||||
msgID = *msg.MessageID
|
||||
}
|
||||
return retry.NotifyRecover(
|
||||
func() (err error) {
|
||||
// Ensure the queue or topic exists the first time it is referenced
|
||||
// This does nothing if DisableEntityManagement is true
|
||||
err = a.client.EnsureTopic(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the sender
|
||||
var sender *servicebus.Sender
|
||||
sender, err = a.client.GetSender(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try sending the message
|
||||
publishCtx, publishCancel := context.WithTimeout(ctx, time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
err = sender.SendMessage(publishCtx, msg, nil)
|
||||
publishCancel()
|
||||
if err != nil {
|
||||
if impl.IsNetworkError(err) {
|
||||
// Retry after reconnecting
|
||||
a.client.CloseSender(req.Topic, a.logger)
|
||||
return err
|
||||
}
|
||||
|
||||
if impl.IsRetriableAMQPError(err) {
|
||||
// Retry (no need to reconnect)
|
||||
return err
|
||||
}
|
||||
|
||||
// Do not retry on other errors
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
bo,
|
||||
func(err error, _ time.Duration) {
|
||||
a.logger.Warnf("Could not publish service bus message (%s). Retrying...: %v", msgID, err)
|
||||
},
|
||||
func() {
|
||||
a.logger.Infof("Successfully published service bus message (%s) after it previously failed", msgID)
|
||||
},
|
||||
)
|
||||
return a.client.PublishPubSub(ctx, req, a.client.EnsureTopic, a.logger)
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) BulkPublish(ctx context.Context, req *pubsub.BulkPublishRequest) (pubsub.BulkPublishResponse, error) {
|
||||
// If the request is empty, sender.SendMessageBatch will panic later.
|
||||
// Return an empty response to avoid this.
|
||||
if len(req.Entries) == 0 {
|
||||
a.logger.Warnf("Empty bulk publish request, skipping")
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
}
|
||||
|
||||
// Ensure the queue or topic exists the first time it is referenced
|
||||
// This does nothing if DisableEntityManagement is true
|
||||
err := a.client.EnsureTopic(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Get the sender
|
||||
sender, err := a.client.GetSender(ctx, req.Topic)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Create a new batch of messages with batch options.
|
||||
batchOpts := &servicebus.MessageBatchOptions{
|
||||
MaxBytes: utils.GetElemOrDefaultFromMap(req.Metadata, contribMetadata.MaxBulkPubBytesKey, defaultMaxBulkPubBytes),
|
||||
}
|
||||
|
||||
batchMsg, err := sender.NewMessageBatch(ctx, batchOpts)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Add messages from the bulk publish request to the batch.
|
||||
err = impl.UpdateASBBatchMessageWithBulkPublishRequest(batchMsg, req)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
// Azure Service Bus does not return individual status for each message in the request.
|
||||
err = sender.SendMessageBatch(ctx, batchMsg, nil)
|
||||
if err != nil {
|
||||
return pubsub.NewBulkPublishResponse(req.Entries, err), err
|
||||
}
|
||||
|
||||
return pubsub.BulkPublishResponse{}, nil
|
||||
return a.client.PublishPubSubBulk(ctx, req, a.client.EnsureTopic, a.logger)
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) Subscribe(subscribeCtx context.Context, req pubsub.SubscribeRequest, handler pubsub.Handler) error {
|
||||
|
@ -177,7 +71,7 @@ func (a *azureServiceBus) Subscribe(subscribeCtx context.Context, req pubsub.Sub
|
|||
maxConcurrentSessions := utils.GetElemOrDefaultFromMap(req.Metadata, impl.MaxConcurrentSessionsMetadataKey, impl.DefaultMaxConcurrentSessions)
|
||||
|
||||
sub := impl.NewSubscription(
|
||||
subscribeCtx, impl.SubsriptionOptions{
|
||||
impl.SubscriptionOptions{
|
||||
MaxActiveMessages: a.metadata.MaxActiveMessages,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
MaxBulkSubCount: nil,
|
||||
|
@ -186,23 +80,13 @@ func (a *azureServiceBus) Subscribe(subscribeCtx context.Context, req pubsub.Sub
|
|||
Entity: "topic " + req.Topic,
|
||||
LockRenewalInSec: a.metadata.LockRenewalInSec,
|
||||
RequireSessions: requireSessions,
|
||||
SessionIdleTimeout: sessionIdleTimeout,
|
||||
},
|
||||
a.logger,
|
||||
)
|
||||
|
||||
receiveAndBlockFn := func(receiver impl.Receiver, onFirstSuccess func()) error {
|
||||
return sub.ReceiveBlocking(
|
||||
impl.GetPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second),
|
||||
receiver,
|
||||
onFirstSuccess,
|
||||
impl.ReceiveOptions{
|
||||
BulkEnabled: false, // Bulk is not supported in regular Subscribe.
|
||||
SessionIdleTimeout: sessionIdleTimeout,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return a.doSubscribe(subscribeCtx, req, sub, receiveAndBlockFn, impl.SubscribeOptions{
|
||||
handlerFn := impl.GetPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second)
|
||||
return a.doSubscribe(subscribeCtx, req, sub, handlerFn, impl.SubscribeOptions{
|
||||
RequireSessions: requireSessions,
|
||||
MaxConcurrentSesions: maxConcurrentSessions,
|
||||
})
|
||||
|
@ -215,7 +99,7 @@ func (a *azureServiceBus) BulkSubscribe(subscribeCtx context.Context, req pubsub
|
|||
|
||||
maxBulkSubCount := utils.GetIntValOrDefault(req.BulkSubscribeConfig.MaxMessagesCount, defaultMaxBulkSubCount)
|
||||
sub := impl.NewSubscription(
|
||||
subscribeCtx, impl.SubsriptionOptions{
|
||||
impl.SubscriptionOptions{
|
||||
MaxActiveMessages: a.metadata.MaxActiveMessages,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
MaxBulkSubCount: &maxBulkSubCount,
|
||||
|
@ -224,23 +108,13 @@ func (a *azureServiceBus) BulkSubscribe(subscribeCtx context.Context, req pubsub
|
|||
Entity: "topic " + req.Topic,
|
||||
LockRenewalInSec: a.metadata.LockRenewalInSec,
|
||||
RequireSessions: requireSessions,
|
||||
SessionIdleTimeout: sessionIdleTimeout,
|
||||
},
|
||||
a.logger,
|
||||
)
|
||||
|
||||
receiveAndBlockFn := func(receiver impl.Receiver, onFirstSuccess func()) error {
|
||||
return sub.ReceiveBlocking(
|
||||
impl.GetBulkPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second),
|
||||
receiver,
|
||||
onFirstSuccess,
|
||||
impl.ReceiveOptions{
|
||||
BulkEnabled: true, // Bulk is supported in BulkSubscribe.
|
||||
SessionIdleTimeout: sessionIdleTimeout,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return a.doSubscribe(subscribeCtx, req, sub, receiveAndBlockFn, impl.SubscribeOptions{
|
||||
handlerFn := impl.GetBulkPubSubHandlerFunc(req.Topic, handler, a.logger, time.Duration(a.metadata.HandlerTimeoutInSec)*time.Second)
|
||||
return a.doSubscribe(subscribeCtx, req, sub, handlerFn, impl.SubscribeOptions{
|
||||
RequireSessions: requireSessions,
|
||||
MaxConcurrentSesions: maxConcurrentSessions,
|
||||
})
|
||||
|
@ -248,8 +122,12 @@ func (a *azureServiceBus) BulkSubscribe(subscribeCtx context.Context, req pubsub
|
|||
|
||||
// doSubscribe is a helper function that handles the common logic for both Subscribe and BulkSubscribe.
|
||||
// The receiveAndBlockFn is a function should invoke a blocking call to receive messages from the topic.
|
||||
func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
||||
req pubsub.SubscribeRequest, sub *impl.Subscription, receiveAndBlockFn func(impl.Receiver, func()) error, opts impl.SubscribeOptions,
|
||||
func (a *azureServiceBus) doSubscribe(
|
||||
subscribeCtx context.Context,
|
||||
req pubsub.SubscribeRequest,
|
||||
sub *impl.Subscription,
|
||||
handlerFn impl.HandlerFn,
|
||||
opts impl.SubscribeOptions,
|
||||
) error {
|
||||
// Does nothing if DisableEntityManagement is true
|
||||
err := a.client.EnsureSubscription(subscribeCtx, a.metadata.ConsumerID, req.Topic, opts)
|
||||
|
@ -258,23 +136,16 @@ func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
|||
}
|
||||
|
||||
// Reconnection backoff policy
|
||||
bo := backoff.NewExponentialBackOff()
|
||||
bo.MaxElapsedTime = 0
|
||||
bo.InitialInterval = time.Duration(a.metadata.MinConnectionRecoveryInSec) * time.Second
|
||||
bo.MaxInterval = time.Duration(a.metadata.MaxConnectionRecoveryInSec) * time.Second
|
||||
|
||||
onFirstSuccess := func() {
|
||||
// Reset the backoff when the subscription is successful and we have received the first message
|
||||
bo.Reset()
|
||||
}
|
||||
bo := a.client.ReconnectionBackoff()
|
||||
|
||||
go func() {
|
||||
// Reconnect loop.
|
||||
for {
|
||||
// Reset the backoff when the subscription is successful and we have received the first message
|
||||
if opts.RequireSessions {
|
||||
a.ConnectAndReceiveWithSessions(subscribeCtx, req, sub, receiveAndBlockFn, onFirstSuccess, opts.MaxConcurrentSesions)
|
||||
a.connectAndReceiveWithSessions(subscribeCtx, req, sub, handlerFn, bo.Reset, opts.MaxConcurrentSesions)
|
||||
} else {
|
||||
a.ConnectAndReceive(subscribeCtx, req, sub, receiveAndBlockFn, onFirstSuccess)
|
||||
a.connectAndReceive(subscribeCtx, req, sub, handlerFn, bo.Reset)
|
||||
}
|
||||
|
||||
// If context was canceled, do not attempt to reconnect
|
||||
|
@ -286,6 +157,12 @@ func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
|||
wait := bo.NextBackOff()
|
||||
a.logger.Warnf("Subscription to topic %s lost connection, attempting to reconnect in %s...", req.Topic, wait)
|
||||
time.Sleep(wait)
|
||||
|
||||
// Check for context canceled again, after sleeping
|
||||
if subscribeCtx.Err() != nil {
|
||||
a.logger.Debug("Context canceled; will not reconnect")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -293,162 +170,102 @@ func (a *azureServiceBus) doSubscribe(subscribeCtx context.Context,
|
|||
}
|
||||
|
||||
func (a *azureServiceBus) Close() (err error) {
|
||||
a.client.CloseAllSenders(a.logger)
|
||||
a.client.Close(a.logger)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) Features() []pubsub.Feature {
|
||||
return a.features
|
||||
return []pubsub.Feature{
|
||||
pubsub.FeatureMessageTTL,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) ConnectAndReceive(subscribeCtx context.Context, req pubsub.SubscribeRequest, sub *impl.Subscription, receiveAndBlockFn func(impl.Receiver, func()) error, onFirstSuccess func()) error {
|
||||
defer func() {
|
||||
// Gracefully close the connection (in case it's not closed already)
|
||||
// Use a background context here (with timeout) because ctx may be closed already.
|
||||
closeSubCtx, closeSubCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
sub.Close(closeSubCtx)
|
||||
closeSubCancel()
|
||||
}()
|
||||
func (a *azureServiceBus) connectAndReceive(ctx context.Context, req pubsub.SubscribeRequest, sub *impl.Subscription, handlerFn impl.HandlerFn, onFirstSuccess func()) {
|
||||
logMsg := fmt.Sprintf("subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
|
||||
// Blocks until a successful connection (or until context is canceled)
|
||||
receiver, err := sub.Connect(func() (impl.Receiver, error) {
|
||||
a.logger.Debugf("Connecting to subscription %s for topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
r, err := a.client.GetClient().NewReceiverForSubscription(req.Topic, a.metadata.ConsumerID, nil)
|
||||
return impl.NewMessageReceiver(r), err
|
||||
receiver, err := sub.Connect(ctx, func() (impl.Receiver, error) {
|
||||
a.logger.Debug("Connecting to " + logMsg)
|
||||
r, rErr := a.client.GetClient().NewReceiverForSubscription(req.Topic, a.metadata.ConsumerID, nil)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
return impl.NewMessageReceiver(r), nil
|
||||
})
|
||||
if err != nil {
|
||||
// Realistically, the only time we should get to this point is if the context was canceled, but let's log any other error we may get.
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
a.logger.Errorf("Could not instantiate session subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
a.logger.Error("Could not instantiate " + logMsg)
|
||||
}
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
lockCtx, lockCancel := context.WithCancel(subscribeCtx)
|
||||
defer func() {
|
||||
// Cancel the lock renewal loop
|
||||
lockCancel()
|
||||
a.logger.Debug("Receiving messages for " + logMsg)
|
||||
|
||||
// Close the receiver
|
||||
a.logger.Debugf("Closing message receiver for subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
closeReceiverCtx, closeReceiverCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
receiver.Close(closeReceiverCtx)
|
||||
closeReceiverCancel()
|
||||
}()
|
||||
|
||||
// lock renewal loop
|
||||
go func() {
|
||||
a.logger.Debugf("Renewing locks for subscription %s for topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
lockErr := sub.RenewLocksBlocking(lockCtx, receiver, impl.LockRenewalOptions{
|
||||
RenewalInSec: a.metadata.LockRenewalInSec,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
})
|
||||
if lockErr != nil {
|
||||
if !errors.Is(lockErr, context.Canceled) {
|
||||
a.logger.Error(lockErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
a.logger.Debugf("Receiving messages for subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
|
||||
// receiveAndBlockFn will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// ReceiveBlocking will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// If that occurs, we will log the error and attempt to re-establish the subscription connection until we exhaust the number of reconnect attempts.
|
||||
if err := receiveAndBlockFn(receiver, onFirstSuccess); err != nil {
|
||||
return err
|
||||
err = sub.ReceiveBlocking(ctx, handlerFn, receiver, onFirstSuccess, logMsg)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
a.logger.Error(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *azureServiceBus) ConnectAndReceiveWithSessions(subscribeCtx context.Context, req pubsub.SubscribeRequest, sub *impl.Subscription, receiveAndBlockFn func(impl.Receiver, func()) error, onFirstSuccess func(), maxConcurrentSessions int) {
|
||||
func (a *azureServiceBus) connectAndReceiveWithSessions(ctx context.Context, req pubsub.SubscribeRequest, sub *impl.Subscription, handlerFn impl.HandlerFn, onFirstSuccess func(), maxConcurrentSessions int) {
|
||||
sessionsChan := make(chan struct{}, maxConcurrentSessions)
|
||||
for i := 0; i < maxConcurrentSessions; i++ {
|
||||
sessionsChan <- struct{}{}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// Gracefully close the connection (in case it's not closed already)
|
||||
// Use a background context here (with timeout) because ctx may be closed already
|
||||
closeSubCtx, closeSubCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
sub.Close(closeSubCtx)
|
||||
closeSubCancel()
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-subscribeCtx.Done():
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-sessionsChan:
|
||||
select {
|
||||
case <-subscribeCtx.Done():
|
||||
return
|
||||
default:
|
||||
func() { // IIFE to scope context cancellation
|
||||
acceptCtx, acceptCancel := context.WithCancel(subscribeCtx)
|
||||
defer acceptCancel()
|
||||
|
||||
var sessionID string
|
||||
|
||||
// Blocks until a successful connection (or until context is canceled)
|
||||
receiver, err := sub.Connect(func() (impl.Receiver, error) {
|
||||
a.logger.Debugf("Accepting next available session subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
r, err := a.client.GetClient().AcceptNextSessionForSubscription(acceptCtx, req.Topic, a.metadata.ConsumerID, nil)
|
||||
if err == nil && r != nil {
|
||||
sessionID = r.SessionID()
|
||||
}
|
||||
return impl.NewSessionReceiver(r), err
|
||||
})
|
||||
if err != nil {
|
||||
// Realistically, the only time we should get to this point is if the context was canceled, but let's log any other error we may get.
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
a.logger.Errorf("Could not instantiate session subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
lockCtx, lockCancel := context.WithCancel(subscribeCtx)
|
||||
defer func() {
|
||||
// cancel the lock renewal loop
|
||||
lockCancel()
|
||||
|
||||
// close the receiver
|
||||
a.logger.Debugf("Closing session %s receiver for subscription %s to topic %s", sessionID, a.metadata.ConsumerID, req.Topic)
|
||||
closeReceiverCtx, closeReceiverCancel := context.WithTimeout(context.Background(), time.Second*time.Duration(a.metadata.TimeoutInSec))
|
||||
receiver.Close(closeReceiverCtx)
|
||||
closeReceiverCancel()
|
||||
|
||||
// return the session to the pool
|
||||
a.logger.Debugf("Returning session to pool")
|
||||
sessionsChan <- struct{}{}
|
||||
}()
|
||||
|
||||
// lock renewal loop
|
||||
go func() {
|
||||
a.logger.Debugf("Renewing locks for session %s receiver for subscription %s to topic %s", sessionID, a.metadata.ConsumerID, req.Topic)
|
||||
lockErr := sub.RenewLocksBlocking(lockCtx, receiver, impl.LockRenewalOptions{
|
||||
RenewalInSec: a.metadata.LockRenewalInSec,
|
||||
TimeoutInSec: a.metadata.TimeoutInSec,
|
||||
})
|
||||
if lockErr != nil {
|
||||
if !errors.Is(lockErr, context.Canceled) {
|
||||
a.logger.Error(lockErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
a.logger.Debugf("Receiving messages for session %s receiver for subscription %s to topic %s", sessionID, a.metadata.ConsumerID, req.Topic)
|
||||
|
||||
// receiveAndBlockFn will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// If that occurs, we will log the error and attempt to re-establish the subscription connection until we exhaust the number of reconnect attempts.
|
||||
err = receiveAndBlockFn(receiver, onFirstSuccess)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
a.logger.Error(err)
|
||||
}
|
||||
}() // end session receive goroutine
|
||||
}()
|
||||
}
|
||||
// nop - continue
|
||||
}
|
||||
|
||||
// Check again if the context was canceled
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
acceptCtx, acceptCancel := context.WithCancel(ctx)
|
||||
|
||||
// Blocks until a successful connection (or until context is canceled)
|
||||
receiver, err := sub.Connect(ctx, func() (impl.Receiver, error) {
|
||||
a.logger.Debugf("Accepting next available session subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
r, rErr := a.client.GetClient().AcceptNextSessionForSubscription(acceptCtx, req.Topic, a.metadata.ConsumerID, nil)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
return impl.NewSessionReceiver(r), nil
|
||||
})
|
||||
acceptCancel()
|
||||
if err != nil {
|
||||
// Realistically, the only time we should get to this point is if the context was canceled, but let's log any other error we may get.
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
a.logger.Errorf("Could not instantiate session subscription %s to topic %s", a.metadata.ConsumerID, req.Topic)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Receive messages for the session in a goroutine
|
||||
go func() {
|
||||
logMsg := fmt.Sprintf("session %s for subscription %s to topic %s", receiver.(*impl.SessionReceiver).SessionID(), a.metadata.ConsumerID, req.Topic)
|
||||
|
||||
defer func() {
|
||||
// Return the session to the pool
|
||||
sessionsChan <- struct{}{}
|
||||
}()
|
||||
|
||||
a.logger.Debug("Receiving messages for " + logMsg)
|
||||
|
||||
// ReceiveBlocking will only return with an error that it cannot handle internally. The subscription connection is closed when this method returns.
|
||||
// If that occurs, we will log the error and attempt to re-establish the subscription connection until we exhaust the number of reconnect attempts.
|
||||
err = sub.ReceiveBlocking(ctx, handlerFn, receiver, onFirstSuccess, logMsg)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
a.logger.Error(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
@ -29,7 +29,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1 h1:YvQv9Mz6T8oR5ypQOL6erY0Z5t71ak1uHV4QFokCOZk=
|
||||
|
@ -71,8 +71,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -19,8 +19,8 @@ require (
|
|||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
|
@ -32,7 +32,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -42,10 +42,10 @@ github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVt
|
|||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3 h1:x1shk+tVZ6kLwIQMn4r+pdz8szo3mA0jd8STmgh+aRk=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3/go.mod h1:Fy3bbChFm4cZn6oIxYYqKB2FG3rBDxk3NZDLDJCHl+Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
|
@ -73,8 +73,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -18,8 +18,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0 // indirect
|
||||
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0 h1:X/ePaAG8guM7j5WORT5eEIw7cGUxe9Ah1jEQJKLmmSo=
|
||||
|
@ -75,8 +75,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -17,10 +17,10 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
github.com/Azure/go-amqp v0.18.1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
@ -31,7 +31,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
|
|
|
@ -40,14 +40,14 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4 h1:kaZamwZwmUqnECvnPkf1LBRBIFYYCy3E0gKHn/UFSD0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4/go.mod h1:uDLwkzCJMvTrHsvtiVFeAp85hi3W77zvs61wrpc+6ho=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0 h1:2BE/tjVTT4SNWwI3dWiMqX9mt0cImxYoJIXtFeJ72t4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0/go.mod h1:R6+0udeRV8iYSTVuT5RT7If4sc46K5Bz3ZKrmvZQF7U=
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
|
||||
github.com/Azure/go-amqp v0.18.1 h1:D5Ca+uijuTcj5g76sF+zT4OQZcFFY397+IGf/5Ip5Sc=
|
||||
|
@ -73,8 +73,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -17,8 +17,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
@ -29,7 +29,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
|
||||
|
@ -69,8 +69,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -18,8 +18,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0 // indirect
|
||||
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v0.4.0 h1:X/ePaAG8guM7j5WORT5eEIw7cGUxe9Ah1jEQJKLmmSo=
|
||||
|
@ -75,8 +75,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -18,10 +18,10 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
github.com/Azure/go-amqp v0.18.1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
@ -32,7 +32,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
|
|
|
@ -40,14 +40,14 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4 h1:kaZamwZwmUqnECvnPkf1LBRBIFYYCy3E0gKHn/UFSD0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.1.4/go.mod h1:uDLwkzCJMvTrHsvtiVFeAp85hi3W77zvs61wrpc+6ho=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0 h1:2BE/tjVTT4SNWwI3dWiMqX9mt0cImxYoJIXtFeJ72t4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0/go.mod h1:R6+0udeRV8iYSTVuT5RT7If4sc46K5Bz3ZKrmvZQF7U=
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
|
||||
github.com/Azure/go-amqp v0.18.1 h1:D5Ca+uijuTcj5g76sF+zT4OQZcFFY397+IGf/5Ip5Sc=
|
||||
|
@ -73,8 +73,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -1355,6 +1355,7 @@ func TestServicebusWithSessionsRoundRobin(t *testing.T) {
|
|||
|
||||
func componentRuntimeOptions() []runtime.Option {
|
||||
log := logger.NewLogger("dapr.components")
|
||||
log.SetOutputLevel(logger.DebugLevel)
|
||||
|
||||
pubsubRegistry := pubsub_loader.NewRegistry()
|
||||
pubsubRegistry.Logger = log
|
||||
|
|
|
@ -16,8 +16,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect
|
||||
|
@ -30,7 +30,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0 h1:82w8tzLcOwDP/Q35j/wEBPt0n0kVC3cjtPdD62G8UAk=
|
||||
|
@ -73,8 +73,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -16,8 +16,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
|
@ -29,7 +29,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.6.1 h1:YvQv9Mz6T8oR5ypQOL6erY0Z5t71ak1uHV4QFokCOZk=
|
||||
|
@ -71,8 +71,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -17,8 +17,8 @@ require (
|
|||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
|
@ -30,7 +30,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -42,10 +42,10 @@ github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVt
|
|||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3 h1:x1shk+tVZ6kLwIQMn4r+pdz8szo3mA0jd8STmgh+aRk=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v0.3.3/go.mod h1:Fy3bbChFm4cZn6oIxYYqKB2FG3rBDxk3NZDLDJCHl+Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
|
@ -73,8 +73,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
|
@ -16,8 +16,8 @@ require (
|
|||
github.com/AdhityaRamadhanus/fasthttpcors v0.0.0-20170121111917-d4c07198763a // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.0.0 // indirect
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 // indirect
|
||||
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd // indirect
|
||||
|
@ -29,7 +29,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
|
||||
|
|
|
@ -40,10 +40,10 @@ github.com/Azure/azure-amqp-common-go/v4 v4.0.0/go.mod h1:4+qRvizIo4+CbGG552O6a8
|
|||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
|
||||
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1 h1:gVXuXcWd1i4C2Ruxe321aU+IKGaStvGB/S90PUPB/W8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1 h1:bFa9IcjvrCber6gGgDAUZ+I2bO8J7s8JxXmu9fhi2ss=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1/go.mod h1:l3wvZkG9oW07GLBW5Cd0WwG5asOfJ8aqE8raUvNzLpk=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2 h1:+5VZ72z0Qan5Bog5C+ZkgSqUbeVUd9wgtHOrIKuc5b8=
|
||||
|
@ -71,8 +71,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
|
|
Loading…
Reference in New Issue