Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lilith committed Jan 26, 2024
1 parent d78d297 commit 1e81a5b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 14 deletions.
8 changes: 8 additions & 0 deletions src/Imazen.Routing/Layers/LocalFilesLayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ public async ValueTask<IAdaptableHttpResponse> CreateResponseAsync(IRequestSnaps
{
return new BlobResponse(await TryGetBlobAsync(request, router, pipeline, cancellationToken)).AsResponse();
}



public bool HasDependencies => false;
public bool ReadyToWriteCacheKeyBasisData => true;
Expand All @@ -136,6 +138,12 @@ public virtual void WriteCacheKeyBasisPairsToRecursive(IBufferWriter<byte> write
FinalRequest.WriteCacheKeyBasisPairsTo(writer);
}

private byte[]? cacheKey32Bytes = null;
public byte[] GetCacheKey32Bytes()
{
return cacheKey32Bytes ??= this.GetCacheKey32BytesUncached();
}

public virtual bool SupportsPreSignedUrls => false;

public abstract ValueTask<CodeResult<IBlobWrapper>> TryGetBlobAsync(IRequestSnapshot request,
Expand Down
22 changes: 20 additions & 2 deletions src/Imazen.Routing/Promises/IInstantPromise.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public interface IInstantCacheKeySupportingPromise: IInstantPromise

// Must call resolve dependencies first
void WriteCacheKeyBasisPairsToRecursive(IBufferWriter<byte> writer);

byte[] GetCacheKey32Bytes();
}
public interface ICacheableBlobPromise : IInstantCacheKeySupportingPromise
{
Expand All @@ -55,7 +57,16 @@ public interface ISupportsPreSignedUrls : ICacheableBlobPromise

public static class CacheableBlobPromiseExtensions
{

public static byte[] GetCacheKey32BytesUncached(this ICacheableBlobPromise promise)
{
var buffer = new byte[32];
var used = promise.CopyCacheKeyBytesTo(buffer);
if (used.Length != 32)
{
throw new InvalidOperationException("Hash buffer failure 1125125");
}
return buffer;
}
public static ReadOnlySpan<byte> CopyCacheKeyBytesTo(this ICacheableBlobPromise promise, Span<byte> buffer32Bytes)
{
if (buffer32Bytes.Length < 32)
Expand All @@ -66,11 +77,12 @@ public static ReadOnlySpan<byte> CopyCacheKeyBytesTo(this ICacheableBlobPromise
{
throw new InvalidOperationException("Promise is not ready to write cache key basis data. Did you call RouteDependenciesAsync? Check ReadyToWriteCacheKeyBasisData first");
}
var buffer = new ArrayPoolBufferWriter<byte>(4096);
using var buffer = new ArrayPoolBufferWriter<byte>(4096);
promise.WriteCacheKeyBasisPairsToRecursive(buffer);

#if NET5_0_OR_GREATER
var bytesWritten = SHA256.HashData(buffer.WrittenSpan, buffer32Bytes);
buffer.Dispose();
return buffer32Bytes[..bytesWritten];
#elif NETSTANDARD2_0
using var hasher = SHA256.Create();
Expand All @@ -96,6 +108,12 @@ public record CacheableBlobPromise(IRequestSnapshot FinalRequest, Func<IRequestS
public bool ReadyToWriteCacheKeyBasisData => true;
public bool SupportsPreSignedUrls => false;

private byte[]? cacheKey32Bytes = null;
public byte[] GetCacheKey32Bytes()
{
return cacheKey32Bytes ??= this.GetCacheKey32BytesUncached();
}

public ValueTask<CodeResult> RouteDependenciesAsync(IBlobRequestRouter router, CancellationToken cancellationToken = default)
{
return Tasks.ValueResult(CodeResult.Ok());
Expand Down
17 changes: 10 additions & 7 deletions src/Imazen.Routing/Promises/Pipelines/ImagingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public ImagingPromise(ImagingMiddlewareOptions options,
PromisePipeline = promisePipeline;
Options = options;
AppliedWatermarks = appliedWatermarks;
FinalCommandString = finalCommandString;
FinalCommandString = finalCommandString.TrimStart('?');

// determine if we have extra dependencies

Expand All @@ -134,7 +134,12 @@ public ImagingPromise(ImagingMiddlewareOptions options,
Dependencies = new List<ICacheableBlobPromise>(){Input0};
}
}

private byte[]? cacheKey32Bytes = null;
public byte[] GetCacheKey32Bytes()
{
return cacheKey32Bytes ??= this.GetCacheKey32BytesUncached();
}

private string FinalCommandString { get; init; }

public async ValueTask<CodeResult<IBlobWrapper>> TryGetBlobAsync(IRequestSnapshot request,
Expand Down Expand Up @@ -189,12 +194,10 @@ public async ValueTask<CodeResult<IBlobWrapper>> TryGetBlobAsync(IRequestSnapsho
{
watermarks = new List<InputWatermark>(AppliedWatermarks.Count);
watermarks.AddRange(
AppliedWatermarks.Select((t, i) =>
{
return new InputWatermark(
AppliedWatermarks.Select((t, i)
=> new InputWatermark(
byteSources[i + 1],
t.Watermark);
}));
t.Watermark)));
}

try
Expand Down
14 changes: 10 additions & 4 deletions src/Imazen.Routing/Promises/Pipelines/ServerlessCacheEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public ServerlessCacheEngine(IBlobPromisePipeline? next, ServerlessCacheEngineOp
}

public async ValueTask<CodeResult<ICacheableBlobPromise>> GetFinalPromiseAsync(ICacheableBlobPromise promise, IBlobRequestRouter router,
IBlobPromisePipeline promisePipeline,IHttpRequestStreamAdapter outerRequest, CancellationToken cancellationToken = default)
IBlobPromisePipeline promisePipeline, IHttpRequestStreamAdapter outerRequest, CancellationToken cancellationToken = default)
{
var wrappedPromise = promise;
if (Next != null)
Expand All @@ -97,9 +97,8 @@ public async ValueTask<CodeResult<ICacheableBlobPromise>> GetFinalPromiseAsync(I

public static IBlobCacheRequest For(ICacheableBlobPromise promise, BlobGroup blobGroup)
{
var bytes = new byte[32];
var hex = promise.CopyCacheKeyBytesTo(bytes)
.ToHexLowercase();
var bytes = promise.GetCacheKey32Bytes();
var hex = bytes.ToHexLowercase();
return new BlobCacheRequest(blobGroup, bytes, hex, false);
}

Expand Down Expand Up @@ -415,6 +414,13 @@ internal record ServerlessCachePromise(IRequestSnapshot FinalRequest, ICacheable
public bool HasDependencies => FreshPromise.HasDependencies;
public bool ReadyToWriteCacheKeyBasisData => FreshPromise.ReadyToWriteCacheKeyBasisData;
public bool SupportsPreSignedUrls => FreshPromise.SupportsPreSignedUrls;

private byte[]? cacheKey32Bytes = null;
public byte[] GetCacheKey32Bytes()
{
return cacheKey32Bytes ??= this.GetCacheKey32BytesUncached();
}

public ValueTask<CodeResult> RouteDependenciesAsync(IBlobRequestRouter router, CancellationToken cancellationToken = default)
{
return FreshPromise.RouteDependenciesAsync(router, cancellationToken);
Expand Down
3 changes: 2 additions & 1 deletion src/Imazen.Routing/Serving/ImageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public ImageServer(IImageServerContainer container,
};

pipeline = new ServerlessCacheEngine(null, sourceCacheOptions);
pipeline = new ImagingMiddleware(pipeline, imagingOptions);
pipeline = new ImagingMiddleware(null, imagingOptions);
pipeline = new ServerlessCacheEngine(pipeline, sourceCacheOptions);
}

Expand Down Expand Up @@ -196,6 +196,7 @@ public async ValueTask<bool> TryHandleRequestAsync(TRequest request, TResponse r
var blob = blobResult.Unwrap();

// TODO: if the blob provided an etag, it could be from blob storage, or it could be from a cache.
// TODO: TryGetBlobAsync already calculates the cache if it's a serverless promise...
// Since cache provider has to calculate the cache key anyway, can't we figure out how to improve this?
promisedEtag ??= CreateEtag(finalPromise);

Expand Down

0 comments on commit 1e81a5b

Please sign in to comment.