Files
git.stella-ops.org/src/__Libraries/StellaOps.Artifact.Infrastructure/S3UnifiedArtifactStore.StoreHelpers.cs

101 lines
3.4 KiB
C#

using Microsoft.Extensions.Logging;
using StellaOps.Artifact.Core;
namespace StellaOps.Artifact.Infrastructure;
public sealed partial class S3UnifiedArtifactStore
{
private async Task<ArtifactStoreResult?> TryGetExistingAsync(
ArtifactStoreRequest request,
string fullKey,
CancellationToken ct)
{
if (request.Overwrite || _options.AllowOverwrite)
{
return null;
}
var exists = await _client.ObjectExistsAsync(_options.BucketName, fullKey, ct).ConfigureAwait(false);
if (!exists)
{
return null;
}
_logger.LogInformation("Artifact already exists at {Key}, skipping", fullKey);
var entry = await _indexRepository.GetAsync(
request.BomRef,
request.SerialNumber,
request.ArtifactId,
ct).ConfigureAwait(false);
return entry == null
? null
: ArtifactStoreResult.Succeeded(fullKey, entry.Sha256, entry.SizeBytes, wasCreated: false);
}
private async Task<(byte[] ContentBytes, string Sha256)> ReadContentAsync(
ArtifactStoreRequest request,
CancellationToken ct)
{
using var memoryStream = new MemoryStream();
await request.Content.CopyToAsync(memoryStream, ct).ConfigureAwait(false);
var contentBytes = memoryStream.ToArray();
var sha256 = ComputeSha256(contentBytes);
return (contentBytes, sha256);
}
private async Task<string> WriteContentAsync(
ArtifactStoreRequest request,
string fullKey,
byte[] contentBytes,
string sha256,
CancellationToken ct)
{
if (_options.EnableDeduplication)
{
var existingBySha = await _indexRepository.FindBySha256Async(sha256, ct).ConfigureAwait(false);
if (existingBySha.Count > 0)
{
var existingKey = existingBySha[0].StorageKey;
_logger.LogInformation(
"Deduplicating artifact {ArtifactId} - content matches {ExistingKey}",
request.ArtifactId,
existingKey);
return existingKey;
}
}
await UploadAsync(fullKey, request, contentBytes, ct).ConfigureAwait(false);
return fullKey;
}
private async Task UploadAsync(string key, ArtifactStoreRequest request, byte[] contentBytes, CancellationToken ct)
{
using var uploadStream = new MemoryStream(contentBytes);
var metadata = BuildS3Metadata(request);
await _client.PutObjectAsync(
_options.BucketName,
key,
uploadStream,
request.ContentType,
metadata,
ct).ConfigureAwait(false);
}
private ArtifactIndexEntry BuildIndexEntry(
ArtifactStoreRequest request,
string storageKey,
string sha256,
long sizeBytes)
{
var now = _timeProvider.GetUtcNow();
return new ArtifactIndexEntry
{
Id = _guidProvider.NewGuid(),
TenantId = request.TenantId,
BomRef = request.BomRef,
SerialNumber = request.SerialNumber,
ArtifactId = request.ArtifactId,
StorageKey = storageKey,
Type = request.Type,
ContentType = request.ContentType,
Sha256 = sha256,
SizeBytes = sizeBytes,
CreatedAt = now
};
}
}