Skip to content

Commit

Permalink
Asset Key Value Store for entity framework.
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianStehle committed Jan 19, 2025
1 parent 709397f commit 4561306
Show file tree
Hide file tree
Showing 30 changed files with 289 additions and 301 deletions.
13 changes: 10 additions & 3 deletions Squidex.Libs.sln
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Events", "events\Sq
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Events.EntityFramework", "events\Squidex.Events.EntityFramework\Squidex.Events.EntityFramework.csproj", "{5F4B51E1-0ADD-4C03-A93A-401BA86D08BA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.Events.Tests", "events\Squidex.Events.Tests\Squidex.Events.Tests.csproj", "{1E9B31E9-EA9D-4A82-B207-00E8B275EFD4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Events.Tests", "events\Squidex.Events.Tests\Squidex.Events.Tests.csproj", "{1E9B31E9-EA9D-4A82-B207-00E8B275EFD4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.Events.Mongo", "events\Squidex.Events.Mongo\Squidex.Events.Mongo.csproj", "{E36DAC0D-8A2D-49AA-B9C4-E74CAB0660B0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Events.Mongo", "events\Squidex.Events.Mongo\Squidex.Events.Mongo.csproj", "{E36DAC0D-8A2D-49AA-B9C4-E74CAB0660B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.Events.GetEventStore", "events\Squidex.Events.GetEventStore\Squidex.Events.GetEventStore.csproj", "{98156A5E-1B4A-46EF-AA84-019868425D80}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Events.GetEventStore", "events\Squidex.Events.GetEventStore\Squidex.Events.GetEventStore.csproj", "{98156A5E-1B4A-46EF-AA84-019868425D80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squidex.Assets.EntityFramework", "assets\Squidex.Assets.EntityFramework\Squidex.Assets.EntityFramework.csproj", "{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -283,6 +285,10 @@ Global
{98156A5E-1B4A-46EF-AA84-019868425D80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98156A5E-1B4A-46EF-AA84-019868425D80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98156A5E-1B4A-46EF-AA84-019868425D80}.Release|Any CPU.Build.0 = Release|Any CPU
{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -331,6 +337,7 @@ Global
{1E9B31E9-EA9D-4A82-B207-00E8B275EFD4} = {94285572-6875-4A9C-AFC4-987758DC9088}
{E36DAC0D-8A2D-49AA-B9C4-E74CAB0660B0} = {94285572-6875-4A9C-AFC4-987758DC9088}
{98156A5E-1B4A-46EF-AA84-019868425D80} = {94285572-6875-4A9C-AFC4-987758DC9088}
{C3D35ED4-8C81-449B-B732-3F0EE1FD6C7A} = {C857F3ED-A6AE-47C6-A115-87ECCB36AC02}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {060512DD-34DA-4929-A67F-2E473577FBF5}
Expand Down
30 changes: 15 additions & 15 deletions ai/Squidex.AI.Tests/EFChatStoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public sealed class EFChatStoreFixture : IAsyncLifetime
.WithLabel("reuse-id", "chatstore-postgres")
.Build();

private IServiceProvider services;
public IServiceProvider Services { get; private set; }

public EFChatStore<AppDbContext> Store => services.GetRequiredService<EFChatStore<AppDbContext>>();
public EFChatStore<AppDbContext> Store => Services.GetRequiredService<EFChatStore<AppDbContext>>();

public sealed class AppDbContext(DbContextOptions options) : DbContext(options)
{
Expand All @@ -38,21 +38,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
}
}

public async Task DisposeAsync()
{
foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}

await postgresSql.StopAsync();
}

public async Task InitializeAsync()
{
await postgresSql.StartAsync();

services = new ServiceCollection()
Services = new ServiceCollection()
.AddDbContext<AppDbContext>(b =>
{
b.UseNpgsql(postgresSql.GetConnectionString());
Expand All @@ -62,15 +52,25 @@ public async Task InitializeAsync()
.Services
.BuildServiceProvider();

var factory = services.GetRequiredService<IDbContextFactory<AppDbContext>>();
var factory = Services.GetRequiredService<IDbContextFactory<AppDbContext>>();
var context = await factory.CreateDbContextAsync();
var creator = (RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();

await creator.EnsureCreatedAsync();

foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.InitializeAsync(default);
}
}

public async Task DisposeAsync()
{
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}

await postgresSql.StopAsync();
}
}
30 changes: 15 additions & 15 deletions ai/Squidex.AI.Tests/MongoChatStoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,37 @@ public sealed class MongoChatStoreFixture : IAsyncLifetime
new MongoDbBuilder()
.WithReuse(Debugger.IsAttached)
.WithLabel("reuse-id", "chatstore-mongo")
.Build();
.Build();

private IServiceProvider services;
public IServiceProvider Services { get; private set; }

public MongoChatStore Store => services.GetRequiredService<MongoChatStore>();

public async Task DisposeAsync()
{
foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}

await mongoDb.StopAsync();
}
public MongoChatStore Store => Services.GetRequiredService<MongoChatStore>();

public async Task InitializeAsync()
{
await mongoDb.StartAsync();

services = new ServiceCollection()
Services = new ServiceCollection()
.AddSingleton<IMongoClient>(_ => new MongoClient(mongoDb.GetConnectionString()))
.AddSingleton(c => c.GetRequiredService<IMongoClient>().GetDatabase("Test"))
.AddAI()
.AddMongoChatStore(TestHelpers.Configuration)
.Services
.BuildServiceProvider();

foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.InitializeAsync(default);
}
}

public async Task DisposeAsync()
{
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}

await mongoDb.StopAsync();
}
}
1 change: 1 addition & 0 deletions assets/Squidex.Assets.Mongo/AssetsServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static IServiceCollection AddMongoAssetStore(this IServiceCollection serv

public static IServiceCollection AddMongoAssetKeyValueStore(this IServiceCollection services)
{
services.AddSingleton(typeof(MongoAssetKeyValueStore<>));
services.AddSingleton(typeof(IAssetKeyValueStore<>), typeof(MongoAssetKeyValueStore<>));

return services;
Expand Down
23 changes: 0 additions & 23 deletions assets/Squidex.Assets.Mongo/MongoAssetEntity.cs

This file was deleted.

24 changes: 17 additions & 7 deletions assets/Squidex.Assets.Mongo/MongoAssetKeyValueStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public sealed class MongoAssetKeyValueStore<T> : IAssetKeyValueStore<T>, IInitia
{
IsUpsert = true
};
private readonly IMongoCollection<MongoAssetEntity<T>> collection;
private readonly IMongoCollection<MongoAssetKeyValueEntity<T>> collection;

public MongoAssetKeyValueStore(IMongoDatabase database)
{
var collectionName = $"AssetKeyValueStore_{typeof(T).Name}";

collection = database.GetCollection<MongoAssetEntity<T>>(collectionName);
collection = database.GetCollection<MongoAssetKeyValueEntity<T>>(collectionName);
}

public Task InitializeAsync(
Expand All @@ -37,23 +37,31 @@ public Task InitializeAsync(
});

return collection.Indexes.CreateOneAsync(
new CreateIndexModel<MongoAssetEntity<T>>(
Builders<MongoAssetEntity<T>>.IndexKeys.Ascending(x => x.Expires)),
new CreateIndexModel<MongoAssetKeyValueEntity<T>>(
Builders<MongoAssetKeyValueEntity<T>>.IndexKeys.Ascending(x => x.Expires)),
cancellationToken: ct);
}

public Task DeleteAsync(string key,
CancellationToken ct = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(key);

return collection.DeleteOneAsync(x => x.Key == key, ct);
}

public async Task<T> GetAsync(string key,
public async Task<T?> GetAsync(string key,
CancellationToken ct = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(key);

var entity = await collection.Find(x => x.Key == key).FirstOrDefaultAsync(ct);
if (entity == null)
{
return default;
}

return entity != null ? entity.Value! : default!;
return entity.Value;
}

public async IAsyncEnumerable<(string Key, T Value)> GetExpiredEntriesAsync(DateTimeOffset now,
Expand All @@ -75,10 +83,12 @@ public async Task<T> GetAsync(string key,
public Task SetAsync(string key, T value, DateTimeOffset expires,
CancellationToken ct = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(key);

var utcExpires = expires.UtcDateTime;

return collection.UpdateOneAsync(x => x.Key == key,
Builders<MongoAssetEntity<T>>.Update
Builders<MongoAssetKeyValueEntity<T>>.Update
.Set(x => x.Expires, utcExpires)
.Set(x => x.Value, value),
upsert, ct);
Expand Down
24 changes: 12 additions & 12 deletions assets/Squidex.Assets.Tests/AmazonS3AssetStoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@ namespace Squidex.Assets;

public sealed class AmazonS3AssetStoreFixture : IAsyncLifetime
{
private IServiceProvider services;
public IServiceProvider Services { get; private set; }

public AmazonS3AssetStore Store => services.GetRequiredService<AmazonS3AssetStore>();

public async Task DisposeAsync()
{
foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
public AmazonS3AssetStore Store => Services.GetRequiredService<AmazonS3AssetStore>();

public async Task InitializeAsync()
{
// From: https://console.aws.amazon.com/iam/home?region=eu-central-1#/users/s3?section=security_credentials
services =
Services =
new ServiceCollection()
.AddAmazonS3AssetStore(TestHelpers.Configuration)
.BuildServiceProvider();

foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.InitializeAsync(default);
}
}

public async Task DisposeAsync()
{
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
}
24 changes: 12 additions & 12 deletions assets/Squidex.Assets.Tests/AzureBlobAssetStoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ namespace Squidex.Assets;

public sealed class AzureBlobAssetStoreFixture : IAsyncLifetime
{
private IServiceProvider services;
public IServiceProvider Services { get; private set; }

public AzureBlobAssetStore Store => services.GetRequiredService<AzureBlobAssetStore>();

public async Task DisposeAsync()
{
foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
public AzureBlobAssetStore Store => Services.GetRequiredService<AzureBlobAssetStore>();

public async Task InitializeAsync()
{
services =
Services =
new ServiceCollection()
.AddAzureBlobAssetStore(TestHelpers.Configuration)
.BuildServiceProvider();

foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.InitializeAsync(default);
}
}

public async Task DisposeAsync()
{
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
}
8 changes: 4 additions & 4 deletions assets/Squidex.Assets.Tests/CloudflareR2Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public CloudflareR2Fixture()
Store = services.GetRequiredService<AmazonS3AssetStore>();
}

public async Task DisposeAsync()
public async Task InitializeAsync()
{
await Store.ReleaseAsync(default);
await Store.InitializeAsync(default);
}

public async Task InitializeAsync()
public async Task DisposeAsync()
{
await Store.InitializeAsync(default);
await Store.ReleaseAsync(default);
}
}
24 changes: 12 additions & 12 deletions assets/Squidex.Assets.Tests/FTPAssetStoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@ namespace Squidex.Assets;

public sealed class FTPAssetStoreFixture : IAsyncLifetime
{
private IServiceProvider services;
public IServiceProvider Services { get; private set; }

public FTPAssetStore Store => services.GetRequiredService<FTPAssetStore>();

public async Task DisposeAsync()
{
foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
public FTPAssetStore Store => Services.GetRequiredService<FTPAssetStore>();

public async Task InitializeAsync()
{
services =
Services =
new ServiceCollection()
.AddSingleton(A.Fake<ILogger<FTPAssetStore>>())
.AddFTPAssetStore(TestHelpers.Configuration)
.BuildServiceProvider();

foreach (var service in services.GetRequiredService<IEnumerable<IInitializable>>())
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.InitializeAsync(default);
}
}

public async Task DisposeAsync()
{
foreach (var service in Services.GetRequiredService<IEnumerable<IInitializable>>())
{
await service.ReleaseAsync(default);
}
}
}
Loading

0 comments on commit 4561306

Please sign in to comment.