Exemple #1
0
        public async Task <QueryResult <string> > TranslateLegacyTokenRules(string id, QueryOptions q, CancellationToken ct = default(CancellationToken))
        {
            var res = await _client.Get($"/v1/acl/rules/translate/{id}", q).Execute(ct).ConfigureAwait(false);

            return(new QueryResult <string>(res, res.Response));
        }
Exemple #2
0
 /// <summary>
 /// Node gets all sessions for a node
 /// </summary>
 /// <param name="node">The node ID</param>
 /// <param name="q">Customized query options</param>
 /// <returns>A query result containing the list of sessions, or an empty query result if no sessions exist</returns>
 public Task <QueryResult <SessionEntry[]> > Node(string node, QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <SessionEntry[]>(string.Format("/v1/session/node/{0}", node), q).Execute(ct));
 }
Exemple #3
0
        /// <summary>
        /// Gets an existing ACL Token from Consul
        /// </summary>
        /// <param name="id">The Accessor ID of the ACL Token to get</param>
        /// <param name="queryOptions">Customized query options</param>
        /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
        /// <returns>A query result containing the requested ACL Token</returns>
        public async Task <QueryResult <TokenEntry> > Read(string id, QueryOptions queryOptions, CancellationToken ct = default(CancellationToken))
        {
            var res = await _client.Get <TokenActionResult>($"/v1/acl/token/{id}", queryOptions).Execute(ct).ConfigureAwait(false);

            return(new QueryResult <TokenEntry>(res, res.Response));
        }
Exemple #4
0
        /// <summary>
        /// Service is used to query catalog entries for a given service
        /// </summary>
        /// <param name="service">The service ID</param>
        /// <param name="tag">A tag to filter on</param>
        /// <param name="q">Customized query options</param>
        /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
        /// <returns>A list of service instances</returns>
        public Task <QueryResult <CatalogService[]> > Service(string service, string tag, QueryOptions q, CancellationToken ct)
        {
            var req = _client.Get <CatalogService[]>(string.Format("/v1/catalog/service/{0}", service), q);

            if (!string.IsNullOrEmpty(tag))
            {
                req.Params["tag"] = tag;
            }
            return(req.Execute(ct));
        }
Exemple #5
0
        /// <summary>
        /// Info looks up a single session
        /// </summary>
        /// <param name="id">The session ID to look up</param>
        /// <param name="q">Customized query options</param>
        /// <returns>A query result containing the session information, or an empty query result if the session entry does not exist</returns>
        public async Task <QueryResult <SessionEntry> > Info(string id, QueryOptions q, CancellationToken ct = default(CancellationToken))
        {
            var res = await _client.Get <SessionEntry[]>(string.Format("/v1/session/info/{0}", id), q).Execute(ct).ConfigureAwait(false);

            return(new QueryResult <SessionEntry>(res, res.Response != null && res.Response.Length > 0 ? res.Response[0] : null));
        }
Exemple #6
0
 /// <summary>
 /// RaftGetConfiguration is used to query the current Raft peer set.
 /// </summary>
 public Task <QueryResult <RaftConfiguration> > RaftGetConfiguration(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <RaftConfiguration>("/v1/operator/raft/configuration", q).Execute(ct));
 }
Exemple #7
0
 /// <summary>
 /// Nodes is used to query all the known nodes
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>A list of all nodes</returns>
 public Task <QueryResult <Node[]> > Nodes(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <Node[]>("/v1/catalog/nodes", q).Execute(ct));
 }
Exemple #8
0
        /// <summary>
        /// Gets the requested ACL Role from Consul
        /// </summary>
        /// <param name="name">The Name of the ACL Role to get</param>
        /// <param name="queryOptions">Customised query options</param>
        /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
        /// <returns>A query result containing the requested ACL Role</returns>
        public async Task <QueryResult <RoleEntry> > ReadByName(string name, QueryOptions queryOptions, CancellationToken ct = default(CancellationToken))
        {
            var res = await _client.Get <RoleEntry>($"/v1/acl/role/name/{name}", queryOptions).Execute(ct).ConfigureAwait(false);

            return(new QueryResult <RoleEntry>(res, res.Response));
        }
Exemple #9
0
 /// <summary>
 /// Query is used to do a GET request against an endpoint and deserialize the response into an interface using standard Consul conventions.
 /// </summary>
 /// <param name="endpoint">The URL endpoint to access</param>
 /// <param name="q">Custom query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>The data returned by the custom endpoint</returns>
 public Task <QueryResult <dynamic> > Query(string endpoint, QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <dynamic>(endpoint, q).Execute(ct));
 }
Exemple #10
0
        /// <summary>
        /// Acquire attempts to reserve a slot in the semaphore, blocking until success, interrupted via CancellationToken or if an error is encountered.
        /// A provided CancellationToken can be used to abort the attempt.
        /// There is no notification that the semaphore slot has been lost, but IsHeld may be set to False at any time due to session invalidation, communication errors, operator intervention, etc.
        /// It is NOT safe to assume that the slot is held until Release() unless the Session is specifically created without any associated health checks.
        /// By default Consul sessions prefer liveness over safety and an application must be able to handle the session being lost.
        /// </summary>
        /// <param name="ct">The cancellation token to cancel semaphore acquisition</param>
        public CancellationToken Acquire(CancellationToken ct)
        {
            lock (_lock)
            {
                try
                {
                    if (IsHeld)
                    {
                        // Check if we already hold the lock
                        throw new SemaphoreHeldException();
                    }
                    // Don't overwrite the CancellationTokenSource until AFTER we've tested for holding, since there might be tasks that are currently running for this lock.
                    if (_cts.IsCancellationRequested)
                    {
                        _cts.Dispose();
                        _cts = new CancellationTokenSource();
                    }
                    _cts        = new CancellationTokenSource();
                    LockSession = Opts.Session;

                    // Check if we need to create a session first
                    if (string.IsNullOrEmpty(Opts.Session))
                    {
                        try
                        {
                            Opts.Session      = CreateSession().GetAwaiter().GetResult();
                            _sessionRenewTask = _client.Session.RenewPeriodic(Opts.SessionTTL, Opts.Session, WriteOptions.Default, _cts.Token);
                            LockSession       = Opts.Session;
                        }
                        catch (Exception ex)
                        {
                            throw new InvalidOperationException("Failed to create session", ex);
                        }
                    }
                    else
                    {
                        LockSession = Opts.Session;
                    }

                    var contender = _client.KV.Acquire(ContenderEntry(LockSession)).GetAwaiter().GetResult().Response;
                    if (!contender)
                    {
                        throw new ApplicationException("Failed to make contender entry");
                    }

                    var qOpts = new QueryOptions()
                    {
                        WaitTime = Opts.SemaphoreWaitTime
                    };

                    var attempts = 0;
                    var start    = DateTime.UtcNow;

                    while (!ct.IsCancellationRequested)
                    {
                        if (attempts > 0 && Opts.SemaphoreTryOnce)
                        {
                            var elapsed = DateTime.UtcNow.Subtract(start);
                            if (elapsed > qOpts.WaitTime)
                            {
                                throw new SemaphoreMaxAttemptsReachedException("SemaphoreTryOnce is set and the semaphore is already at maximum capacity");
                            }
                            qOpts.WaitTime -= elapsed;
                        }

                        attempts++;

                        QueryResult <KVPair[]> pairs;
                        try
                        {
                            pairs = _client.KV.List(Opts.Prefix, qOpts).GetAwaiter().GetResult();
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException("Failed to read prefix", ex);
                        }

                        var lockPair = FindLock(pairs.Response);
                        if (lockPair.Flags != SemaphoreFlagValue)
                        {
                            throw new SemaphoreConflictException();
                        }

                        var semaphoreLock = DecodeLock(lockPair);
                        if (semaphoreLock.Limit != Opts.Limit)
                        {
                            throw new SemaphoreLimitConflictException(
                                      string.Format("Semaphore limit conflict (lock: {0}, local: {1})", semaphoreLock.Limit,
                                                    Opts.Limit),
                                      semaphoreLock.Limit, Opts.Limit);
                        }

                        PruneDeadHolders(semaphoreLock, pairs.Response);
                        if (semaphoreLock.Holders.Count >= semaphoreLock.Limit)
                        {
                            qOpts.WaitIndex = pairs.LastIndex;
                            continue;
                        }

                        semaphoreLock.Holders[LockSession] = true;

                        var newLock = EncodeLock(semaphoreLock, lockPair.ModifyIndex);

                        if (ct.IsCancellationRequested)
                        {
                            _cts.Cancel();
                            throw new TaskCanceledException();
                        }

                        // Handle the case of not getting the lock
                        if (!_client.KV.CAS(newLock).GetAwaiter().GetResult().Response)
                        {
                            continue;
                        }

                        IsHeld = true;
                        MonitorLock(LockSession);
                        return(_cts.Token);
                    }
                    throw new SemaphoreNotHeldException("Unable to acquire the semaphore with Consul");
                }
                finally
                {
                    if (ct.IsCancellationRequested || (!IsHeld && !string.IsNullOrEmpty(Opts.Session)))
                    {
                        _cts.Cancel();
                        _client.KV.Delete(ContenderEntry(LockSession).Key).GetAwaiter().GetResult();
                        if (_sessionRenewTask != null)
                        {
                            try
                            {
                                _sessionRenewTask.Wait();
                            }
                            catch (AggregateException)
                            {
                                // Ignore AggregateExceptions from the tasks during Release, since if the Renew task died, the developer will be Super Confused if they see the exception during Release.
                            }
                        }
                        else
                        {
                            _client.Session.Destroy(Opts.Session).Wait();
                        }
                        Opts.Session = null;
                    }
                }
            }
        }
Exemple #11
0
        /// <summary>
        /// monitorLock is a long running routine to monitor a semaphore ownership
        /// It sets IsHeld to false if we lose our slot.
        /// </summary>
        /// <param name="lockSession">The session ID to monitor</param>
        private Task MonitorLock(string lockSession)
        {
            return(Task.Run(async() =>
            {
                try
                {
                    var opts = new QueryOptions()
                    {
                        Consistency = ConsistencyMode.Consistent
                    };
                    _retries = Opts.MonitorRetries;
                    while (IsHeld && !_cts.Token.IsCancellationRequested)
                    {
                        try
                        {
                            var pairs = await _client.KV.List(Opts.Prefix, opts).ConfigureAwait(false);
                            if (pairs.Response != null)
                            {
                                _retries = Opts.MonitorRetries;

                                var lockPair = FindLock(pairs.Response);
                                var semaphoreLock = DecodeLock(lockPair);
                                PruneDeadHolders(semaphoreLock, pairs.Response);

                                // Slot is no longer held! Shut down everything.
                                if (!semaphoreLock.Holders.ContainsKey(lockSession))
                                {
                                    IsHeld = false;
                                    _cts.Cancel();
                                    return;
                                }

                                // Semaphore is still held, start a blocking query
                                opts.WaitIndex = pairs.LastIndex;
                                continue;
                            }
                            // Failsafe in case the KV store is unavailable
                            else
                            {
                                IsHeld = false;
                                _cts.Cancel();
                                return;
                            }
                        }
                        catch (Exception)
                        {
                            if (_retries > 0)
                            {
                                await Task.Delay(Opts.MonitorRetryTime, _cts.Token).ConfigureAwait(false);
                                _retries--;
                                opts.WaitIndex = 0;
                                continue;
                            }
                            throw;
                        }
                    }
                }
                finally
                {
                    IsHeld = false;
                }
            }));
        }
Exemple #12
0
 /// <summary>
 /// List is used to get all the ACL tokens
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>A write result containing the list of all ACLs</returns>
 public Task <QueryResult <ACLEntry[]> > List(QueryOptions q, CancellationToken ct)
 {
     return(_client.Get <ACLEntry[]>("/v1/acl/list", q).Execute(ct));
 }
Exemple #13
0
 /// <summary>
 /// List is used to get all the ACL tokens
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <returns>A write result containing the list of all ACLs</returns>
 public Task <QueryResult <ACLEntry[]> > List(QueryOptions q)
 {
     return(List(q, CancellationToken.None));
 }
Exemple #14
0
 /// <summary>
 /// Info is used to query for information about an ACL token
 /// </summary>
 /// <param name="id">The ACL ID to request information about</param>
 /// <param name="q">Customized query options</param>
 /// <returns>A query result containing the ACL entry matching the provided ID, or a query result with a null response if no token matched the provided ID</returns>
 public Task <QueryResult <ACLEntry> > Info(string id, QueryOptions q)
 {
     return(Info(id, q, CancellationToken.None));
 }
        /// <summary>
        /// MonitorLock is a long running routine to monitor a lock ownership. It sets IsHeld to false if we lose our leadership.
        /// </summary>
        private Task MonitorLock()
        {
            return(Task.Factory.StartNew(async() =>
            {
                // Copy a reference to _cts since we could end up destroying it before this method returns
                var cts = _cts;
                try
                {
                    var opts = new QueryOptions()
                    {
                        Consistency = ConsistencyMode.Consistent
                    };
                    _retries = Opts.MonitorRetries;
                    while (IsHeld && !cts.Token.IsCancellationRequested)
                    {
                        try
                        {
                            // Check to see if the current session holds the lock
                            var pair = await _client.KV.Get(Opts.Key, opts).ConfigureAwait(false);
                            if (pair.Response != null)
                            {
                                _retries = Opts.MonitorRetries;

                                // Lock is no longer held! Shut down everything.
                                if (pair.Response.Session != LockSession)
                                {
                                    IsHeld = false;
                                    DisposeCancellationTokenSource();
                                    return;
                                }

                                // Lock is still held, start a blocking query
                                opts.WaitIndex = pair.LastIndex;
                                continue;
                            }
                            else
                            {
                                // Failsafe in case the KV store is unavailable
                                IsHeld = false;
                                DisposeCancellationTokenSource();
                                return;
                            }
                        }
                        catch (ConsulRequestException)
                        {
                            if (_retries > 0)
                            {
                                await Task.Delay(Opts.MonitorRetryTime, cts.Token).ConfigureAwait(false);
                                _retries--;
                                opts.WaitIndex = 0;
                                continue;
                            }
                            throw;
                        }
                        catch (OperationCanceledException)
                        {
                            // Ignore and retry since this could be the underlying HTTPClient being swapped out/disposed of.
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
                finally
                {
                    IsHeld = false;
                    DisposeCancellationTokenSource();
                }
            }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap());
        }
Exemple #16
0
 /// <summary>
 /// List gets all active sessions
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <returns>A query result containing the list of sessions, or an empty query result if no sessions exist</returns>
 public QueryResult <SessionEntry[]> List(QueryOptions q)
 {
     return(_client.CreateQuery <SessionEntry[]>("/v1/session/list", q).Execute());
 }
        /// <summary>
        /// Lists the existing ACL Policies in Consul
        /// </summary>
        /// <param name="queryOptions">Customised query options</param>
        /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
        /// <returns>A query result containing an array of ACL Policies</returns>
        public async Task <QueryResult <PolicyEntry[]> > List(QueryOptions queryOptions, CancellationToken ct = default(CancellationToken))
        {
            var res = await _client.Get <PolicyEntry[]>("/v1/acl/policies", queryOptions).Execute(ct).ConfigureAwait(false);

            return(new QueryResult <PolicyEntry[]>(res, res.Response));
        }
Exemple #18
0
 /// <summary>
 /// Node gets all sessions for a node
 /// </summary>
 /// <param name="node">The node ID</param>
 /// <param name="q">Customized query options</param>
 /// <returns>A query result containing the list of sessions, or an empty query result if no sessions exist</returns>
 public QueryResult <SessionEntry[]> Node(string node, QueryOptions q)
 {
     return(_client.CreateQuery <SessionEntry[]>(string.Format("/v1/session/node/{0}", node), q).Execute());
 }
Exemple #19
0
 /// <summary>
 /// KeyringList is used to list the gossip keys installed in the cluster
 /// </summary>
 public Task <QueryResult <KeyringResponse[]> > KeyringList(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <KeyringResponse[]>("/v1/operator/keyring", q).Execute(ct));
 }
Exemple #20
0
 internal GetRequest <TOut> Get <TOut>(string path, QueryOptions opts = null, IEncodable filter = null)
 {
     return(new GetRequest <TOut>(this, path, opts ?? QueryOptions.Default, filter));
 }
Exemple #21
0
 /// <summary>
 /// Services is used to query for all known services
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>A list of all services</returns>
 public Task <QueryResult <Dictionary <string, string[]> > > Services(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <Dictionary <string, string[]> >("/v1/catalog/services", q).Execute(ct));
 }
Exemple #22
0
 internal GetRequest Get(string path, QueryOptions opts = null)
 {
     return(new GetRequest(this, path, opts ?? QueryOptions.Default));
 }
Exemple #23
0
 /// <summary>
 /// Node is used to query for service information about a single node
 /// </summary>
 /// <param name="node">The node name</param>
 /// <param name="q">Customized query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>The node information including a list of services</returns>
 public Task <QueryResult <CatalogNode> > Node(string node, QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <CatalogNode>(string.Format("/v1/catalog/node/{0}", node), q).Execute(ct));
 }
 public Task <QueryResult <PreparedQueryExecuteResponse> > Execute(string queryIDOrName, QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <PreparedQueryExecuteResponse>(string.Format("/v1/query/{0}/execute", queryIDOrName), q).Execute(ct));
 }
Exemple #25
0
 /// <summary>
 /// List gets all active sessions
 /// </summary>
 /// <param name="q">Customized query options</param>
 /// <returns>A query result containing the list of sessions, or an empty query result if no sessions exist</returns>
 public Task <QueryResult <SessionEntry[]> > List(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <SessionEntry[]>("/v1/session/list", q).Execute(ct));
 }
 public Task <QueryResult <PreparedQueryDefinition[]> > Get(string queryID, QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <PreparedQueryDefinition[]>(string.Format("/v1/query/{0}", queryID), q).Execute(ct));
 }
Exemple #27
0
        /// <summary>
        /// Lock attempts to acquire the lock and blocks while doing so.
        /// Providing a CancellationToken can be used to abort the lock attempt.
        /// There is no notification that the lock has been lost, but IsHeld may be set to False at any time due to session invalidation, communication errors, operator intervention, etc.
        /// It is NOT safe to assume that the lock is held until Unlock() unless the Session is specifically created without any associated health checks.
        /// Users of the Lock object should check the IsHeld property before entering the critical section of their code, e.g. in a "while (myLock.IsHeld) {criticalsection}" block.
        /// By default Consul sessions prefer liveness over safety and an application must be able to handle the lock being lost.
        /// </summary>
        /// <param name="ct">The cancellation token to cancel lock acquisition</param>
        public CancellationToken Acquire(CancellationToken ct)
        {
            lock (_lock)
            {
                try
                {
                    if (IsHeld)
                    {
                        // Check if we already hold the lock
                        throw new LockHeldException();
                    }

                    // Don't overwrite the CancellationTokenSource until AFTER we've tested for holding, since there might be tasks that are currently running for this lock.
                    if (_cts.IsCancellationRequested)
                    {
                        _cts.Dispose();
                        _cts = new CancellationTokenSource();
                    }

                    // Check if we need to create a session first
                    if (string.IsNullOrEmpty(Opts.Session))
                    {
                        try
                        {
                            Opts.Session      = CreateSession().GetAwaiter().GetResult();
                            _sessionRenewTask = _client.Session.RenewPeriodic(Opts.SessionTTL, Opts.Session,
                                                                              WriteOptions.Default, _cts.Token);
                            LockSession = Opts.Session;
                        }
                        catch (Exception ex)
                        {
                            throw new ConsulRequestException("Failed to create session", ex);
                        }
                    }
                    else
                    {
                        LockSession = Opts.Session;
                    }

                    var qOpts = new QueryOptions()
                    {
                        WaitTime = Opts.LockWaitTime
                    };

                    var attempts = 0;

                    while (!ct.IsCancellationRequested)
                    {
                        if (attempts > 0 && Opts.LockTryOnce)
                        {
                            throw new LockMaxAttemptsReachedException("LockTryOnce is set and the lock is already held or lock delay is in effect");
                        }

                        attempts++;

                        QueryResult <KVPair> pair;
                        try
                        {
                            pair = _client.KV.Get(Opts.Key, qOpts).GetAwaiter().GetResult();
                        }
                        catch (Exception ex)
                        {
                            throw new ConsulRequestException("Failed to read lock key", ex);
                        }

                        if (pair.Response != null)
                        {
                            if (pair.Response.Flags != LockFlagValue)
                            {
                                throw new LockConflictException();
                            }

                            // Already locked by this session
                            if (pair.Response.Session == LockSession)
                            {
                                // Don't restart MonitorLock if this session already holds the lock
                                if (IsHeld)
                                {
                                    return(_cts.Token);
                                }
                                IsHeld = true;
                                MonitorLock();
                                return(_cts.Token);
                            }

                            // If it's not empty, some other session must have the lock
                            if (!string.IsNullOrEmpty(pair.Response.Session))
                            {
                                qOpts.WaitIndex = pair.LastIndex;
                                continue;
                            }
                        }

                        // If the code executes this far, no other session has the lock, so try to lock it
                        var kvPair = LockEntry(Opts.Session);
                        var locked = _client.KV.Acquire(kvPair).GetAwaiter().GetResult().Response;

                        // KV acquisition succeeded, so the session now holds the lock
                        if (locked)
                        {
                            IsHeld = true;
                            MonitorLock();
                            return(_cts.Token);
                        }

                        // Handle the case of not getting the lock
                        if (ct.IsCancellationRequested)
                        {
                            _cts.Cancel();
                            throw new TaskCanceledException();
                        }

                        // Failed to get the lock, determine why by querying for the key again
                        qOpts.WaitIndex = 0;
                        pair            = _client.KV.Get(Opts.Key, qOpts).GetAwaiter().GetResult();

                        // If the session is not null, this means that a wait can safely happen using a long poll
                        if (pair.Response != null && pair.Response.Session != null)
                        {
                            qOpts.WaitIndex = pair.LastIndex;
                            continue;
                        }

                        // If the session is null and the lock failed to acquire, then it means a lock-delay is in effect and a timed wait must be used to avoid a hot loop.
                        try { Task.Delay(DefaultLockRetryTime, ct).Wait(ct); }
                        catch (TaskCanceledException) { /* Ignore TaskTaskCanceledException */ }
                    }
                    throw new LockNotHeldException("Unable to acquire the lock with Consul");
                }
                finally
                {
                    if (ct.IsCancellationRequested || (!IsHeld && !string.IsNullOrEmpty(Opts.Session)))
                    {
                        _cts.Cancel();
                        if (_sessionRenewTask != null)
                        {
                            try
                            {
                                _sessionRenewTask.Wait();
                            }
                            catch (AggregateException)
                            {
                                // Ignore AggregateExceptions from the tasks during Release, since if the Renew task died, the developer will be Super Confused if they see the exception during Release.
                            }
                        }
                        else
                        {
                            _client.Session.Destroy(Opts.Session).Wait();
                        }
                        Opts.Session = null;
                    }
                }
            }
        }
 public Task <QueryResult <PreparedQueryDefinition[]> > List(QueryOptions q, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <PreparedQueryDefinition[]>("/v1/query", q).Execute(ct));
 }
Exemple #29
0
 /// <summary>
 /// Lists the existing ACL Tokens in Consul
 /// </summary>
 /// <param name="queryOptions">Customized query options</param>
 /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param>
 /// <returns>A query result containing an array of ACL Tokens</returns>
 public Task <QueryResult <TokenEntry[]> > List(QueryOptions queryOptions, CancellationToken ct = default(CancellationToken))
 {
     return(_client.Get <TokenEntry[]>("/v1/acl/tokens", queryOptions).Execute(ct));
 }
Exemple #30
0
        /// <summary>
        /// monitorLock is a long running routine to monitor a semaphore ownership
        /// It sets IsHeld to false if we lose our slot.
        /// </summary>
        /// <param name="lockSession">The session ID to monitor</param>
        private Task MonitorLock(string lockSession)
        {
            return(Task.Factory.StartNew(async() =>
            {
                try
                {
                    var opts = new QueryOptions()
                    {
                        Consistency = ConsistencyMode.Consistent
                    };
                    _retries = Opts.MonitorRetries;
                    while (IsHeld && !_cts.Token.IsCancellationRequested)
                    {
                        try
                        {
                            var pairs = await _client.KV.List(Opts.Prefix, opts).ConfigureAwait(false);
                            if (pairs.Response != null)
                            {
                                _retries = Opts.MonitorRetries;

                                var lockPair = FindLock(pairs.Response);
                                var semaphoreLock = DecodeLock(lockPair);
                                PruneDeadHolders(semaphoreLock, pairs.Response);

                                // Slot is no longer held! Shut down everything.
                                if (!semaphoreLock.Holders.ContainsKey(lockSession))
                                {
                                    IsHeld = false;
                                    DisposeCancellationTokenSource();
                                    return;
                                }

                                // Semaphore is still held, start a blocking query
                                opts.WaitIndex = pairs.LastIndex;
                                continue;
                            }
                            // Failsafe in case the KV store is unavailable
                            else
                            {
                                IsHeld = false;
                                DisposeCancellationTokenSource();
                                return;
                            }
                        }
                        catch (ConsulRequestException)
                        {
                            if (_retries > 0)
                            {
                                await Task.Delay(Opts.MonitorRetryTime, _cts.Token).ConfigureAwait(false);
                                _retries--;
                                opts.WaitIndex = 0;
                                continue;
                            }
                            throw;
                        }
                        catch (OperationCanceledException)
                        {
                            // Ignore and retry since this could be the underlying HTTPClient being swapped out/disposed of.
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
                finally
                {
                    IsHeld = false;
                }
            }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap());
        }