public void Create_NoLeaseExists_LeaseCreated( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { var actual = repo.Create(lease, ctx); actual.Should().BeTrue(); } }
public void Create_LeaseAlreadyExists_FalseReturned( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { repo.Create(lease, ctx); var actual = repo.Create(lease, ctx); actual.Should().BeFalse(); } }
public void TryObtainLock_NoLeaseExists_LockObtained( ILeaseService service, ISystemContext ctx, ElasticLease lease, TestIndexUtils contactIndex) { using (contactIndex) { ElasticLease winner; service.TryObtainLock(lease, ctx, out winner).Should().BeTrue(); lease.ShouldBeEquivalentTo(winner); } }
public virtual bool TryObtainLock( ElasticLease challenger, ISystemContext ctx, out ElasticLease winner) { // NOTE: The approach here is to fail immediately if someone else already has the lock. Else // we try and obtain the lock. If in the very unlikely/unlucky scenario that a lock is obtained // between the first check and then the grab, we try again (recurse). The likely hood of many // recursions there for is very very unlikely, so there is currently no guard against that. var currentLease = this.leaseRepository.Get(challenger.ResourceId, ctx); // there is no current lease if (currentLease == null) { var esChallenger = challenger; if (this.leaseRepository.Create(esChallenger, ctx)) // 'create only' ES query so will fail if we were beaten to it { winner = challenger; return true; } else { // someone just beat us to it, so have another go... return this.TryObtainLock(challenger, ctx, out winner); } } // lease is already held, and not by the challenger... if (!currentLease.HasExpired(this.dateTime.UtcNow) && !currentLease.IsOwnedBy(challenger.Owner)) { winner = currentLease; return false; } // lease has either expired, or is held by the current challenger owner and needs extending... if (!currentLease.IsOwnedBy(challenger.Owner) || (currentLease.IsOwnedBy(challenger.Owner) && currentLease.Expires >= challenger.Expires)) { if (!this.leaseRepository.SaveOptimistically(challenger, ctx)) // ES (upsert) using optimistic concurrency, so will fail if we were beaten to it { // someone just beat us to it, so have another go... return this.TryObtainLock(challenger, ctx, out winner); } } winner = challenger; return true; }
public void TryObtainLock_ActiveLeaseExistsBySameOwner_LockObtained( ILeaseService service, ISystemContext ctx, ElasticLease activeLease, TestIndexUtils contactIndex, IFixture fixture ) { using (contactIndex) { service.TryObtainLock(activeLease, ctx, out activeLease); var activeLease2 = new ElasticLease( activeLease.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(2), activeLease.Owner, activeLease.Version); ElasticLease winner; service.TryObtainLock(activeLease2, ctx, out winner); activeLease2.ShouldBeEquivalentTo(winner); } }
public void TryObtainLock_InactiveLeaseExistsByDifferentOwner_LockObtained( ILeaseService service, ISystemContext ctx, ElasticLease owner1InactiveLease, TestIndexUtils contactIndex, IFixture fixture) { using (contactIndex) { service.TryObtainLock(owner1InactiveLease, ctx, out owner1InactiveLease).Should().BeTrue(); var owner2ActiveLease = new ElasticLease( owner1InactiveLease.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(2), fixture.Create<ElasticLeaseOwner>(), owner1InactiveLease.Version); ElasticLease winner; service.TryObtainLock(owner2ActiveLease, ctx, out winner).Should().BeTrue(); owner2ActiveLease.ShouldBeEquivalentTo(winner); } }
public void TryObtainLock_ActiveLeaseExistsByDifferentOwner_LockRefused( ILeaseService service, ISystemContext ctx, ElasticLease owner1ActiveLease, TestIndexUtils contactIndex, IFixture fixture) { using (contactIndex) { ElasticLease winner; service.TryObtainLock(owner1ActiveLease, ctx, out winner).Should().BeTrue(); var owner2ActiveLease = new ElasticLease( winner.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(1), fixture.Create<ElasticLeaseOwner>(), winner.Version); service.TryObtainLock(owner2ActiveLease, ctx, out winner).Should().BeFalse(); } }
public void Extend_LeaseExistsVersionNotChanged_LeaseExtended( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { repo.Create(lease, ctx); var extendedLease = new ElasticLease( lease.ResourceId, lease.Expires + TimeSpan.FromHours(2), lease.Owner, lease.Version); var actual = repo.SaveOptimistically(extendedLease, ctx); actual.Should().BeTrue(); } }
protected virtual LockAttemptStatus TryLockContact( Guid id, ElasticLease challengerLease, ISystemContext ctx, out ElasticLease newLease) { var status = this.contactLeaseService.TryObtainLock(challengerLease, ctx, out newLease) ? LockAttemptStatus.Success : LockAttemptStatus.AlreadyLocked; return status; }
public void Extend_InactiveLeaseExistsButLeaseGrabbedByDifferentOwner_LeaseNotExtended( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex, IFixture fixture) { using (contactIndex) { // expired lease exists with owner1. repo.Create(lease, ctx); // simulate owner2 taking the lease... var changedLease = new ElasticLease( lease.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(5), fixture.Create<ElasticLeaseOwner>(), lease.Version); repo.SaveOptimistically(changedLease, ctx); // now owner 1 tries to extend what it thinks is it's lease... var actual = repo.SaveOptimistically(lease, ctx); actual.Should().BeFalse(); } }
public void Extend_NoLeaseExists_LeaseCreatedAndSuccessful( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { var actual = repo.SaveOptimistically(lease, ctx); actual.Should().BeTrue(); } }
public void Delete_LeaseExists_LeaseDeleted( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { repo.Create(lease, ctx); repo.Delete(lease.ResourceId, ctx); repo.Get(lease.ResourceId, ctx).Should().BeNull(); } }
public void Get_LeaseAlreadyExists_LeaseIsReturned( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex) { using (contactIndex) { repo.Create(lease, ctx); var actual = repo.Get(lease.ResourceId, ctx); actual.Should().NotBeNull(); actual.ShouldBeEquivalentTo(lease); } }
public virtual bool Extend(ElasticLease lease, TimeSpan leaseDuration, ISystemContext ctx, out ElasticLease currentLease) { var newLease = new ElasticLease(lease.ResourceId, this.dateTime.UtcNow + leaseDuration, lease.Owner); return this.TryObtainLock(newLease, ctx, out currentLease); }
public void Extend_InactiveLeaseExistsThenLeaseGrabbedBySameOwner_LeaseNotExtended( IConcurrencyControlRepository<ElasticLease> repo, ElasticLease lease, ISystemContext ctx, TestIndexUtils contactIndex, IFixture fixture) { using (contactIndex) { // expired lease exists with owner1. repo.Create(lease, ctx); // simulate owner1 (in a different thread/process I guess) taking the lease... var changedLease = new ElasticLease( lease.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(5), lease.Owner, lease.Version); repo.SaveOptimistically(changedLease, ctx); // version will get incremented // now owner 1 tries to extend what it thinks is it's lease, this should eventually be allowed... var actual = repo.SaveOptimistically(lease, ctx); actual.Should().BeFalse(); } }
public void TryObtainLock_InactiveLeaseExistsBySameOwner_LockObtained( ILeaseService service, ISystemContext ctx, ElasticLease inactiveLease, TestIndexUtils contactIndex) { using (contactIndex) { // write inactive lease service.TryObtainLock(inactiveLease, ctx, out inactiveLease).Should().BeTrue(); var activeLease = new ElasticLease( inactiveLease.ResourceId, DateTime.UtcNow + TimeSpan.FromHours(1), inactiveLease.Owner, inactiveLease.Version); ElasticLease winner; service.TryObtainLock(activeLease, ctx, out winner).Should().BeTrue(); activeLease.ShouldBeEquivalentTo(winner); } }
protected virtual LockAttemptStatus TryLockContact( Guid id, ElasticLeaseOwner targetLeaseOwner, TimeSpan leaseDuration, ISystemContext ctx, out ElasticLease newLease) { // TODO: this is a bit crap var leaseExpiration = (this.dateTime.UtcNow + ElasticAnalyticsSettings.MaxAcceptedClockDeviation + leaseDuration); var challengerLease = new ElasticLease(id, leaseExpiration, targetLeaseOwner); return this.TryLockContact(id, challengerLease, ctx, out newLease); }