public IAsyncEnumerable <StockTickerUpdate> Subscribe(IAsyncEnumerable <SymbolRequest> request, CallContext context)
        {
            var cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, context.CancellationToken).Token;
            var buffer            = Channel.CreateUnbounded <StockTickerUpdate>();

            _subscriber         = _subscriberFactory.GetSubscriber();
            _subscriber.Update += async(sender, args) =>
            {
                try
                {
                    await buffer.Writer.WriteAsync(new StockTickerUpdate
                    {
                        Symbol = args.Symbol,
                        Price  = args.Price,
                        Time   = DateTime.UtcNow
                    });
                }
                catch (Exception e)
                {
                    _logger.LogError($"Failed to write message: {e.Message}");
                }
            };

            _processRequestTask = ProcessRequests(request, buffer.Writer, cancellationToken);

            return(buffer.AsAsyncEnumerable(cancellationToken));
        }
    public override async Task Subscribe(IAsyncStreamReader <ActionMessage> requestStream, IServerStreamWriter <StockTickerUpdate> responseStream, ServerCallContext context)
    {
        using var subscriber = _subscriberFactory.GetSubscriber();

        subscriber.Update += async(sender, args) =>
                             await WriteUpdateAsync(responseStream, args.Symbol, args.Price);

        var actionsTask = HandleActions(requestStream, subscriber, context.CancellationToken);

        _logger.LogInformation("Subscription started.");
        await AwaitCancellation(context.CancellationToken);

        try { await actionsTask; } catch { /* Ignored */ }

        _logger.LogInformation("Subscription finished.");
    }