using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Windows.ApplicationModel.AppService; using Windows.Foundation.Collections; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Server; using Wino.Messaging; namespace Wino.Server.Core { public abstract class ServerMessageHandlerBase { public string HandlingRequestType { get; } public abstract Task ExecuteAsync(IClientMessage message, AppServiceRequest request = null, CancellationToken cancellationToken = default); } public abstract class ServerMessageHandler : ServerMessageHandlerBase where TClientMessage : IClientMessage { /// /// Response to return when server encounters and exception while executing code. /// /// Exception that target threw. /// Default response on failure object. public abstract WinoServerResponse FailureDefaultResponse(Exception ex); /// /// Safely executes the handler code and returns the response. /// This call will never crash the server. Exceptions encountered will be handled and returned as response. /// /// IClientMessage that client asked the response for from the server. /// optional AppServiceRequest to return response for. /// Cancellation token. /// Response object that server executes for the given method. public override async Task ExecuteAsync(IClientMessage message, AppServiceRequest request = null, CancellationToken cancellationToken = default) { WinoServerResponse response = default; try { response = await HandleAsync((TClientMessage)message, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { response = FailureDefaultResponse(ex); } finally { // No need to send response if request is null. // Handler might've been called directly from the server itself. if (request != null) { var valueSet = new ValueSet() { { MessageConstants.MessageDataKey, JsonSerializer.Serialize(response) } }; await request.SendResponseAsync(valueSet); } } } /// /// Code that will be executed directly on the server. /// All handlers must implement this method. /// Response is wrapped with WinoServerResponse. /// /// IClientMessage that client asked the response for from the server. /// Cancellation token. protected abstract Task> HandleAsync(TClientMessage message, CancellationToken cancellationToken = default); } }