1
+ using Azure . Storage . Blobs ;
2
+ using Azure . Storage . Blobs . Models ;
3
+ using Imazen . Common . Concurrency ;
4
+ using Microsoft . Extensions . Logging ;
5
+ using System ;
6
+ using System . Collections . Generic ;
7
+ using System . Linq ;
8
+ using System . Threading . Tasks ;
9
+ using Imazen . Abstractions . Logging ;
10
+ using Imazen . Abstractions . Resulting ;
11
+
12
+ namespace Imageflow . Server . Storage . AzureBlob . Caching
13
+ {
14
+ internal class LifecycleRuleUpdater
15
+ {
16
+ private readonly NamedCacheConfiguration config ;
17
+ private readonly IReLogger logger ;
18
+ private readonly BlobServiceClient defaultClient ;
19
+ private readonly BasicAsyncLock updateLock = new BasicAsyncLock ( ) ;
20
+ private bool updateComplete = false ;
21
+
22
+ public LifecycleRuleUpdater ( NamedCacheConfiguration config , BlobServiceClient defaultClient , IReLogger logger )
23
+ {
24
+ this . config = config ;
25
+ this . logger = logger . WithSubcategory ( nameof ( LifecycleRuleUpdater ) ) ;
26
+ this . defaultClient = defaultClient ;
27
+ }
28
+
29
+ internal async Task UpdateIfIncompleteAsync ( )
30
+ {
31
+ if ( updateComplete ) return ;
32
+
33
+ using ( await updateLock . LockAsync ( ) )
34
+ {
35
+ if ( updateComplete ) return ;
36
+ await CreateContainersAsync ( ) ;
37
+ await UpdateLifecycleRulesAsync ( ) ;
38
+ await CreateAndReadTestFilesAsync ( false ) ;
39
+ updateComplete = true ;
40
+ }
41
+ }
42
+
43
+ internal async Task CreateContainersAsync ( )
44
+ {
45
+ // Implementation similar to S3LifecycleUpdater's CreateBucketsAsync
46
+ // Use BlobServiceClient to create containers if they don't exist
47
+ }
48
+
49
+ internal async Task UpdateLifecycleRulesAsync ( )
50
+ {
51
+ var client = defaultClient ;
52
+ var lifecycleManagementPolicy = new BlobLifecycleManagementPolicy ( ) ;
53
+ var rules = new List < BlobLifecycleRule > ( ) ;
54
+
55
+ foreach ( var groupConfig in config . BlobGroupConfigurations . Values )
56
+ {
57
+ if ( groupConfig . UpdateLifecycleRules == false ) continue ;
58
+
59
+ var containerName = groupConfig . Location . ContainerName ;
60
+ var prefix = groupConfig . Location . BlobPrefix ;
61
+
62
+ if ( groupConfig . Lifecycle . DaysBeforeExpiry . HasValue )
63
+ {
64
+ var rule = new BlobLifecycleRule
65
+ {
66
+ Name = $ "Rule-{ containerName } -{ prefix } ",
67
+ Enabled = true ,
68
+ Definition = new BlobLifecycleRuleDefinition
69
+ {
70
+ Filters = new BlobLifecycleRuleFilter
71
+ {
72
+ PrefixMatch = new List < string > { $ "{ containerName } /{ prefix } " }
73
+ } ,
74
+ Actions = new BlobLifecycleRuleActions
75
+ {
76
+ BaseBlob = new BlobLifecycleRuleActionBase
77
+ {
78
+ Delete = new BlobLifecycleRuleActionDelete
79
+ {
80
+ DaysAfterModificationGreaterThan = groupConfig . Lifecycle . DaysBeforeExpiry . Value
81
+ }
82
+ }
83
+ }
84
+ }
85
+ } ;
86
+
87
+ rules . Add ( rule ) ;
88
+ }
89
+ }
90
+
91
+ lifecycleManagementPolicy . Rules = rules ;
92
+
93
+ try
94
+ {
95
+ await client . SetBlobLifecyclePolicyAsync ( lifecycleManagementPolicy ) ;
96
+ logger . LogInformation ( "Updated lifecycle rules for storage account" ) ;
97
+ }
98
+ catch ( Exception e )
99
+ {
100
+ logger . LogError ( e , $ "Error updating lifecycle rules for storage account: { e . Message } ") ;
101
+ }
102
+ }
103
+
104
+ internal async Task < TestFilesResult > CreateAndReadTestFilesAsync ( bool forceAll )
105
+ {
106
+ // Implementation similar to S3LifecycleUpdater's CreateAndReadTestFilesAsync
107
+ // Use BlobContainerClient to perform operations on blobs
108
+ }
109
+
110
+ private async Task < CodeResult > TryAzureOperationAsync ( string containerName , string blobName , string operationName ,
111
+ Func < Task > operation )
112
+ {
113
+ try
114
+ {
115
+ await operation ( ) ;
116
+ return CodeResult . Ok ( ) ;
117
+ }
118
+ catch ( Azure . RequestFailedException e )
119
+ {
120
+ var err = CodeResult . FromException ( e , $ "Azure { operationName } { containerName } { blobName } ") ;
121
+ logger . LogAsError ( err ) ;
122
+ return err ;
123
+ }
124
+ }
125
+
126
+ internal record class TestFilesResult ( List < CodeResult > Results , bool ReadsFailed , bool WritesFailed , bool ListFailed , bool DeleteFailed ) ;
127
+ }
128
+ }
0 commit comments