[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:
Alessandro (Ale) Segala 2023-02-13 17:23:03 +00:00 committed by GitHub
parent 9dfe2f40bd
commit 12acf8effe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 746 additions and 854 deletions

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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()

View File

@ -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,

View File

@ -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,
}
}

View File

@ -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)
}
}()
}
}

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=

View File

@ -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

View File

@ -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=