예제 #1
0
 internal IndexBucketModel(BucketBase entity)
 {
     this.BucketId   = entity.BucketId;
     this.ModifyDate = entity.ModifyDate ?? entity.CreationDate;
     this.CreatedBy  = entity.CreatedBy;
     this.BucketName = entity.BucketName;
 }
예제 #2
0
        public IEnumerable <IScope> CreateScopes(BucketBase bucket, Manifest manifest)
        {
            if (bucket == null)
            {
                throw new ArgumentNullException(nameof(bucket));
            }
            if (manifest == null)
            {
                throw new ArgumentNullException(nameof(manifest));
            }

            foreach (var scopeDef in manifest.scopes)
            {
                var collections = new List <ICollection>();
                foreach (var collectionDef in scopeDef.collections)
                {
                    collections.Add(_collectionFactory.Create(bucket,
                                                              Convert.ToUInt32(collectionDef.uid, 16),
                                                              collectionDef.name,
                                                              scopeDef.name));
                }

                yield return(new Scope(scopeDef.name, scopeDef.uid, collections, bucket, _scopeLogger));
            }
        }
 internal CouchbaseCollection(BucketBase bucket, ClusterContext context, uint?cid, string name)
 {
     Cid      = cid;
     Name     = name;
     _bucket  = bucket;
     _context = context;
 }
예제 #4
0
        public Scope(ScopeDef?scopeDef, ICollectionFactory collectionFactory, BucketBase bucket, ILogger <Scope> logger)
        {
            _bucket = bucket ?? throw new ArgumentNullException(nameof(bucket));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            if (scopeDef != null)
            {
                Name = scopeDef.name;
                Id   = scopeDef.uid;

                _collections = new ConcurrentDictionary <string, ICouchbaseCollection>(
                    scopeDef.collections
                    .Select(p => collectionFactory.Create(bucket, this, Convert.ToUInt32(p.uid, 16), p.name))
                    .ToDictionary(x => x.Name, v => v));
            }
            else
            {
                Name = DefaultScopeName;
                Id   = DefaultScopeId;

                _collections = new ConcurrentDictionary <string, ICouchbaseCollection>();
                _collections.TryAdd(CouchbaseCollection.DefaultCollectionName,
                                    collectionFactory.Create(bucket, this, null, CouchbaseCollection.DefaultCollectionName));
            }

            _queryContext = $"{_bucket.Name}.{Name}";
        }
예제 #5
0
        // protected internal for a unit test seam
        protected internal virtual async Task <bool> RefreshCollectionId(BucketBase bucket, IOperation op)
        {
            try
            {
                var scope = await bucket.ScopeAsync(op.SName !).ConfigureAwait(false);

                if (await scope.CollectionAsync(op.CName !).ConfigureAwait(false) is IInternalCollection collection)
                {
                    //re-fetch the CID but do not allow retries in that path and force the CID update
                    await collection.PopulateCidAsync(false, true);

                    op.Reset();
                    op.Cid = collection.Cid;

                    return(true);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting new collection id.");
            }

            op.Reset();
            return(false);
        }
        // protected internal for a unit test seam
        protected internal virtual async Task <bool> RefreshCollectionId(BucketBase bucket, IOperation op)
        {
            try
            {
                var vBucket  = (VBucket)bucket.KeyMapper !.MapKey(op.Key);
                var endPoint = op.ReplicaIdx > 0 ? vBucket.LocateReplica(op.ReplicaIdx) : vBucket.LocatePrimary();

                if (bucket.Nodes.TryGet(endPoint !, out var clusterNode))
                {
                    var scope      = bucket.Scope(op.SName);
                    var collection = (CouchbaseCollection)scope.Collection(op.CName);

                    var newCid = await clusterNode.GetCid($"{op.SName}.{op.CName}").ConfigureAwait(false);

                    collection.Cid = newCid;

                    op.Reset();
                    op.Cid = newCid;

                    return(true);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting new collection id.");
            }

            op.Reset();
            return(false);
        }
        public async Task RetryAsync(BucketBase bucket, IOperation operation, CancellationToken token = default,
                                     TimeSpan?timeout = null)
        {
            try
            {
                var backoff = ControlledBackoff.Create();
                do
                {
                    try
                    {
                        operation.Attempts++;
                        await bucket.SendAsync(operation, token, timeout).ConfigureAwait(false);

                        break;
                    }
                    catch (CouchbaseException e)
                    {
                        if (e is IRetryable)
                        {
                            var reason = e.ResolveRetryReason();
                            if (reason.AlwaysRetry())
                            {
                                if (token.IsCancellationRequested)
                                {
                                    token.ThrowIfCancellationRequested();
                                }

                                _logger.LogDebug("Retrying op {opaque}/{key} because {reason}.", operation.Opaque,
                                                 operation.Key, reason);

                                await backoff.Delay(operation).ConfigureAwait(false);

                                continue;
                            }

                            var strategy = operation.RetryStrategy;
                            var action   = strategy.RetryAfter(operation, reason);

                            if (action.DurationValue.HasValue)
                            {
                                _logger.LogDebug("Retrying op {opaque}/{key} because {reason}.", operation.Opaque,
                                                 operation.Key, reason);

                                await Task.Delay(action.DurationValue.Value, token).ConfigureAwait(false);
                            }
                            else
                            {
                                break; //don't retry
                            }
                        }
                        else
                        {
                            throw;
                        }
                    }
                } while (true);
            }
            catch (TaskCanceledException) { ThrowTimeoutException(operation, timeout); }
            catch (OperationCanceledException) { ThrowTimeoutException(operation, timeout); }
        }
예제 #8
0
 public Scope(string name, string id, IEnumerable <ICouchbaseCollection> collections, BucketBase bucket, ILogger <Scope> logger)
 {
     Name         = name ?? throw new ArgumentNullException(nameof(name));
     Id           = id ?? throw new ArgumentNullException(nameof(id));
     _collections = new ConcurrentDictionary <string, ICouchbaseCollection>(collections.ToDictionary(x => x.Name, v => v));
     _bucket      = bucket ?? throw new ArgumentNullException(nameof(bucket));
     _logger      = logger ?? throw new ArgumentNullException(nameof(logger));
 }
        public IScope CreateDefaultScope(BucketBase bucket)
        {
            if (bucket == null)
            {
                throw new ArgumentNullException(nameof(bucket));
            }

            return(new Scope(null, _collectionFactory, bucket, _scopeLogger));
        }
예제 #10
0
 public CouchbaseCollection(BucketBase bucket, ITypeTranscoder transcoder, ILogger <CouchbaseCollection> logger,
                            uint?cid, string name, string scopeName)
 {
     Cid         = cid;
     Name        = name ?? throw new ArgumentNullException(nameof(name));
     _bucket     = bucket ?? throw new ArgumentNullException(nameof(bucket));
     Logger      = logger ?? throw new ArgumentNullException(nameof(logger));
     _transcoder = transcoder ?? throw new ArgumentNullException(nameof(transcoder));
     ScopeName   = scopeName;
 }
예제 #11
0
        public Scope(string name, BucketBase bucket, ICollectionFactory collectionFactory, ILogger <Scope> logger)
        {
            Name               = name ?? throw new ArgumentNullException(nameof(name));
            _bucket            = bucket ?? throw new ArgumentNullException(nameof(bucket));
            _logger            = logger ?? throw new ArgumentNullException(nameof(logger));
            _collectionFactory = collectionFactory ?? throw new ArgumentNullException(nameof(collectionFactory));

            _collections  = new ConcurrentDictionary <string, ICouchbaseCollection>();
            _queryContext = $"{_bucket.Name}.{Name}";
        }
예제 #12
0
        public Scope(string name, BucketBase bucket, ICollectionFactory collectionFactory, ILogger <Scope> logger)
        {
            Name               = name ?? throw new ArgumentNullException(nameof(name));
            _bucket            = bucket ?? throw new ArgumentNullException(nameof(bucket));
            _logger            = logger ?? throw new ArgumentNullException(nameof(logger));
            _collectionFactory = collectionFactory ?? throw new ArgumentNullException(nameof(collectionFactory));

            _collections   = new ConcurrentDictionary <string, ICouchbaseCollection>();
            _queryContext  = $"default:{_bucket.Name.EscapeIfRequired()}.{name.EscapeIfRequired()}";
            IsDefaultScope = name == DefaultScopeName;
        }
예제 #13
0
        public void Unsubscribe(BucketBase bucket)
        {
            ConfigChanged -= bucket.ConfigUpdated;

            if (bucket is MemcachedBucket)
            {
                if (_httpConfigListeners.TryRemove(bucket.Name, out HttpStreamingConfigListener listener))
                {
                    listener.Dispose();
                }
            }
        }
예제 #14
0
        public void Subscribe(BucketBase bucket)
        {
            ConfigChanged += bucket.ConfigUpdated;

            if (bucket is MemcachedBucket)
            {
                var httpListener = new HttpStreamingConfigListener(bucket.Name, _configuration, _httpClient, this, TokenSource.Token);
                if (_httpConfigListeners.TryAdd(bucket.Name, httpListener))
                {
                    httpListener.StartListening();
                }
            }
        }
 internal CouchbaseCollection(BucketBase bucket, ITypeTranscoder transcoder, ILogger <CouchbaseCollection> logger,
                              ILogger <GetResult> getLogger, IRedactor redactor,
                              uint?cid, string name, IScope scope)
 {
     Cid         = cid;
     Name        = name ?? throw new ArgumentNullException(nameof(name));
     _bucket     = bucket ?? throw new ArgumentNullException(nameof(bucket));
     Logger      = logger ?? throw new ArgumentNullException(nameof(logger));
     Redactor    = redactor ?? throw new ArgumentNullException(nameof(redactor));
     _transcoder = transcoder ?? throw new ArgumentNullException(nameof(transcoder));
     _getLogger  = getLogger ?? throw new ArgumentNullException(nameof(getLogger));
     Scope       = scope ?? throw new ArgumentNullException(nameof(scope));
 }
예제 #16
0
 internal CouchbaseCollection(BucketBase bucket, IOperationConfigurator operationConfigurator, ILogger <CouchbaseCollection> logger,
                              ILogger <GetResult> getLogger, IRedactor redactor,
                              uint?cid, string name, IScope scope, IRequestTracer tracer)
 {
     Cid      = cid;
     Name     = name ?? throw new ArgumentNullException(nameof(name));
     _bucket  = bucket ?? throw new ArgumentNullException(nameof(bucket));
     Logger   = logger ?? throw new ArgumentNullException(nameof(logger));
     Redactor = redactor ?? throw new ArgumentNullException(nameof(redactor));
     _operationConfigurator = operationConfigurator ?? throw new ArgumentNullException(nameof(operationConfigurator));
     _getLogger             = getLogger ?? throw new ArgumentNullException(nameof(getLogger));
     _tracer = tracer;
     Scope   = scope ?? throw new ArgumentNullException(nameof(scope));
 }
예제 #17
0
        public IScope CreateDefaultScope(BucketBase bucket)
        {
            if (bucket == null)
            {
                throw new ArgumentNullException(nameof(bucket));
            }

            var collections = new List <ICollection>
            {
                _collectionFactory.Create(bucket, null,
                                          CouchbaseCollection.DefaultCollectionName, Scope.DefaultScopeName)
            };

            return(new Scope(Scope.DefaultScopeName, "0", collections, bucket, _scopeLogger));
        }
        public void Unsubscribe(BucketBase bucket)
        {
            lock (_configChangedSubscribers)
            {
                _configChangedSubscribers.Remove(bucket);
            }

            if (bucket is MemcachedBucket)
            {
                if (_httpConfigListeners.TryRemove(bucket.Name, out var listener))
                {
                    listener.Dispose();
                }
            }
        }
        public IEnumerable <IScope> CreateScopes(BucketBase bucket, Manifest manifest)
        {
            if (bucket == null)
            {
                throw new ArgumentNullException(nameof(bucket));
            }
            if (manifest == null)
            {
                throw new ArgumentNullException(nameof(manifest));
            }

            foreach (var scopeDef in manifest.scopes)
            {
                yield return(new Scope(scopeDef, _collectionFactory, bucket, _scopeLogger));
            }
        }
예제 #20
0
        public void Subscribe(BucketBase bucket)
        {
            ConfigChanged += bucket.ConfigUpdated;

            if (bucket is MemcachedBucket)
            {
                var httpListener = _configListenerFactory.Create(bucket.Name, this);
                if (_httpConfigListeners.TryAdd(bucket.Name, httpListener))
                {
                    httpListener.StartListening();

                    // Dispose the listener when we're stopped
                    TokenSource.Token.Register(state =>
                    {
                        ((HttpStreamingConfigListener)state).Dispose();
                    }, httpListener);
                }
            }
        }
        // protected internal for a unit test seam
        protected internal virtual async Task <bool> RefreshCollectionId(BucketBase bucket, IOperation op)
        {
            try
            {
                var scope = await bucket.ScopeAsync(op.SName).ConfigureAwait(false);

                var collection = (IInternalCollection)await scope.CollectionAsync(op.CName).ConfigureAwait(false);

                var newCid = await((IInternalScope)scope).GetCidAsync($"{op.SName}.{op.CName}").ConfigureAwait(false);
                collection.Cid = newCid;

                op.Reset();
                op.Cid = newCid;

                return(true);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting new collection id.");
            }

            op.Reset();
            return(false);
        }
 public ICollection Create(BucketBase bucket, uint?cid, string name, string scopeName) =>
 new CouchbaseCollection(bucket, _transcoder, _logger, cid, name, scopeName);
 internal CouchbaseCollection(BucketBase bucket, uint?cid, string name)
 {
     Cid     = cid;
     Name    = name;
     _bucket = bucket;
 }
        public async Task RetryAsync(BucketBase bucket, IOperation operation, CancellationToken token = default)
        {
            try
            {
                var backoff = ControlledBackoff.Create();
                do
                {
                    try
                    {
                        operation.Attempts++;

                        try
                        {
                            await bucket.SendAsync(operation, token).ConfigureAwait(false);

                            break;
                        }
                        catch (CollectionOutdatedException e)
                        {
                            // We catch CollectionOutdatedException separately from the CouchbaseException catch block
                            // in case RefreshCollectionId fails. This causes that failure to trigger normal retry logic.

                            _logger.LogInformation("Updating stale manifest for collection and retrying.", e);
                            if (!await RefreshCollectionId(bucket, operation)
                                .ConfigureAwait(false))
                            {
                                // rethrow if we fail to refresh he collection ID so we hit retry logic
                                // otherwise we'll loop and retry immediately
                                throw;
                            }
                        }
                    }
                    catch (CouchbaseException e)
                    {
                        if (e is IRetryable)
                        {
                            var reason = e.ResolveRetryReason();
                            if (reason.AlwaysRetry())
                            {
                                token.ThrowIfCancellationRequested();

                                _logger.LogDebug("Retrying op {opaque}/{key} because {reason} and always retry.",
                                                 operation.Opaque,
                                                 operation.Key, reason);

                                await backoff.Delay(operation).ConfigureAwait(false);

                                operation.Reset();
                                continue;
                            }

                            var strategy = operation.RetryStrategy;
                            var action   = strategy.RetryAfter(operation, reason);

                            if (action.Retry)
                            {
                                _logger.LogDebug("Retrying op {opaque}/{key} because {reason} and action duration.",
                                                 operation.Opaque,
                                                 operation.Key, reason);

                                operation.Reset();
                                await Task.Delay(action.DurationValue.Value, token).ConfigureAwait(false);
                            }
                            else
                            {
                                throw; //don't retry
                            }
                        }
                        else
                        {
                            throw;
                        }
                    }
                } while (true);
            }
            catch (OperationCanceledException) { ThrowTimeoutException(operation, operation.Timeout); }
        }
예제 #25
0
        public async Task RetryAsync(BucketBase bucket, IOperation operation, CancellationTokenPair tokenPair = default)
        {
            try
            {
                var backoff = ControlledBackoff.Create();
                operation.Token = tokenPair;

                do
                {
                    tokenPair.ThrowIfCancellationRequested();

                    try
                    {
                        operation.Attempts++;

                        try
                        {
                            await bucket.SendAsync(operation, tokenPair).ConfigureAwait(false);

                            break;
                        }
                        catch (CouchbaseException e) when(e is ScopeNotFoundException || e is CollectionNotFoundException)
                        {
                            // We catch CollectionOutdatedException separately from the CouchbaseException catch block
                            // in case RefreshCollectionId fails. This causes that failure to trigger normal retry logic.

                            _logger.LogInformation("Updating stale manifest for collection and retrying.", e);
                            if (!await RefreshCollectionId(bucket, operation)
                                .ConfigureAwait(false))
                            {
                                // rethrow if we fail to refresh he collection ID so we hit retry logic
                                // otherwise we'll loop and retry immediately
                                throw;
                            }
                        }
                    }
                    catch (CouchbaseException e) when(e is IRetryable && !tokenPair.IsCancellationRequested)
                    {
                        var reason = e.ResolveRetryReason();

                        if (reason.AlwaysRetry())
                        {
                            _logger.LogDebug("Retrying op {opaque}/{key} because {reason} and always retry.",
                                             operation.Opaque,
                                             operation.Key, reason);

                            await backoff.Delay(operation).ConfigureAwait(false);

                            // no need to reset op in this case as it was not actually sent
                            if (reason != RetryReason.CircuitBreakerOpen)
                            {
                                operation.Reset();
                            }

                            continue;
                        }

                        var strategy = operation.RetryStrategy;
                        var action   = strategy.RetryAfter(operation, reason);

                        if (action.Retry)
                        {
                            _logger.LogDebug("Retrying op {opaque}/{key} because {reason} and action duration.",
                                             operation.Opaque,
                                             operation.Key, reason);

                            // Reset first so operation is not marked as sent if canceled during the delay
                            operation.Reset();

                            await Task.Delay(action.DurationValue.GetValueOrDefault(), tokenPair)
                            .ConfigureAwait(false);
                        }
                        else
                        {
                            throw; //don't retry
                        }
                    }
                } while (true);
            }
            catch (OperationCanceledException) when(!tokenPair.IsExternalCancellation)
            {
                ThrowHelper.ThrowTimeoutException(operation, new KeyValueErrorContext
                {
                    BucketName      = operation.BucketName,
                    ClientContextId = operation.Opaque.ToString(),
                    DocumentKey     = operation.Key,
                    Cas             = operation.Cas,
                    CollectionName  = operation.CName,
                    ScopeName       = operation.SName,
                    OpCode          = operation.OpCode
                });
            }
        }
 public ICouchbaseCollection Create(BucketBase bucket, IScope scope, string name) =>
 new CouchbaseCollection(bucket, _operationConfigurator, _logger, _getLogger, _redactor, name, scope, _tracer);
예제 #27
0
 public ICouchbaseCollection Create(BucketBase bucket, IScope scope, uint?cid, string name) =>
 new CouchbaseCollection(bucket, _transcoder, _logger, _getLogger, _redactor, cid, name, scope);
예제 #28
0
        public async Task RetryAsync(BucketBase bucket, IOperation operation, CancellationTokenPair tokenPair = default)
        {
            try
            {
                var backoff = ControlledBackoff.Create();

                do
                {
                    tokenPair.ThrowIfCancellationRequested();

                    try
                    {
                        if (operation.Attempts > 1)
                        {
                            MetricTracker.KeyValue.TrackRetry(operation.OpCode);
                        }

                        try
                        {
                            await bucket.SendAsync(operation, tokenPair).ConfigureAwait(false);

                            break;
                        }
                        catch (CouchbaseException e) when(operation is not GetCid &&
                                                          (e is ScopeNotFoundException ||
                                                           e is CollectionNotFoundException))
                        {
                            // We catch CollectionOutdatedException separately from the CouchbaseException catch block
                            // in case RefreshCollectionId fails. This causes that failure to trigger normal retry logic.

                            LogRefreshingCollectionId(e);
                            if (!await RefreshCollectionId(bucket, operation)
                                .ConfigureAwait(false))
                            {
                                // rethrow if we fail to refresh he collection ID so we hit retry logic
                                // otherwise we'll loop and retry immediately
                                throw;
                            }
                        }
                    }
                    catch (CouchbaseException e) when(e is IRetryable && !tokenPair.IsCancellationRequested)
                    {
                        var reason = e.ResolveRetryReason();

                        if (reason.AlwaysRetry())
                        {
                            LogRetryDueToAlwaysRetry(operation.Opaque, _redactor.UserData(operation.Key), reason);

                            await backoff.Delay(operation).ConfigureAwait(false);

                            // no need to reset op in this case as it was not actually sent
                            if (reason != RetryReason.CircuitBreakerOpen)
                            {
                                operation.Reset();
                            }
                            operation.IncrementAttempts(reason);

                            continue;
                        }

                        var strategy = operation.RetryStrategy;
                        var action   = strategy.RetryAfter(operation, reason);

                        if (action.Retry)
                        {
                            LogRetryDueToDuration(operation.Opaque, _redactor.UserData(operation.Key), reason);

                            // Reset first so operation is not marked as sent if canceled during the delay
                            operation.Reset();
                            operation.IncrementAttempts(reason);

                            await Task.Delay(action.DurationValue.GetValueOrDefault(), tokenPair)
                            .ConfigureAwait(false);
                        }
                        else
                        {
                            throw; //don't retry
                        }
                    }
                } while (true);
            }
            catch (OperationCanceledException) when(!tokenPair.IsExternalCancellation)
            {
                MetricTracker.KeyValue.TrackTimeout(operation.OpCode);

                ThrowHelper.ThrowTimeoutException(operation, new KeyValueErrorContext
                {
                    BucketName      = operation.BucketName,
                    ClientContextId = operation.Opaque.ToStringInvariant(),
                    DocumentKey     = operation.Key,
                    Cas             = operation.Cas,
                    CollectionName  = operation.CName,
                    ScopeName       = operation.SName,
                    OpCode          = operation.OpCode,
                    DispatchedFrom  = operation.LastDispatchedFrom,
                    DispatchedTo    = operation.LastDispatchedTo,
                    RetryReasons    = operation.RetryReasons
                });
            }
        }
예제 #29
0
 public IScope CreateScope(string name, BucketBase bucket)
 {
     return(new Scope(name, bucket, _collectionFactory, _scopeLogger));
 }