Files
jellyfin-ha-src/Emby.Server.Implementations/Session/RemoteSessionController.cs
T

77 lines
2.7 KiB
C#

using System;
using System.Globalization;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Extensions.Json;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Session;
/// <summary>
/// Stands in for the websocket of a session another instance holds: messages are forwarded to that
/// instance, which writes them to the connection it owns and reports back whether it did.
/// </summary>
public sealed class RemoteSessionController : ISessionController
{
private readonly IPodMessageBus _bus;
private readonly ILogger _logger;
private readonly string _ownerPod;
private readonly string _sessionId;
/// <summary>
/// Initializes a new instance of the <see cref="RemoteSessionController"/> class.
/// </summary>
/// <param name="bus">The cross-instance bus.</param>
/// <param name="logger">The logger.</param>
/// <param name="ownerPod">The instance holding the connection.</param>
/// <param name="sessionId">The session identifier.</param>
/// <param name="supportsMediaControl">Whether the owner reported the session as controllable.</param>
public RemoteSessionController(IPodMessageBus bus, ILogger logger, string ownerPod, string sessionId, bool supportsMediaControl)
{
_bus = bus;
_logger = logger;
_ownerPod = ownerPod;
_sessionId = sessionId;
SupportsMediaControl = supportsMediaControl;
}
/// <inheritdoc />
public bool IsSessionActive => true;
/// <inheritdoc />
public bool SupportsMediaControl { get; }
/// <inheritdoc />
public async Task SendMessage<T>(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken)
{
var routed = new RoutedSessionMessage
{
SessionId = _sessionId,
MessageType = name,
MessageId = messageId,
Data = JsonSerializer.Serialize(data, JsonDefaults.Options)
};
var delivered = await _bus.RequestAsync(
_ownerPod,
new PodMessage
{
Kind = RoutedSessionMessage.Kind,
Payload = JsonSerializer.Serialize(routed, JsonDefaults.Options)
},
cancellationToken).ConfigureAwait(false);
if (!delivered)
{
_logger.LogWarning("Instance {OwnerPod} did not write the {MessageType} message for session {SessionId} to a connection.", _ownerPod, name, _sessionId);
throw new ResourceNotFoundException(
string.Format(CultureInfo.InvariantCulture, "No instance holds a connection to session {0}.", _sessionId));
}
}
}