private async Task <bool> SubscribeToOrderBookUpdatesAsync(int timeoutMs, CancellationToken cancellationToken) { var tcsSubscribed = new TaskCompletionSource <string>(); _api.Subscribed += (sender, message) => { tcsSubscribed.SetResult(message); return(tcsSubscribed.Task); }; // Subscribe var skipTask = _api.SubscribeToOrderBookUpdatesAsync(new[] { _btcUsd }, cancellationToken); await WhenAllTaskAreDone(timeoutMs, tcsSubscribed.Task); // Wait max n milliseconds for subscription return(tcsSubscribed.Task.IsCompletedSuccessfully); }
protected override async Task MessageLoopImpl() { try { await _websocketApi.ConnectAsync(CancellationToken); // First subscribe with websockets and ignore all the order events with // sequential number less than symbol's orderbook orders var subscriptionTask = new AsyncEventAwaiter <string>(ref _websocketApi.Subscribed) .Await(CancellationToken); var ordersListenerTask = _websocketApi.SubscribeToOrderBookUpdatesAsync( _configuration.SupportedCurrencySymbols.Select(s => s.ExchangeSymbol).ToList(), CancellationToken); await subscriptionTask; // Wait to be subscribed first var retrieveOrderBooksTask = Task.Run(async() => { foreach (var currencySymbol in _configuration.SupportedCurrencySymbols) { var orderBook = await _restApi.GetFullOrderBook( currencySymbol.ExchangeSymbol, CancellationToken); await HandleRetrievedOrderBook(currencySymbol.ExchangeSymbol, orderBook); } }); await Task.WhenAll(ordersListenerTask, retrieveOrderBooksTask); } finally { try { if (_websocketApi != null) { using (var cts = new CancellationTokenSource(5000)) { await _websocketApi.CloseConnectionAsync(cts.Token); } } } catch (Exception ex) { await Log.WriteErrorAsync(nameof(GdaxOrderBooksHarvester), "Could not close web sockets connection properly", ex); } } }