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); }
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)); }
private static bool VerifyOwnerToken(string ownerToken, ReservedValue reservedValue) { return(reservedValue.OwnerToken == ownerToken); }
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; } })); }