Example #1
0
        internal async Task <long> AtomicIncDecAsync(string key, long amount, CancellationToken token = default)
        {
            long count   = 0;
            bool updated = false;

            await ExecUtils.RetryUntilTrueAsync(async() =>
            {
                var entry = await GetEntryAsync(key, token);

                if (entry == null)
                {
                    count = amount;
                    entry = CreateTableEntry(key, Serialize(count));
                    try
                    {
                        updated = (await table.ExecuteAsync(TableOperation.Insert(entry), token)).HttpStatusCode == (int)HttpStatusCode.NoContent;
                    }
                    catch (StorageException ex)
                    {
                        if (!ex.HasStatus(HttpStatusCode.Conflict))
                        {
                            throw;
                        }
                    }
                }
                else
                {
                    count      = Deserialize <long>(entry.Data) + amount;
                    entry.Data = Serialize(count);
                    var op     = TableOperation.Replace(entry);
                    try
                    {
                        var result = (await table.ExecuteAsync(op, null, null, token)).HttpStatusCode;
                        updated    = result == (int)HttpStatusCode.OK || result == (int)HttpStatusCode.NoContent;
                    }
                    catch (StorageException ex)
                    {
                        if (!ex.HasStatus(HttpStatusCode.PreconditionFailed))
                        {
                            throw;
                        }
                    }
                }

                return(updated);
            }, TimeSpan.FromSeconds(30));

            return(count);
        }