public PhotoTaggingProcessor() { _requestQueue = new BufferBlock <PhotoAnalysisRequest>(); _resultQueue = new BufferBlock <PhotoAnalysisResult>(); _requestQueueListeners = new List <Action>(); _photoAnayser = new PhotoAnayser(); _rateLimiter = new F0RateLimiter(); AddListenersToQueue(); }
/// <summary> /// Construct an <see cref="IBinanceApiUser"/> instance providing an API /// key and optional API secret. The API secret is not required for /// the user stream methods, but is required for other account methods. /// </summary> /// <param name="apiKey">The user's API key.</param> /// <param name="apiSecret">The user's API secret (optional, but required for signing).</param> /// <param name="rateLimiter">The rate limiter (auto-configured).</param> /// <param name="options">The JSON API options.</param> public BinanceApiUser(string apiKey, string apiSecret = null, IApiRateLimiter rateLimiter = null, IOptions <BinanceApiOptions> options = null) { Throw.IfNullOrWhiteSpace(apiKey, nameof(apiKey)); ApiKey = apiKey; if (!string.IsNullOrWhiteSpace(apiSecret)) { _hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)); } RateLimiter = rateLimiter; var opt = options?.Value ?? new BinanceApiOptions(); // Configure order rate limiter. RateLimiter?.Configure(TimeSpan.FromDays(opt.OrderRateLimit.DurationDays), opt.OrderRateLimit.Count); // Configure order burst rate limiter. RateLimiter?.Configure(TimeSpan.FromSeconds(opt.OrderRateLimit.BurstDurationSeconds), opt.OrderRateLimit.BurstCount); }
/// <summary> /// Constructor. /// </summary> /// <param name="rateLimiter">The rate limiter (auto configured).</param> /// <param name="options">The options.</param> /// <param name="logger">The logger.</param> internal BinanceHttpClient(IApiRateLimiter rateLimiter = null, IOptions <BinanceApiOptions> options = null, ILogger <BinanceHttpClient> logger = null) { RateLimiter = rateLimiter ?? new ApiRateLimiter(); Options = options?.Value ?? new BinanceApiOptions(); _logger = logger; // Configure request rate limiter. RateLimiter.Configure(TimeSpan.FromMinutes(Options.RequestRateLimit.DurationMinutes), Options.RequestRateLimit.Count); // Configure request burst rate limiter. RateLimiter.Configure(TimeSpan.FromSeconds(Options.RequestRateLimit.BurstDurationSeconds), Options.RequestRateLimit.BurstCount); _httpClient = new HttpClient { BaseAddress = new Uri(EndpointUrl) }; var version = GetType().Assembly.GetName().Version; var versionString = $"{version.Major}.{version.Minor}.{version.Build}{(version.Revision > 0 ? $".{version.Revision}" : string.Empty)}"; _httpClient.DefaultRequestHeaders.Add("User-Agent", $"Binance/{versionString} (.NET; +https://github.com/sonvister/Binance)"); }
/// <summary> /// Constructor. /// </summary> /// <param name="timestampProvider">The timestamp provider.</param> /// <param name="rateLimiter">The rate limiter (auto configured).</param> /// <param name="options">The options.</param> /// <param name="logger">The logger.</param> internal BinanceHttpClient(ITimestampProvider timestampProvider = null, IApiRateLimiter rateLimiter = null, IOptions <BinanceApiOptions> options = null, ILogger <BinanceHttpClient> logger = null) : base(logger) { TimestampProvider = timestampProvider ?? new TimestampProvider(); RateLimiter = rateLimiter ?? new ApiRateLimiter(); var apiOptions = options?.Value ?? new BinanceApiOptions(); DefaultRecvWindow = apiOptions.RecvWindowDefault ?? default; TimestampProvider.TimestampOffsetRefreshPeriod = TimeSpan.FromMinutes(apiOptions.TimestampOffsetRefreshPeriodMinutes); try { // Configure request rate limiter. RateLimiter.Configure(TimeSpan.FromMinutes(apiOptions.RequestRateLimit.DurationMinutes), apiOptions.RequestRateLimit.Count); // Configure request burst rate limiter. RateLimiter.Configure(TimeSpan.FromSeconds(apiOptions.RequestRateLimit.BurstDurationSeconds), apiOptions.RequestRateLimit.BurstCount); } catch (Exception e) { var message = $"{nameof(BinanceHttpClient)}: Failed to configure request rate limiter."; Logger?.LogError(e, message); throw new BinanceApiException(message, e); } var uri = new Uri(EndpointUrl); try { _httpClient = new HttpClient { BaseAddress = uri, Timeout = TimeSpan.FromSeconds(apiOptions.HttpClientTimeoutDefaultSeconds) }; } catch (Exception e) { var message = $"{nameof(BinanceHttpClient)}: Failed to create HttpClient."; Logger?.LogError(e, message); throw new BinanceApiException(message, e); } if (apiOptions.ServicePointManagerConnectionLeaseTimeoutMilliseconds > 0) { try { // FIX: Singleton HttpClient doesn't respect DNS changes. // https://github.com/dotnet/corefx/issues/11224 var sp = ServicePointManager.FindServicePoint(uri); sp.ConnectionLeaseTimeout = apiOptions.ServicePointManagerConnectionLeaseTimeoutMilliseconds; } catch (Exception e) { var message = $"{nameof(BinanceHttpClient)}: Failed to set {nameof(ServicePointManager)}.ConnectionLeaseTimeout."; Logger?.LogError(e, message); throw new BinanceApiException(message, e); } } try { var version = GetType().Assembly.GetName().Version; var versionString = $"{version.Major}.{version.Minor}.{version.Build}{(version.Revision > 0 ? $".{version.Revision}" : string.Empty)}"; _httpClient.DefaultRequestHeaders.Add("User-Agent", $"Binance/{versionString} (.NET; +https://github.com/sonvister/Binance)"); } catch (Exception e) { var message = $"{nameof(BinanceHttpClient)}: Failed to set User-Agent."; Logger?.LogError(e, message); throw new BinanceApiException(message, e); } }
private async Task <string> RequestAsync(HttpMethod method, BinanceHttpRequest request, CancellationToken token = default, IApiRateLimiter rateLimiter = null) { Throw.IfNull(request, nameof(request)); token.ThrowIfCancellationRequested(); var requestMessage = request.CreateMessage(method); _logger?.LogDebug($"{nameof(BinanceHttpClient)}.{nameof(RequestAsync)}: [{method.Method}] \"{requestMessage.RequestUri}\""); await(rateLimiter ?? RateLimiter).DelayAsync(request.RateLimitWeight, token) .ConfigureAwait(false); using (var response = await _httpClient.SendAsync(requestMessage, token).ConfigureAwait(false)) { if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); _logger?.LogDebug($"{nameof(BinanceHttpClient)}: \"{json}\""); return(json); } if (response.StatusCode == HttpStatusCode.GatewayTimeout) { throw new BinanceUnknownStatusException(); } var error = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); var errorCode = 0; string errorMessage = null; // ReSharper disable once InvertIf if (!string.IsNullOrWhiteSpace(error) && error.IsJsonObject()) { try // to parse server error response. { var jObject = JObject.Parse(error); errorCode = jObject["code"]?.Value <int>() ?? 0; errorMessage = jObject["msg"]?.Value <string>(); } catch (Exception e) { _logger?.LogError(e, $"{nameof(BinanceHttpClient)}.{nameof(RequestAsync)} failed to parse server error response: \"{error}\""); } } switch (response.StatusCode) { case (HttpStatusCode)429: throw new BinanceRequestRateLimitExceededException(response.ReasonPhrase, errorCode, errorMessage); case (HttpStatusCode)418: throw new BinanceRequestRateLimitIpBanException(response.ReasonPhrase, errorCode, errorMessage); default: throw new BinanceHttpException(response.StatusCode, response.ReasonPhrase, errorCode, errorMessage); } } }
public Task <string> DeleteAsync(BinanceHttpRequest request, CancellationToken token = default, IApiRateLimiter rateLimiter = null) { return(RequestAsync(HttpMethod.Delete, request, token, rateLimiter)); }
public Task <string> PutAsync(BinanceHttpRequest request, CancellationToken token = default, IApiRateLimiter rateLimiter = null) { return(RequestAsync(HttpMethod.Put, request, rateLimiter ?? RateLimiter, token)); }