Skip to content

Commit

Permalink
ITenantRepository refactoring (#209)
Browse files Browse the repository at this point in the history
* added GetAll to ITenantRepository

removed GetByHost from ITenantRepository
added ITenantHostRepository
fix PostMan collection

* remove cache for all tenants

* put back GetByHost

added repo test

Co-authored-by: [email protected] <[email protected]>
  • Loading branch information
dorinsimionescu and [email protected] authored Feb 18, 2022
1 parent f68bc7e commit 5744ce4
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "fe2223de-d906-4829-b07f-e1172bd2d2c7",
"_postman_id": "a6cf0814-a93a-4ca1-8320-d0424ddd19c5",
"name": "MultiTenantTodoList",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
Expand Down Expand Up @@ -48,7 +48,7 @@
],
"body": {
"mode": "raw",
"raw": "{\n \"Name\": \"My task name\",\n \"Description\": \"My task description\"\n}"
"raw": "{\n \"Name\": \"My task name\",\n \"Description\": \"My task description\",\n \"DueDate\": \"2022-07-01\"\n}"
},
"url": {
"raw": "http://localhost:58733/api/todo",
Expand Down
2 changes: 1 addition & 1 deletion samples/MultiTenancy/NBB.Todo.Worker/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private static void ConfigureServices(HostBuilderContext hostingContext, IServic
services.AddMultitenancy(hostingContext.Configuration)
.AddMultiTenantMessaging()
.AddDefaultMessagingTenantIdentification()
.AddTenantRepository<BasicTenantRepository>();
.AddTenantRepository<ConfigurationTenantRepository>();
}

private static void ConfigureLogging(HostBuilderContext ctx, ILoggingBuilder _builder)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -42,16 +43,37 @@ public async Task<Tenant> Get(Guid id, CancellationToken token)
return dbTenant;
}

private async Task<Tenant> GetTenantFromCache(string key, CancellationToken token = default)
{
var sTenant = await _cache.GetStringAsync(key, token);
return string.IsNullOrWhiteSpace(sTenant) ? null : JsonConvert.DeserializeObject<Tenant>(sTenant);
}

private async Task SetTenantToCache(Tenant tenant, string key, CancellationToken token = default)
{
var sTenant = JsonConvert.SerializeObject(tenant);
await _cache.SetStringAsync(key, sTenant,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(3)
},token);
}

public async Task<List<Tenant>> GetAll(CancellationToken token = default)
{
var tenants = await _tenantRepository.GetAll(token);
return tenants;
}

public async Task<Tenant> GetByHost(string host, CancellationToken token)
{

var cacheKey = CacheTenantByHostKey(host);
var cachedTenant = await GetTenantFromCache(cacheKey, token);
if (cachedTenant != null)
{
return cachedTenant;
}

var dbTenant = await _tenantRepository.GetByHost(host, token);
if (dbTenant == null)
{
Expand All @@ -62,21 +84,5 @@ public async Task<Tenant> GetByHost(string host, CancellationToken token)

return dbTenant;
}

private async Task<Tenant> GetTenantFromCache(string key, CancellationToken token = default)
{
var sTenant = await _cache.GetStringAsync(key, token);
return string.IsNullOrWhiteSpace(sTenant) ? null : JsonConvert.DeserializeObject<Tenant>(sTenant);
}

private async Task SetTenantToCache(Tenant tenant, string key, CancellationToken token = default)
{
var sTenant = JsonConvert.SerializeObject(tenant);
await _cache.SetStringAsync(key, sTenant,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(3)
},token);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using NBB.MultiTenancy.Abstractions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -43,7 +45,6 @@ public ConfigurationTenantRepository(IConfiguration configuration, IOptions<Tena

public Task<Tenant> Get(Guid id, CancellationToken token = default)
{

return Task.FromResult(tenantMap.TryGetValue(id, out var result) ? result : throw new Exception($"Tenant configuration not found for tenant {id}"));
}

Expand Down Expand Up @@ -72,5 +73,10 @@ private void LoadDefaultTenant()
var newTenant = Tenant.Default;
tenantMap = new ConcurrentDictionary<Guid, Tenant>() { [newTenant.TenantId] = newTenant };
}

public Task<List<Tenant>> GetAll(CancellationToken token = default)
{
return Task.FromResult(tenantMap.Values.ToList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// This source code is licensed under the MIT license.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -11,5 +12,6 @@ public interface ITenantRepository
{
Task<Tenant> Get(Guid id, CancellationToken token = default);
Task<Tenant> GetByHost(string host, CancellationToken token = default);
Task<List<Tenant>> GetAll(CancellationToken token = default);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ namespace NBB.MultiTenancy.Identification.Identifiers
{
public class HostTenantIdentifier : ITenantIdentifier
{
private readonly ITenantRepository _hostTenantRepository;
private readonly ITenantRepository _tenantRepository;

public HostTenantIdentifier(ITenantRepository hostTenantRepository)
public HostTenantIdentifier(ITenantRepository tenantRepository)
{
_hostTenantRepository = hostTenantRepository;
_tenantRepository = tenantRepository;
}

public async Task<Guid> GetTenantIdAsync(string tenantToken)
{
var tenant = await _hostTenantRepository.GetByHost(tenantToken);
var tenant = await _tenantRepository.GetByHost(tenantToken);
return tenant.TenantId;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using NBB.MultiTenancy.Abstractions.Configuration;
using NBB.MultiTenancy.Abstractions.Context;
using NBB.MultiTenancy.Abstractions.Options;
using NBB.MultiTenancy.Abstractions.Repositories;
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -18,8 +19,6 @@ namespace NBB.MultiTenancy.Configuration.Tests
{
public class TenantConfigurationTests
{


[Fact]
public void load_value_from_config()
{
Expand Down Expand Up @@ -375,7 +374,7 @@ public void load_connectionString_with_concatenated_defaults()
""MultiTenancy"": {
""Defaults"": {
""ConnectionStrings"": {
""Leasing_Database"": ""Server=server0;Database=lsngdbqa;User Id=web;Password=pas;MultipleActiveResultSets=true""
""Leasing_Database"": ""Server=server0;Database=db2;User Id=web;Password=pas;MultipleActiveResultSets=true""
}
},
""Tenants"": [
Expand Down Expand Up @@ -443,7 +442,7 @@ public void load_connectionString_concatenated_with_splitted_defaults()
{
""TenantId"": ""68a448a2-e7d8-4875-8127-f18668217eb6"",
""ConnectionStrings"": {
""Leasing_Database"": ""Server=server0;Database=lsngdbqa;User Id=web;Password=B1llpwd!;MultipleActiveResultSets=true""
""Leasing_Database"": ""Server=server0;Database=db;User Id=a;Password=a;MultipleActiveResultSets=true""
}
},
{
Expand Down Expand Up @@ -475,8 +474,10 @@ public void load_connectionString_concatenated_with_splitted_defaults()

// Assert
tenantConfig.GetConnectionString("ConnectionString_").Should().BeNull();
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server0;Database=lsngdbqa;User Id=web;Password=B1llpwd!;MultipleActiveResultSets=true");
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server0;Database=db;User Id=a;Password=a;MultipleActiveResultSets=true");
tenantConfig.GetValue<string>("TenantId").Should().Be("68a448a2-e7d8-4875-8127-f18668217eb6");
}


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) TotalSoft.
// This source code is licensed under the MIT license.

using FluentAssertions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using NBB.MultiTenancy.Abstractions;
using NBB.MultiTenancy.Abstractions.Configuration;
using NBB.MultiTenancy.Abstractions.Context;
using NBB.MultiTenancy.Abstractions.Options;
using NBB.MultiTenancy.Abstractions.Repositories;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Xunit;


namespace NBB.MultiTenancy.Configuration.Tests
{
public class TenantRepositoryTests
{
[Fact]
public void get_all_tenants_should_work()
{
// Arrange
var myConfiguration = @"{
""MultiTenancy"": {
""Defaults"": {
""ConnectionStrings"": {
""Leasing_Database"": {
""Server"": ""server1"",
""Database"": ""db1"",
""UserName"": ""web"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
},
""Tenants"": [
{
""TenantId"": ""68a448a2-e7d8-4875-8127-f18668217eb6"",
""ConnectionStrings"": {
""Leasing_Database"": ""Server=server0;Database=lsngdbqa;User Id=web;Password=;MultipleActiveResultSets=true""
}
},
{
""TenantId"": ""ef8d5362-9969-4e02-8794-0d1af56816f6"",
""Code"": ""BCR""
},
{
""TenantId"": ""da84628a-2925-4b69-9116-a90dd5a72b1f"",
""Code"": ""DEV""
}
]
}
}";

var configuration = new ConfigurationBuilder()
.AddInMemoryCollection()
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(myConfiguration)))
.Build();

var tenancyHostingOptions = new TenancyHostingOptions()
{
TenancyType = TenancyType.MultiTenant
};

var options = new OptionsWrapper<TenancyHostingOptions>(tenancyHostingOptions);

var repo = new ConfigurationTenantRepository(configuration, options);

//arrange
var all = repo.GetAll().GetAwaiter().GetResult();

// Assert
all.Should().NotBeNull();
all.Should().NotBeEmpty();
all.Count.Should().Be(3);

//all[0].TenantId.Should().Be(Guid.Parse("ef8d5362-9969-4e02-8794-0d1af56816f6"));
//all[1].TenantId.Should().Be(Guid.Parse("68a448a2-e7d8-4875-8127-f18668217eb6"));
//all[2].TenantId.Should().Be(Guid.Parse("da84628a-2925-4b69-9116-a90dd5a72b1f"));

//all[0].Code.Should().Be("BCR");
//all[1].Code.Should().BeNull();
//all[2].Code.Should().Be("DEV");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ namespace NBB.MultiTenancy.Identification.Tests.Identifiers
{
public class HostTenantIdentifierTests
{
private readonly Mock<ITenantRepository> _hostTenantRepository;
private readonly Mock<ITenantRepository> _tenantRepository;

public HostTenantIdentifierTests()
{
_hostTenantRepository = new Mock<ITenantRepository>();
_tenantRepository = new Mock<ITenantRepository>();
}

[Fact]
Expand All @@ -28,8 +28,8 @@ public void Should_Return_TenantId()
// Arrange
var tenantId = Guid.NewGuid();
var tenant = new Tenant(tenantId, string.Empty);
_hostTenantRepository.Setup(r => r.GetByHost(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(tenant));
var sut = new HostTenantIdentifier(_hostTenantRepository.Object);
_tenantRepository.Setup(r => r.GetByHost(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(tenant));
var sut = new HostTenantIdentifier(_tenantRepository.Object);

// Act
var result = sut.GetTenantIdAsync(string.Empty).Result;
Expand All @@ -43,14 +43,14 @@ public void Should_Pass_Token_To_Repository()
{
// Arrange
const string tenantToken = "tenant token";
_hostTenantRepository.Setup(r => r.GetByHost(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new Tenant(Guid.Empty, string.Empty)));
var sut = new HostTenantIdentifier(_hostTenantRepository.Object);
_tenantRepository.Setup(r => r.GetByHost(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new Tenant(Guid.Empty, string.Empty)));
var sut = new HostTenantIdentifier(_tenantRepository.Object);

// Act
var _ = sut.GetTenantIdAsync(tenantToken).Result;

// Assert
_hostTenantRepository.Verify(r => r.GetByHost(It.Is<string>(s => string.Equals(s, tenantToken)), It.IsAny<CancellationToken>()), Times.Once());
_tenantRepository.Verify(r => r.GetByHost(It.Is<string>(s => string.Equals(s, tenantToken)), It.IsAny<CancellationToken>()), Times.Once());
}
}
}

0 comments on commit 5744ce4

Please sign in to comment.