Skip to content

Commit

Permalink
feat: added the Echo Store. (#807)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thijs153 authored Oct 4, 2024
1 parent a221f31 commit a3e5eee
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 0 deletions.
18 changes: 18 additions & 0 deletions docs/Stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,21 @@ services.AddMultiTenant<TenantInfo>()
services.AddMultiTenant<TenantInfo>()
.WithDistributedCacheStore(TimeSpan.FromMinutes(5));
```

## Echo Store

> NuGet package: Finbuckle.MultiTenant

The Echo Store serves as a simple, read-only store that directly returns a new tenant instance based on the given identifier
without any additional settings. It's particularly suited for applications that require a simple, immediate method for tenant identification without the need for persistence, such as during testing phases or in environments where tenant information is static and predefined elsewhere.


This store is read-only and calls to `TryAddAsync`, `TryUpdateAsync`, and `TryRemoveAsync` will throw
a `NotImplementedException`. Because no stores are saved, a call to `GetAllAsync` will also throw an Exception.

Configure by calling `WithEchoStore` after `AddMultiTenant<TTenantInfo>`.

```csharp
services.AddMultiTenant<TenantInfo>()
.WithEchoStore();
```
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Finbuckle.MultiTenant.Internal;
using Finbuckle.MultiTenant.Stores.ConfigurationStore;
using Finbuckle.MultiTenant.Stores.DistributedCacheStore;
using Finbuckle.MultiTenant.Stores.EchoStore;
using Finbuckle.MultiTenant.Stores.HttpRemoteStore;
using Finbuckle.MultiTenant.Stores.InMemoryStore;
using Finbuckle.MultiTenant.Strategies;
Expand Down Expand Up @@ -116,6 +117,14 @@ public static MultiTenantBuilder<TTenantInfo> WithInMemoryStore<TTenantInfo>(thi

return builder.WithStore<InMemoryStore<TTenantInfo>>(ServiceLifetime.Singleton);
}

/// <summary>
/// Adds an EchoStore to the application.
/// </summary>
/// <param name="builder">The builder instance.</param>
public static MultiTenantBuilder<TTenantInfo> WithEchoStore<TTenantInfo>(this MultiTenantBuilder<TTenantInfo> builder)
where TTenantInfo : class, ITenantInfo, new()
=> builder.WithStore<EchoStore<TTenantInfo>>(ServiceLifetime.Singleton);

/// <summary>
/// Adds and configures a StaticStrategy to the application.
Expand Down
65 changes: 65 additions & 0 deletions src/Finbuckle.MultiTenant/Stores/EchoStore/EchoStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright Finbuckle LLC, Andrew White, and Contributors.
// Refer to the solution LICENSE file for more information.

// ReSharper disable once CheckNamespace

using Finbuckle.MultiTenant.Abstractions;

namespace Finbuckle.MultiTenant.Stores.EchoStore;

/// <summary>
/// Basic store that simply returns a tenant based on the identifier without any additional settings.
/// Note that add, update, and remove functionality is not implemented.
/// If underlying configuration supports reload-on-change then this store will reflect such changes.
/// </summary>
/// <typeparam name="TTenantInfo">The ITenantInfo implementation type.</typeparam>
public class EchoStore<TTenantInfo> : IMultiTenantStore<TTenantInfo> where TTenantInfo : class, ITenantInfo, new()
{
/// <inheritdoc />
public async Task<TTenantInfo?> TryGetByIdentifierAsync(string identifier)
{
return await Task.FromResult(new TTenantInfo { Id = identifier, Identifier = identifier });
}

/// <inheritdoc />
public async Task<TTenantInfo?> TryGetAsync(string id)
{
return await Task.FromResult(new TTenantInfo { Id = id, Identifier = id });
}

/// <summary>
/// Not implemented in this implementation.
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public Task<bool> TryAddAsync(TTenantInfo tenantInfo)
{
throw new NotImplementedException();
}

/// <summary>
/// Not implemented in this implementation.
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public Task<bool> TryUpdateAsync(TTenantInfo tenantInfo)
{
throw new NotImplementedException();
}

/// <summary>
/// Not implemented in this implementation.
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public Task<bool> TryRemoveAsync(string identifier)
{
throw new NotImplementedException();
}

/// <summary>
/// Not implemented in this implementation.
/// </summary>
/// <exception cref="NotImplementedException"></exception>
public Task<IEnumerable<TTenantInfo>> GetAllAsync()
{
throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Finbuckle.MultiTenant.Abstractions;
using Finbuckle.MultiTenant.Stores.ConfigurationStore;
using Finbuckle.MultiTenant.Stores.DistributedCacheStore;
using Finbuckle.MultiTenant.Stores.EchoStore;
using Finbuckle.MultiTenant.Stores.HttpRemoteStore;
using Finbuckle.MultiTenant.Stores.InMemoryStore;
using Finbuckle.MultiTenant.Strategies;
Expand Down Expand Up @@ -157,6 +158,26 @@ public async Task AddInMemoryStoreWithCaseSensitivity()
Assert.Null(tc);
}

[Fact]
public async Task AddEchoStore()
{
var services = new ServiceCollection();
var builder = new MultiTenantBuilder<TenantInfo>(services);
builder.WithEchoStore();
var sp = services.BuildServiceProvider();

var store = sp.GetRequiredService<IMultiTenantStore<TenantInfo>>();
Assert.IsType<EchoStore<TenantInfo>>(store);

var tc = await store.TryGetByIdentifierAsync("initech");
Assert.Equal("initech", tc!.Id);
Assert.Equal("initech", tc.Identifier);

tc = await store.TryGetByIdentifierAsync("lol");
Assert.Equal("lol", tc!.Id);
Assert.Equal("lol", tc.Identifier);
}

[Fact]
public void AddDelegateStrategy()
{
Expand Down

0 comments on commit a3e5eee

Please sign in to comment.