using System; using System.Threading.Tasks; using LiteNetLib; namespace GameCult.Networking { /// /// Routes CultNet schema-v0 document messages through a . /// public sealed class CultNetDatabaseServer : IDisposable { private readonly Server _server; private readonly CultNetDatabase _database; private readonly Func _snapshotHandler; private readonly Func _putHandler; private readonly Func _deleteHandler; private bool _disposed; /// /// Creates and attaches a database message bridge to a server. /// public CultNetDatabaseServer(Server server, CultNetDatabase database) { _server = server ?? throw new ArgumentNullException(nameof(server)); _database = database ?? throw new ArgumentNullException(nameof(database)); _snapshotHandler = HandleSnapshotRequestAsync; _putHandler = HandlePutAsync; _deleteHandler = HandleDeleteAsync; _server.OnCultNet(_snapshotHandler); _server.OnCultNet(_putHandler); _server.OnCultNet(_deleteHandler); } /// /// Gets the database used by this bridge. /// public CultNetDatabase Database => _database; /// /// Applies a raw put message through the database shard policy. /// public Task ApplyPutAsync(CultNetDocumentPutRawMessage message) { return _database.ApplyPutAsync(message); } /// /// Applies a raw delete message through the database shard policy. /// public Task ApplyDeleteAsync(CultNetDocumentDeleteMessage message) { return _database.ApplyDeleteAsync(message); } /// /// Creates a raw snapshot response from the database cache. /// public CultNetSnapshotResponseRawMessage CreateSnapshotResponse(CultNetSnapshotRequestMessage request) { if (request == null) throw new ArgumentNullException(nameof(request)); return _database.Documents.CreateRawSnapshotResponse( _database.Cache, string.IsNullOrWhiteSpace(request.MessageId) ? Guid.NewGuid().ToString("N") : request.MessageId, request); } /// /// Detaches handlers from the server. /// public void Dispose() { if (_disposed) { return; } _disposed = true; _server.RemoveCultNetMessageListener(_snapshotHandler); _server.RemoveCultNetMessageListener(_putHandler); _server.RemoveCultNetMessageListener(_deleteHandler); } private Task HandleSnapshotRequestAsync(CultNetSnapshotRequestMessage request, NetPeer peer) { peer.SendCultNet(CreateSnapshotResponse(request)); return Task.CompletedTask; } private async Task HandlePutAsync(CultNetDocumentPutRawMessage message, NetPeer peer) { try { await ApplyPutAsync(message).ConfigureAwait(false); } catch (Exception ex) { peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message }); } } private async Task HandleDeleteAsync(CultNetDocumentDeleteMessage message, NetPeer peer) { try { await ApplyDeleteAsync(message).ConfigureAwait(false); } catch (Exception ex) { peer.SendCultNet(new CultNetErrorMessage { Error = ex.Message }); } } } }