//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Persistence.InMemory;
using System.Threading;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Interfaces;
using MUnique.OpenMU.PlugIns;
using Nito.Disposables;
///
/// A context provider which uses in-memory repositories to hold its data, e.g. for testing or demo purposes.
/// Changes in one context directly have effect in other contexts! Calling SaveChanges or not doesn't matter.
///
public class InMemoryPersistenceContextProvider : IMigratableDatabaseContextProvider
{
private InMemoryRepositoryProvider _repositoryProvider = new();
///
/// Initializes a new instance of the class.
///
/// The change publisher.
public InMemoryPersistenceContextProvider(IConfigurationChangePublisher? changePublisher = null)
{
this.ChangePublisher = changePublisher;
}
///
public IRepositoryProvider RepositoryProvider => this._repositoryProvider;
///
/// Gets or sets the publisher for configuration changes.
///
public IConfigurationChangePublisher? ChangePublisher { get; set; }
///
public IContext CreateNewContext()
{
var context = new InMemoryContext(this._repositoryProvider);
this.AttachChangePublisher(context, typeof(PlugInConfiguration));
return context;
}
///
public IContext CreateNewContext(GameConfiguration gameConfiguration)
{
var context = new InMemoryContext(this._repositoryProvider);
this.AttachChangePublisher(context, typeof(PlugInConfiguration));
return context;
}
///
public IContext CreateNewTradeContext()
{
return new InMemoryContext(this._repositoryProvider);
}
///
public IPlayerContext CreateNewPlayerContext(GameConfiguration gameConfiguration)
{
return new PlayerInMemoryContext(this._repositoryProvider);
}
///
public IConfigurationContext CreateNewConfigurationContext()
{
return new ConfigurationInMemoryContext(this._repositoryProvider);
}
///
public IFriendServerContext CreateNewFriendServerContext()
{
return new FriendServerInMemoryContext(this._repositoryProvider);
}
///
public IGuildServerContext CreateNewGuildContext()
{
return new GuildServerInMemoryContext(this._repositoryProvider);
}
///
public IContext CreateNewTypedContext(Type editType, bool useCache, GameConfiguration? gameConfiguration = null)
{
var context = new InMemoryContext(this._repositoryProvider);
this.AttachChangePublisher(context, editType);
return context;
}
///
public Task DatabaseExistsAsync(CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
///
public Task IsDatabaseUpToDateAsync(CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
///
public Task ApplyAllPendingUpdatesAsync()
{
// we don't need to do anything.
return Task.CompletedTask;
}
///
public Task WaitForUpdatedDatabaseAsync(CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
///
public Task CanConnectToDatabaseAsync(CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
///
public Task ShouldDoAutoSchemaUpdateAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(true);
}
///
public Task ReCreateDatabaseAsync(bool dropExistingDatabase = true)
{
this._repositoryProvider = new();
return Task.FromResult(new Disposable(() => { }));
}
///
public void ResetCache()
{
// do nothing here
}
private void AttachChangePublisher(InMemoryContext context, Type editType)
{
if (this.ChangePublisher is { } changePublisher)
{
#pragma warning disable VSTHRD100
async void OnContextOnSavedChanges(object? o, EventArgs e)
#pragma warning restore VSTHRD100
{
await this.PublishConfigurationChangesAsync(context, changePublisher, editType).ConfigureAwait(false);
}
context.SavedChanges += OnContextOnSavedChanges;
}
}
private async ValueTask PublishConfigurationChangesAsync(InMemoryContext context, IConfigurationChangePublisher changePublisher, Type editType)
{
try
{
foreach (var obj in await context.GetAsync(editType, default).ConfigureAwait(false))
{
await changePublisher.ConfigurationChangedAsync(editType, obj.GetId(), obj).ConfigureAwait(false);
}
}
catch
{
// ignore all errors.
}
}
}