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));
        }
    private async Task HandleActions(IAsyncStreamReader <ActionMessage> requestStream, IFullStockPriceSubscriber subscriber, CancellationToken token)
    {
        await foreach (var action in requestStream.ReadAllAsync(token))
        {
            switch (action.ActionCase)
            {
            case ActionMessage.ActionOneofCase.None:
                _logger.LogWarning("No Action specified.");
                break;

            case ActionMessage.ActionOneofCase.Add:
                subscriber.Add(action.Add.Symbol);
                break;

            case ActionMessage.ActionOneofCase.Remove:
                subscriber.Remove(action.Remove.Symbol);
                break;

            default:
                _logger.LogWarning($"Unknown Action '{action.ActionCase}'.");
                break;
            }
        }
    }