public async Task <Dictionary <string, int> > GetPendingMutationsAsync(GetPendingAnalyticsMutationsOptions?options = null)
        {
            options ??= new GetPendingAnalyticsMutationsOptions();
            _logger.LogInformation("Getting pending mutations.");
            try
            {
                var builder = new UriBuilder(_serviceUriProvider.GetRandomManagementUri());
                builder.Path += "analytics/node/agg/stats/remaining";
                var uri = builder.Uri;
                using var httpClient = _httpClientFactory.Create();
                var result = await httpClient.GetAsync(uri, options.TokenValue).ConfigureAwait(false);

                result.EnsureSuccessStatusCode();
                var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                var json = JToken.Parse(content);

                return(parseResult(json));
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "Failed to retrieve pending mutations.");
                throw;
            }
        }
        public async Task <DesignDocument> GetDesignDocumentAsync(string designDocName, DesignDocumentNamespace @namespace, GetDesignDocumentOptions?options = null)
        {
            options ??= GetDesignDocumentOptions.Default;
            var uri = GetUri(designDocName, @namespace);

            _logger.LogInformation("Attempting to get design document {_bucketName}/{designDocName} - {uri}",
                                   _redactor.MetaData(_bucketName), _redactor.MetaData(designDocName), _redactor.SystemData(uri));

            try
            {
                using var httpClient = _httpClientFactory.Create();

                var result = await httpClient.GetAsync(uri, options.TokenValue).ConfigureAwait(false);

                if (result.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new DesignDocumentNotFoundException(_bucketName, designDocName);
                }

                result.EnsureSuccessStatusCode();

                var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                var designDocument = JsonConvert.DeserializeObject <DesignDocument>(content);
                designDocument !.Name = designDocName;

                return(designDocument);
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "Failed to get design document {_bucketName}/{designDocName} - {uri}",
                                 _redactor.MetaData(_bucketName), _redactor.MetaData(designDocName), _redactor.SystemData(uri));
                throw;
            }
        }
예제 #3
0
        public async Task <UserAndMetaData> GetUserAsync(string username, GetUserOptions?options = null)
        {
            options ??= GetUserOptions.Default;
            var uri = GetUsersUri(options.DomainNameValue, username);

            _logger.LogInformation("Attempting to get user with username {username} - {uri}",
                                   _redactor.UserData(username), _redactor.SystemData(uri));

            try
            {
                // check user exists before trying to read content
                using var httpClient = _httpClientFactory.Create();
                var result = await httpClient.GetAsync(uri, options.TokenValue).ConfigureAwait(false);

                if (result.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new UserNotFoundException(username);
                }

                result.EnsureSuccessStatusCode();

                // get user from result
                var json = JObject.Parse(await result.Content.ReadAsStringAsync().ConfigureAwait(false));
                return(UserAndMetaData.FromJson(json));
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "Error trying to get user with username {username} - {uri}",
                                 _redactor.UserData(username), _redactor.SystemData(uri));
                throw;
            }
        }
        public override async Task <BucketConfig> GetClusterMapAsync(string bucketName, HostEndpoint hostEndpoint,
                                                                     CancellationToken cancellationToken)
        {
            var uri = new UriBuilder
            {
                Scheme = _context.ClusterOptions.EffectiveEnableTls ? Uri.UriSchemeHttps : Uri.UriSchemeHttp,
                Host   = hostEndpoint.Host,
                Port   = _context.ClusterOptions.EffectiveEnableTls
                    ? _context.ClusterOptions.BootstrapHttpPortTls
                    : _context.ClusterOptions.BootstrapHttpPort,
                Path = Path + bucketName
            };

            using var httpClient = _httpClientFactory.Create();

            using (var response = await httpClient.GetAsync(uri.Uri, cancellationToken).ConfigureAwait(false))
            {
                response.EnsureSuccessStatusCode();
                var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                var bucketConfig = await JsonSerializer
                                   .DeserializeAsync(stream, InternalSerializationContext.Default.BucketConfig, cancellationToken)
                                   .ConfigureAwait(false);

                bucketConfig !.ReplacePlaceholderWithBootstrapHost(uri.Host);
                return(bucketConfig);
            }
        }
예제 #5
0
        public async Task CreateBucketAsync(BucketSettings settings, CreateBucketOptions?options = null)
        {
            options ??= new CreateBucketOptions();
            var uri = GetUri();

            _logger.LogInformation("Attempting to create bucket with name {settings.Name} - {uri}",
                                   _redactor.MetaData(settings.Name), _redactor.SystemData(uri));

            try
            {
                // create bucket
                var content = new FormUrlEncodedContent(settings !.ToFormValues());
                using var httpClient = _httpClientFactory.Create();
                var result = await httpClient.PostAsync(uri, content, options.TokenValue).ConfigureAwait(false);

                if (result.IsSuccessStatusCode)
                {
                    return;
                }

                var body = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                var ctx = new ManagementErrorContext
                {
                    HttpStatus = result.StatusCode,
                    Message    = body,
                    Statement  = uri.ToString()
                };

                //Throw specific exception if a rate limiting exception is thrown.
                result.ThrowIfRateLimitingError(body, ctx);



                if (result.StatusCode == HttpStatusCode.BadRequest)
                {
                    if (body.IndexOf("Bucket with given name already exists",
                                     StringComparison.InvariantCultureIgnoreCase) >= 0)
                    {
                        throw new BucketExistsException(settings.Name);
                    }
                }

                //Throw any other error cases
                result.ThrowOnError(ctx);
            }
            catch (BucketExistsException)
            {
                _logger.LogError("Failed to create bucket with name {settings.Name} because it already exists",
                                 _redactor.MetaData(settings.Name));
                throw;
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "Failed to create bucket with name {settings.Name} - {uri}",
                                 _redactor.MetaData(settings.Name), _redactor.SystemData(uri));
                throw;
            }
        }
        public async Task <IEnumerable <ScopeSpec> > GetAllScopesAsync(GetAllScopesOptions?options = null)
        {
            options ??= GetAllScopesOptions.Default;
            var uri = GetUri(RestApi.GetScopes(_bucketName));

            _logger.LogInformation("Attempting to get all scopes - {uri}", _redactor.SystemData(uri));

            try
            {
                // get manifest
                using var httpClient = _httpClientFactory.Create();
                var result = await httpClient.GetAsync(uri, options.TokenValue).ConfigureAwait(false);

                var body = await result.Content.ReadAsStringAsync().ConfigureAwait(false);

                //Throw any other error cases
                if (result.StatusCode != HttpStatusCode.OK)
                {
                    var ctx = new ManagementErrorContext
                    {
                        HttpStatus = result.StatusCode,
                        Message    = body,
                        Statement  = uri.ToString()
                    };

                    //Throw specific exception if a rate limiting exception is thrown.
                    result.ThrowIfRateLimitingError(body, ctx);

                    result.ThrowOnError(ctx);
                }

                using var stream = await result.Content.ReadAsStreamAsync().ConfigureAwait(false);

                using var jsonReader = new JsonTextReader(new StreamReader(stream, Encoding.UTF8));

                // check scope & collection exists in manifest
                var json = await JToken.ReadFromAsync(jsonReader, options.TokenValue).ConfigureAwait(false);

                var scopes = json.SelectToken("scopes") !;

                return(scopes.Select(scope => new ScopeSpec(scope["name"]?.Value <string>())
                {
                    Collections = scope["collections"] !.Select(collection =>
                                                                new CollectionSpec(scope["name"]?.Value <string>(), collection["name"]?.Value <string>())
                    {
                        MaxExpiry = collection["maxTTL"] == null
                                ? (TimeSpan?)null
                                : TimeSpan.FromSeconds(collection["maxTTL"] !.Value <long>())
                    }
                                                                ).ToList()
                }).ToList());
        public async Task AllowQueryingAsync(string indexName, AllowQueryingSearchIndexOptions?options = null)
        {
            options ??= AllowQueryingSearchIndexOptions.Default;
            var baseUri = GetQueryControlUri(indexName, true);

            _logger.LogInformation("Trying to allow querying for index with name {indexName} - {baseUri}",
                                   _redactor.MetaData(indexName), _redactor.SystemData(baseUri));

            try
            {
                using var httpClient = _httpClientFactory.Create();
                var result = await httpClient.PostAsync(baseUri, null !, options.TokenValue).ConfigureAwait(false);

                //Handle any errors that may exist
                await CheckStatusAndThrowIfErrorsAsync(result, baseUri, indexName).ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                _logger.LogError(exception, "Failed to allow querying for index with name {indexName} - {baseUri}",
                                 _redactor.MetaData(indexName), _redactor.SystemData(baseUri));
                throw;
            }
        }
        private Task StartBackgroundTask()
        {
            // Ensure that we don't flow the ExecutionContext into the long running task below
            using var flowControl = ExecutionContext.SuppressFlow();

            return(Task.Run(async() =>
            {
                var delayMs = InitialDelayMs;

                var bucket = _bucket as BucketBase;

                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    try
                    {
                        var nodes = bucket?.Nodes.ToList().Shuffle();
                        while (nodes != null && nodes.Any())
                        {
                            try
                            {
                                var node = nodes.First();
                                nodes?.Remove(node);

                                _logger.LogDebug("HTTP Streaming with node {node}", node.EndPoint.Host);

                                var streamingUri = new UriBuilder()
                                {
                                    Scheme =
                                        _clusterOptions.EffectiveEnableTls ? Uri.UriSchemeHttps : Uri.UriSchemeHttp,
                                    Host = node.ManagementUri.Host,
                                    Port = node.ManagementUri.Port,
                                    Path = _streamingUriPath
                                };

                                using var httpClient = _httpClientFactory.Create();
                                httpClient.Timeout = Timeout.InfiniteTimeSpan;

                                var response = await httpClient.GetAsync(streamingUri.Uri,
                                                                         HttpCompletionOption.ResponseHeadersRead,
                                                                         _cancellationTokenSource.Token).ConfigureAwait(false);

                                response.EnsureSuccessStatusCode();

                                using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
                                if (stream.CanTimeout)
                                {
                                    //the stream itself can timeout if CanTimeout is true on a platform
                                    stream.ReadTimeout = Timeout.Infinite;
                                }

                                using var reader = new StreamReader(stream, Encoding.UTF8, false);

                                string?config;
                                while (!_cancellationTokenSource.IsCancellationRequested &&
                                       (config = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
                                {
                                    if (config != string.Empty)
                                    {
                                        _logger.LogDebug(LoggingEvents.ConfigEvent, config);
                                        config = config.Replace("$HOST", node.EndPoint.Host);
                                        var bucketConfig = JsonSerializer.Deserialize(config,
                                                                                      InternalSerializationContext.Default.BucketConfig) !;
                                        _configHandler.Publish(bucketConfig);
                                    }

                                    // on success, reset the exponential delay
                                    delayMs = InitialDelayMs;
                                }
                            }
                            catch (Exception e)
                            {
                                _logger.LogError(e, "HTTP Streaming error.");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        _logger.LogError(e, "HTTP Streaming error. (outer loop)");
                    }

                    // if we exited the inner loop, then all servers failed and we need to start over.
                    // however, we don't want to create a failstorm in the logs if the failure is 100%
                    // try again, but with an exponential delay of up to 10s.
                    await Task.Delay(delayMs).ConfigureAwait(false);
                    delayMs = Math.Min(delayMs * 10, MaxDelayMs);
                }
            }, _cancellationTokenSource.Token));
        }