Skip to content

Commit

Permalink
Stub AzureBlob health+lifecycle rule updater
Browse files Browse the repository at this point in the history
  • Loading branch information
lilith committed Aug 29, 2024
1 parent cd3fd56 commit 2efcb02
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/Imageflow.Server.Storage.AzureBlob/Caching/HealthCheck.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Azure.Storage.Blobs;
using Imazen.Abstractions.BlobCache;
using Microsoft.Extensions.Logging;

namespace Imageflow.Server.Storage.AzureBlob.Caching;

internal record HealthCheck(IBlobCache Cache, NamedCacheConfiguration Config, ILogger Logger, Dictionary<BlobGroup, BlobServiceClient> ServiceClients,
ContainerExistenceCache ContainerExists)
{

// this.InitialCacheCapabilities = new BlobCacheCapabilities
// {
// CanFetchMetadata = true,
// CanFetchData = true,
// CanConditionalFetch = false,
// CanPut = true,
// CanConditionalPut = false,
// CanDelete = false,
// CanSearchByTag = false,
// CanPurgeByTag = false,
// CanReceiveEvents = false,
// SupportsHealthCheck = false,
// SubscribesToRecentRequest = false,
// SubscribesToExternalHits = true,
// SubscribesToFreshResults = true,
// RequiresInlineExecution = false,
// FixedSize = false
// };
//

public ValueTask<IBlobCacheHealthDetails> CacheHealthCheck(CancellationToken cancellationToken = default)
{

}

internal record BasicHealthDetails(bool CanFetchData, bool CanFetchMetadata, bool CanConditionalFetch, bool CanPut, bool CanConditionalPut, bool CanSearchByTag, bool CanPurgeByTag);

internal ValueTask<BasicHealthDetails> CheckGroup(BlobGroup group, CancellationToken cancellationToken = default)
{

}
}
128 changes: 128 additions & 0 deletions src/Imageflow.Server.Storage.AzureBlob/Caching/LifecycleRuleUpdater.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Imazen.Common.Concurrency;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Imazen.Abstractions.Logging;
using Imazen.Abstractions.Resulting;

namespace Imageflow.Server.Storage.AzureBlob.Caching
{
internal class LifecycleRuleUpdater
{
private readonly NamedCacheConfiguration config;
private readonly IReLogger logger;
private readonly BlobServiceClient defaultClient;
private readonly BasicAsyncLock updateLock = new BasicAsyncLock();
private bool updateComplete = false;

public LifecycleRuleUpdater(NamedCacheConfiguration config, BlobServiceClient defaultClient, IReLogger logger)
{
this.config = config;
this.logger = logger.WithSubcategory(nameof(LifecycleRuleUpdater));
this.defaultClient = defaultClient;
}

internal async Task UpdateIfIncompleteAsync()
{
if (updateComplete) return;

using (await updateLock.LockAsync())
{
if (updateComplete) return;
await CreateContainersAsync();
await UpdateLifecycleRulesAsync();
await CreateAndReadTestFilesAsync(false);
updateComplete = true;
}
}

internal async Task CreateContainersAsync()
{
// Implementation similar to S3LifecycleUpdater's CreateBucketsAsync
// Use BlobServiceClient to create containers if they don't exist
}

internal async Task UpdateLifecycleRulesAsync()
{
var client = defaultClient;
var lifecycleManagementPolicy = new BlobLifecycleManagementPolicy();
var rules = new List<BlobLifecycleRule>();

foreach (var groupConfig in config.BlobGroupConfigurations.Values)
{
if (groupConfig.UpdateLifecycleRules == false) continue;

var containerName = groupConfig.Location.ContainerName;
var prefix = groupConfig.Location.BlobPrefix;

if (groupConfig.Lifecycle.DaysBeforeExpiry.HasValue)
{
var rule = new BlobLifecycleRule
{
Name = $"Rule-{containerName}-{prefix}",
Enabled = true,
Definition = new BlobLifecycleRuleDefinition
{
Filters = new BlobLifecycleRuleFilter
{
PrefixMatch = new List<string> { $"{containerName}/{prefix}" }
},
Actions = new BlobLifecycleRuleActions
{
BaseBlob = new BlobLifecycleRuleActionBase
{
Delete = new BlobLifecycleRuleActionDelete
{
DaysAfterModificationGreaterThan = groupConfig.Lifecycle.DaysBeforeExpiry.Value
}
}
}
}
};

rules.Add(rule);
}
}

lifecycleManagementPolicy.Rules = rules;

try
{
await client.SetBlobLifecyclePolicyAsync(lifecycleManagementPolicy);
logger.LogInformation("Updated lifecycle rules for storage account");
}
catch (Exception e)
{
logger.LogError(e, $"Error updating lifecycle rules for storage account: {e.Message}");
}
}

internal async Task<TestFilesResult> CreateAndReadTestFilesAsync(bool forceAll)
{
// Implementation similar to S3LifecycleUpdater's CreateAndReadTestFilesAsync
// Use BlobContainerClient to perform operations on blobs
}

private async Task<CodeResult> TryAzureOperationAsync(string containerName, string blobName, string operationName,
Func<Task> operation)
{
try
{
await operation();
return CodeResult.Ok();
}
catch (Azure.RequestFailedException e)
{
var err = CodeResult.FromException(e, $"Azure {operationName} {containerName} {blobName}");
logger.LogAsError(err);
return err;
}
}

internal record class TestFilesResult(List<CodeResult> Results, bool ReadsFailed, bool WritesFailed, bool ListFailed, bool DeleteFailed);
}
}

0 comments on commit 2efcb02

Please sign in to comment.