diff --git a/weed/remote_storage/azure/azure_storage_client.go b/weed/remote_storage/azure/azure_storage_client.go index 90a11d13e..2dff07d3e 100644 --- a/weed/remote_storage/azure/azure_storage_client.go +++ b/weed/remote_storage/azure/azure_storage_client.go @@ -30,6 +30,23 @@ const ( defaultConcurrency = 16 ) +// DefaultAzBlobClientOptions returns the default Azure blob client options +// with consistent retry configuration across the application. +// This centralizes the retry policy to ensure uniform behavior between +// remote storage and replication sink implementations. +func DefaultAzBlobClientOptions() *azblob.ClientOptions { + return &azblob.ClientOptions{ + ClientOptions: azcore.ClientOptions{ + Retry: policy.RetryOptions{ + MaxRetries: 3, // Reasonable retry count - aggressive retries mask configuration errors + TryTimeout: 10 * time.Second, // Reduced from 1 minute to fail faster on auth issues + RetryDelay: 1 * time.Second, + MaxRetryDelay: 10 * time.Second, + }, + }, + } +} + // invalidMetadataChars matches any character that is not valid in Azure metadata keys. // Azure metadata keys must be valid C# identifiers: letters, digits, and underscores only. var invalidMetadataChars = regexp.MustCompile(`[^a-zA-Z0-9_]`) @@ -86,16 +103,7 @@ func (s azureRemoteStorageMaker) Make(conf *remote_pb.RemoteConf) (remote_storag } serviceURL := fmt.Sprintf("https://%s.blob.core.windows.net/", accountName) - azClient, err := azblob.NewClientWithSharedKeyCredential(serviceURL, credential, &azblob.ClientOptions{ - ClientOptions: azcore.ClientOptions{ - Retry: policy.RetryOptions{ - MaxRetries: 3, // Reasonable retry count - aggressive retries mask configuration errors - TryTimeout: 10 * time.Second, // Reduced from 1 minute to fail faster on auth issues - RetryDelay: 1 * time.Second, - MaxRetryDelay: 10 * time.Second, - }, - }, - }) + azClient, err := azblob.NewClientWithSharedKeyCredential(serviceURL, credential, DefaultAzBlobClientOptions()) if err != nil { return nil, fmt.Errorf("failed to create Azure client: %w", err) } diff --git a/weed/replication/sink/azuresink/azure_sink.go b/weed/replication/sink/azuresink/azure_sink.go index 282f29033..adedeabe0 100644 --- a/weed/replication/sink/azuresink/azure_sink.go +++ b/weed/replication/sink/azuresink/azure_sink.go @@ -5,10 +5,7 @@ import ( "context" "fmt" "strings" - "time" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" @@ -18,6 +15,7 @@ import ( "github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" + "github.com/seaweedfs/seaweedfs/weed/remote_storage/azure" "github.com/seaweedfs/seaweedfs/weed/replication/repl_util" "github.com/seaweedfs/seaweedfs/weed/replication/sink" "github.com/seaweedfs/seaweedfs/weed/replication/source" @@ -73,16 +71,7 @@ func (g *AzureSink) initialize(accountName, accountKey, container, dir string) e } serviceURL := fmt.Sprintf("https://%s.blob.core.windows.net/", accountName) - client, err := azblob.NewClientWithSharedKeyCredential(serviceURL, credential, &azblob.ClientOptions{ - ClientOptions: azcore.ClientOptions{ - Retry: policy.RetryOptions{ - MaxRetries: 3, // Reasonable retry count - aggressive retries mask configuration errors - TryTimeout: 10 * time.Second, // Reduced from 1 minute to fail faster on auth issues - RetryDelay: 1 * time.Second, - MaxRetryDelay: 10 * time.Second, - }, - }, - }) + client, err := azblob.NewClientWithSharedKeyCredential(serviceURL, credential, azure.DefaultAzBlobClientOptions()) if err != nil { return fmt.Errorf("failed to create Azure client: %w", err) }