Exemple #1
0
        /// <summary>
        /// Keeps trying to checkout a guild (with backoff) until either maxTimeout has been hit,
        /// or a value has been returned that's not Locked.
        /// </summary>
        /// <param name="repo">A repo. May not be null.</param>
        /// <param name="guildId">An id associated with a guild.</param>
        /// <param name="maxTimeout">The maximum amount of time to spend waiting for this to unlock.</param>
        /// <param name="recycleResult">A preallocated result that should be returned if passed in.</param>
        /// <returns>The result.</returns>
        public static async Task <GuildCheckoutResult> WaitForNotLockedCheckout(
            this IGuildRepository repo,
            Snowflake guildId,
            TimeSpan maxTimeout,
            GuildCheckoutResult recycleResult = null)
        {
            Stopwatch timer     = new Stopwatch();
            var       retVal    = recycleResult ?? new GuildCheckoutResult();
            TimeSpan  nextDelay = TimeSpan.FromMilliseconds(1);

            timer.Start();
            retVal = await repo.Checkout(guildId, retVal);

            while (retVal.Result == GuildCheckoutResult.ResultType.Locked &&
                   timer.Elapsed + nextDelay < maxTimeout)
            {
                await Task.Delay(nextDelay);

                retVal = await repo.Checkout(guildId, retVal);

                nextDelay *= 1.5;
            }

            return(retVal);
        }
        /// <summary>
        /// Checkout out a <see cref="Guild"/>.
        /// </summary>
        /// <param name="guildId">An id representing a guild.</param>
        /// <param name="recycleResult">A preallocated result that should be returned if passed in.</param>
        /// <returns>The borrowed guild.</returns>
        public async Task <GuildCheckoutResult> Checkout(Snowflake guildId, GuildCheckoutResult recycleResult = null)
        {
            var retVal = recycleResult ?? new GuildCheckoutResult();

            try
            {
                string blobName   = AzureBlobGuildRepository.GetBlobName(guildId);
                var    blobClient = this.blobContainerClient.GetBlockBlobClient(blobName);

                // Aquire a lease on the blob
                var blobLeaseClient = blobClient.GetBlobLeaseClient();
                var leaseResult     = await blobLeaseClient.AcquireAsync(AzureBlobGuildRepository.BlobLeaseDuration).ConfigureAwait(false);

                var lease = leaseResult.Value;

                Guild guild;
                using (var sourceStream = await blobClient.OpenReadAsync())
                    using (var streamReader = new StreamReader(sourceStream))
                        using (var jsonReader = new JsonTextReader(streamReader))
                        {
                            guild = GuildConverter.FromJToken(guildId, await JObject.ReadFromAsync(jsonReader));
                        }

                retVal.ToSuccess(new Borrowed <Guild>(
                                     isntance: guild,
                                     data: lease,
                                     onReturn: this.ReturnGuild));

                return(retVal);
            }
            catch (RequestFailedException e)
            {
                if (e.Status == AzureBlobGuildRepository.NotFoundStatus)
                {
                    retVal.ToDoesNotExist();
                    return(retVal);
                }
                else if (e.Status == AzureBlobGuildRepository.ConflictStatus && "LeaseAlreadyPresent".Equals(e.ErrorCode, StringComparison.OrdinalIgnoreCase))
                {
                    retVal.ToLocked();
                    return(retVal);
                }
                else
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// Checkout out or create a <see cref="Guild"/> if one does not exist.
        /// </summary>
        /// <param name="guildId">An id representing a guild.</param>
        /// <param name="recycleResult">A preallocated result that should be returned if passed in.</param>
        /// <returns>The borrowed guild.</returns>
        public async Task <GuildCheckoutResult> Checkout(Snowflake guildId, GuildCheckoutResult recycleResult = null)
        {
            var retVal = recycleResult ?? new GuildCheckoutResult();

            try
            {
                var sourceStream = new FileStream(
                    FileBasedGuildRepository.GetFilePath(guildId),
                    FileMode.Open,
                    FileAccess.ReadWrite,
                    FileShare.None,
                    bufferSize: 4096,
                    useAsync: true);

                var streamReader = new StreamReader(sourceStream);
                var jsonReader   = new JsonTextReader(streamReader);
                var guild        = GuildConverter.FromJToken(guildId, await JObject.ReadFromAsync(jsonReader));

                retVal.ToSuccess(new Borrowed <Guild>(
                                     isntance: guild,
                                     data: sourceStream,
                                     onReturn: FileBasedGuildRepository.ReturnGuild));
                return(retVal);
            }
            catch (FileNotFoundException)
            {
                retVal.ToDoesNotExist();
                return(retVal);
            }
            catch (IOException e)
            {
                if (e.HResult == FileBasedGuildRepository.LockedFileHRResult)
                {
                    retVal.ToLocked();
                    return(retVal);
                }
                else
                {
                    throw;
                }
            }
        }