-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from marcwittke/develop
5.2
- Loading branch information
Showing
39 changed files
with
844 additions
and
783 deletions.
There are no files selected for viewing
93 changes: 50 additions & 43 deletions
93
src/abstractions/Backend.Fx/Environment/MultiTenancy/ITenantManager.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
src/abstractions/Backend.Fx/Environment/MultiTenancy/LookupTenantManager.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
using JetBrains.Annotations; | ||
|
||
namespace Backend.Fx.Environment.MultiTenancy | ||
{ | ||
/// <summary> | ||
/// A tenant manager that keeps all tenants in a lookup held in memory. Refresh is done | ||
/// automatically when changes occur. However, in a multi process environment, manual | ||
/// triggering of Refresh is required, when another process is updating the tenants. | ||
/// </summary> | ||
public abstract class LookupTenantManager : TenantManager | ||
{ | ||
private LookupItem[] _lookupItems; | ||
private TenantId _defaultTenantId = new TenantId(null); | ||
|
||
public TenantId DefaultTenantId => _defaultTenantId; | ||
|
||
public void EnsureLoaded() | ||
{ | ||
if (_lookupItems == null) RefreshLookupItems(); | ||
} | ||
|
||
public void RefreshLookupItems() | ||
{ | ||
var newLookupItems = LoadTenantLookupItems(); | ||
Interlocked.Exchange(ref _lookupItems, newLookupItems); | ||
} | ||
|
||
public override TenantId[] GetTenantIds() | ||
{ | ||
EnsureLoaded(); | ||
return _lookupItems.Select(itm => itm.TenantId).ToArray(); | ||
} | ||
|
||
public override Tenant[] GetTenants() | ||
{ | ||
EnsureLoaded(); | ||
return _lookupItems.Select(itm => itm.Tenant).ToArray(); | ||
} | ||
|
||
public override Tenant GetTenant(TenantId tenantId) | ||
{ | ||
EnsureLoaded(); | ||
return _lookupItems.First(itm => itm.TenantId.Value == tenantId.Value).Tenant; | ||
} | ||
|
||
[CanBeNull] | ||
public override Tenant FindTenant(TenantId tenantId) | ||
{ | ||
EnsureLoaded(); | ||
return _lookupItems.FirstOrDefault(itm => itm.Tenant.Id == tenantId.Value)?.Tenant; | ||
} | ||
|
||
public override TenantId FindMatchingTenantId(string requestUri) | ||
{ | ||
EnsureLoaded(); | ||
return _lookupItems.FirstOrDefault(t => t.Regex != null && t.Regex.IsMatch(requestUri))?.TenantId ?? DefaultTenantId; | ||
} | ||
|
||
public override TenantId GetDefaultTenantId() | ||
{ | ||
EnsureLoaded(); | ||
return DefaultTenantId; | ||
} | ||
|
||
protected override TenantId CreateTenant(string name, string description, bool isDemo, bool isDefault, CultureInfo defaultCultureInfo, string uriMatchingExpression) | ||
{ | ||
var tenantId = base.CreateTenant(name, description, isDemo, isDefault, defaultCultureInfo, uriMatchingExpression); | ||
return tenantId; | ||
} | ||
|
||
protected abstract Tenant[] LoadTenants(); | ||
|
||
protected override void Dispose(bool disposing) | ||
{ } | ||
|
||
protected override void RaiseTenantCreated(TenantId tenantId) | ||
{ | ||
RefreshLookupItems(); | ||
base.RaiseTenantCreated(tenantId); | ||
} | ||
|
||
protected override void RaiseTenantActivated(TenantId tenantId) | ||
{ | ||
RefreshLookupItems(); | ||
base.RaiseTenantActivated(tenantId); | ||
} | ||
|
||
private LookupItem[] LoadTenantLookupItems() | ||
{ | ||
List<LookupItem> items = new List<LookupItem>(); | ||
foreach (var tenant in LoadTenants()) | ||
{ | ||
var tenantId = new TenantId(tenant.Id); | ||
if (tenant.IsDefault) | ||
{ | ||
Interlocked.Exchange(ref _defaultTenantId, tenantId); | ||
} | ||
|
||
items.Add(new LookupItem(tenant)); | ||
} | ||
|
||
var newLookupItems = items.ToArray(); | ||
return newLookupItems; | ||
} | ||
|
||
private class LookupItem | ||
{ | ||
public LookupItem(Tenant tenant) | ||
{ | ||
Regex = tenant.UriMatchingExpression == null ? null : new Regex(tenant.UriMatchingExpression, RegexOptions.Compiled | RegexOptions.IgnoreCase); | ||
Tenant = tenant; | ||
TenantId = new TenantId(Tenant.Id); | ||
} | ||
|
||
public Regex Regex { get; } | ||
public Tenant Tenant { get; } | ||
public TenantId TenantId { get; } | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/abstractions/Backend.Fx/Extensions/MultipleDisposable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System; | ||
|
||
namespace Backend.Fx.Extensions | ||
{ | ||
public class MultipleDisposable : IDisposable | ||
{ | ||
private readonly IDisposable[] _disposables; | ||
|
||
public MultipleDisposable(params IDisposable[] disposables) | ||
{ | ||
_disposables = disposables; | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
foreach (var disposable in _disposables) | ||
{ | ||
disposable?.Dispose(); | ||
} | ||
} | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
src/abstractions/Backend.Fx/Extensions/ReaderWriterLockSlimExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using System; | ||
using System.Threading; | ||
|
||
namespace Backend.Fx.Extensions | ||
{ | ||
public static class ReaderWriterLockSlimExtensions | ||
{ | ||
private sealed class ReadLockToken : IDisposable | ||
{ | ||
private ReaderWriterLockSlim _sync; | ||
public ReadLockToken(ReaderWriterLockSlim sync) | ||
{ | ||
_sync = sync; | ||
sync.EnterReadLock(); | ||
} | ||
public void Dispose() | ||
{ | ||
if (_sync != null) | ||
{ | ||
_sync.ExitReadLock(); | ||
_sync = null; | ||
} | ||
} | ||
} | ||
private sealed class WriteLockToken : IDisposable | ||
{ | ||
private ReaderWriterLockSlim _sync; | ||
public WriteLockToken(ReaderWriterLockSlim sync) | ||
{ | ||
_sync = sync; | ||
sync.EnterWriteLock(); | ||
} | ||
public void Dispose() | ||
{ | ||
if (_sync != null) | ||
{ | ||
_sync.ExitWriteLock(); | ||
_sync = null; | ||
} | ||
} | ||
} | ||
|
||
public static IDisposable Read(this ReaderWriterLockSlim obj) | ||
{ | ||
return new ReadLockToken(obj); | ||
} | ||
public static IDisposable Write(this ReaderWriterLockSlim obj) | ||
{ | ||
return new WriteLockToken(obj); | ||
} | ||
} | ||
} |
Oops, something went wrong.