github.com/Jeffail/benthos/v3@v3.65.0/lib/output/writer/azure_queue_storage.go (about) 1 //go:build !wasm 2 // +build !wasm 3 4 package writer 5 6 import ( 7 "context" 8 "fmt" 9 "time" 10 11 "github.com/Azure/azure-storage-queue-go/azqueue" 12 "github.com/Jeffail/benthos/v3/internal/bloblang/field" 13 "github.com/Jeffail/benthos/v3/internal/impl/azure" 14 "github.com/Jeffail/benthos/v3/internal/interop" 15 "github.com/Jeffail/benthos/v3/lib/log" 16 "github.com/Jeffail/benthos/v3/lib/metrics" 17 "github.com/Jeffail/benthos/v3/lib/types" 18 ) 19 20 // AzureQueueStorage is a benthos writer.Type implementation that writes messages to an 21 // Azure Queue Storage queue. 22 type AzureQueueStorage struct { 23 conf AzureQueueStorageConfig 24 25 queueName *field.Expression 26 ttl *field.Expression 27 serviceURL *azqueue.ServiceURL 28 29 log log.Modular 30 stats metrics.Type 31 } 32 33 // NewAzureQueueStorage creates a new Azure Queue Storage writer type. 34 // 35 // Deprecated: use the V2 API instead. 36 func NewAzureQueueStorage( 37 conf AzureQueueStorageConfig, 38 log log.Modular, 39 stats metrics.Type, 40 ) (*AzureQueueStorage, error) { 41 return NewAzureQueueStorageV2(conf, types.NoopMgr(), log, stats) 42 } 43 44 // NewAzureQueueStorageV2 creates a new Azure Queue Storage writer type. 45 func NewAzureQueueStorageV2( 46 conf AzureQueueStorageConfig, 47 mgr types.Manager, 48 log log.Modular, 49 stats metrics.Type, 50 ) (*AzureQueueStorage, error) { 51 serviceURL, err := azure.GetQueueServiceURL(conf.StorageAccount, conf.StorageAccessKey, conf.StorageConnectionString) 52 if err != nil { 53 return nil, err 54 } 55 s := &AzureQueueStorage{ 56 conf: conf, 57 log: log, 58 stats: stats, 59 serviceURL: serviceURL, 60 } 61 62 if s.ttl, err = interop.NewBloblangField(mgr, conf.TTL); err != nil { 63 return nil, fmt.Errorf("failed to parse ttl expression: %v", err) 64 } 65 66 if s.queueName, err = interop.NewBloblangField(mgr, conf.QueueName); err != nil { 67 return nil, fmt.Errorf("failed to parse queue name expression: %v", err) 68 } 69 70 return s, nil 71 } 72 73 // ConnectWithContext attempts to establish a connection to the target 74 // queue. 75 func (a *AzureQueueStorage) ConnectWithContext(ctx context.Context) error { 76 return nil 77 } 78 79 // Connect attempts to establish a connection to the target 80 func (a *AzureQueueStorage) Connect() error { 81 return nil 82 } 83 84 // Write attempts to write message contents to a target Azure Queue Storage queue. 85 func (a *AzureQueueStorage) Write(msg types.Message) error { 86 return a.WriteWithContext(context.Background(), msg) 87 } 88 89 // WriteWithContext attempts to write message contents to a target Queue Storage 90 func (a *AzureQueueStorage) WriteWithContext(ctx context.Context, msg types.Message) error { 91 return IterateBatchedSend(msg, func(i int, p types.Part) error { 92 queueURL := a.serviceURL.NewQueueURL(a.queueName.String(i, msg)) 93 msgURL := queueURL.NewMessagesURL() 94 var ttl *time.Duration 95 if ttls := a.ttl.String(i, msg); ttls != "" { 96 td, err := time.ParseDuration(ttls) 97 if err != nil { 98 a.log.Debugf("TTL must be a duration: %v\n", err) 99 return err 100 } 101 ttl = &td 102 } 103 timeToLive := func() time.Duration { 104 if ttl != nil { 105 return *ttl 106 } 107 return 0 108 }() 109 message := string(p.Get()) 110 _, err := msgURL.Enqueue(ctx, message, 0, timeToLive) 111 if err != nil { 112 if cerr, ok := err.(azqueue.StorageError); ok { 113 if cerr.ServiceCode() == azqueue.ServiceCodeQueueNotFound { 114 ctx := context.Background() 115 _, err = queueURL.Create(ctx, azqueue.Metadata{}) 116 if err != nil { 117 return fmt.Errorf("error creating queue: %v", err) 118 } 119 _, err := msgURL.Enqueue(ctx, message, 0, 0) 120 if err != nil { 121 return fmt.Errorf("error retrying to enqueue message: %v", err) 122 } 123 } else { 124 return fmt.Errorf("storage error message: %v", err) 125 } 126 } else { 127 return fmt.Errorf("error enqueuing message: %v", err) 128 } 129 } 130 return nil 131 }) 132 } 133 134 // CloseAsync begins cleaning up resources used by this reader asynchronously. 135 func (a *AzureQueueStorage) CloseAsync() { 136 } 137 138 // WaitForClose will block until either the reader is closed or a specified 139 // timeout occurs. 140 func (a *AzureQueueStorage) WaitForClose(time.Duration) error { 141 return nil 142 } 143 144 //------------------------------------------------------------------------------