示例#1
0
        public async Task <string> ReserveAny(string scope, string ownerToken, TimeSpan?lease = null, string confirmationToken = null)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }
            if (ownerToken == null)
            {
                throw new ArgumentNullException("ownerToken");
            }

            var now = Clock.Now();

            using (var db = CreateReservationServiceDbContext())
            {
                var reservedValues = db.Set <ReservedValue>();
                var expiration     = now + (lease ?? TimeSpan.FromMinutes(1));

                ReservedValue valueToReserve = null;
                do
                {
                    valueToReserve = reservedValues.SingleOrDefault(r => r.OwnerToken == ownerToken &&
                                                                    r.ConfirmationToken == confirmationToken &&
                                                                    r.Expiration != null);

                    if (valueToReserve == null)
                    {
                        valueToReserve = GetValueToReserve(reservedValues, scope, now);
                    }

                    if (valueToReserve == null)
                    {
                        return(null);
                    }

                    valueToReserve.Expiration = expiration;
                    valueToReserve.OwnerToken = ownerToken;

                    if (confirmationToken != null)
                    {
                        valueToReserve.ConfirmationToken = confirmationToken;
                    }

                    try
                    {
                        db.SaveChanges();
                        return(valueToReserve.Value);
                    }
                    catch (Exception exception)
                    {
                        if (!exception.IsConcurrencyException() || exception.IsUniquenessConstraint())
                        {
                            throw;
                        }
                        db.Entry(valueToReserve).State = EntityState.Unchanged;
                    }
                } while (valueToReserve != null); //retry on concurrency exception
            }
            return(null);
        }
示例#2
0
 protected bool Equals(ReservedValue other)
 {
     return(string.Equals(OwnerToken, other.OwnerToken) &&
            string.Equals(Value, other.Value) &&
            string.Equals(ConfirmationToken, other.ConfirmationToken) &&
            string.Equals(Scope, other.Scope) &&
            IsEqualTo(Expiration, other.Expiration));
 }
示例#3
0
 private static bool VerifyOwnerToken(string ownerToken, ReservedValue reservedValue)
 {
     return(reservedValue.OwnerToken == ownerToken);
 }
示例#4
0
        public Task <bool> Reserve(string value, string scope, string ownerToken, TimeSpan?lease = null)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }
            if (ownerToken == null)
            {
                throw new ArgumentNullException("ownerToken");
            }

            var now = Clock.Now();

            return(Task.Run(() =>
            {
                using (var db = CreateReservationServiceDbContext())
                {
                    var reservedValues = db.Set <ReservedValue>();

                    var expiration = now + (lease ?? TimeSpan.FromMinutes(1));

                    // see if there is a pre-existing lease by the same actor
                    var reservedValue = reservedValues.SingleOrDefault(r => r.Scope == scope &&
                                                                       r.Value == value);

                    if (reservedValue == null)
                    {
                        // if not, create a new ticket
                        reservedValue = new ReservedValue
                        {
                            OwnerToken = ownerToken,
                            Scope = scope,
                            Value = value,
                            Expiration = expiration,
                            ConfirmationToken = value
                        };
                        reservedValues.Add(reservedValue);
                    }
                    else if (reservedValue.Expiration == null)
                    {
                        return reservedValue.OwnerToken == ownerToken;
                    }
                    else if (reservedValue.OwnerToken == ownerToken)
                    {
                        // if it's the same, extend the lease
                        reservedValue.Expiration = expiration;
                    }
                    else if (reservedValue.Expiration < now)
                    {
                        // take ownership if the reserved value has expired
                        reservedValue.OwnerToken = ownerToken;
                        reservedValue.Expiration = expiration;
                    }
                    else
                    {
                        return false;
                    }

                    try
                    {
                        db.SaveChanges();

                        return true;
                    }
                    catch (Exception exception)
                    {
                        if (!exception.IsConcurrencyException())
                        {
                            throw;
                        }
                    }

                    return false;
                }
            }));
        }