public ContactService(
            IRepository<ElasticContact> contactRepo,
            IContactIdentityMapService contactIdentityService,
            ILeaseService contactLeaseService,
            IDateTimeController dateTime)
        {
            if (contactRepo == null)
            {
                throw new ArgumentNullException("contactRepo");
            }

            if (contactIdentityService == null)
            {
                throw new ArgumentNullException("contactIdentityService");
            }

            if (contactLeaseService == null)
            {
                throw new ArgumentNullException("contactLeaseService");
            }

            if (dateTime == null)
            {
                throw new ArgumentNullException("dateTime");
            }

            this.contactRepo = contactRepo;
            this.contactIdentityService = contactIdentityService;
            this.contactLeaseService = contactLeaseService;
            this.dateTime = dateTime;
        }
        public LeaseService(
            IDateTimeController dateTime,
            IConcurrencyControlRepository<ElasticLease> leaseRepository)
        {
            if (leaseRepository == null)
            {
                throw new ArgumentNullException("leaseRepository");
            }

            if (dateTime == null)
            {
                throw new ArgumentNullException("dateTime");
            }

            this.leaseRepository = leaseRepository;
            this.dateTime = dateTime;
        }
        public void ObsoleteContact_ContactExistsAndExpiredLockedByDifferentOwner_ContactObsoleted(
            IElasticAnalyticsContactService contactService,
            IRepository<ElasticContact> contactRepo,
            ElasticContact contact,
            Guid successor,
            ElasticLeaseOwner us,
            ElasticLeaseOwner them,
            ISystemContext ctx,
            IDateTimeController dateTime,
            TestIndexUtils contactIndex)
        {
            using (contactIndex)
            {
                // arrange contact with expired lease from another owner...
                var timeTraveller = (DateTimeTimeTraveller)dateTime;

                using (timeTraveller.NewJourney(-24))
                {
                    contactService.Save(contact, them, false, ctx).Should().BeTrue();
                }

                contactService.Obsolete(contact.Id, successor, us, ctx).Should().BeTrue();

                var obsoletedContact = contactRepo.Get(contact.Id, ctx);

                obsoletedContact.Id.Should().Be(contact.Id);
                obsoletedContact.Successor.Should().Be(successor);
                obsoletedContact.Should().BeObsolete();
            }
        }
        public void DeleteContact_ContactExistsWithExpiredLeaseByDifferentOwner_ContactDeleted(
            IElasticAnalyticsContactService contactService,
            ElasticContact contact,
            ElasticLeaseOwner them,
            ISystemContext ctx,
            IDateTimeController dateTime,
            TestIndexUtils contactIndex) 
        {
            using (contactIndex)
            {
                // arrange contact with expired lease from another owner...
                var timeTraveller = (DateTimeTimeTraveller)dateTime;

                using (timeTraveller.NewJourney(-24))
                {
                    contactService.Save(contact, them, false, ctx).Should().BeTrue();
                }

                // deletes don't have an owner, at this level at least.
                contactService.Delete(contact.Id, ctx);

                contactService
                    .LoadForReadOnly(contact.Id, ctx)
                    .Should()
                    .BeNull();
            }
        }
        public void ReleaseContact_CurrentLockByDifferentOwner_ReturnsFalse(
            IElasticAnalyticsContactService contactService,
            IRepository<ElasticContact> contactRepo,
            ElasticContact contact,
            ElasticLeaseOwner us,
            ElasticLeaseOwner them,
            ISystemContext ctx,
            IDateTimeController dateTime,
            TestIndexUtils contactIndex)
        {
            using (contactIndex)
            {
                // contact exists and locked
                contactService.Save(contact, them, false, ctx).Should().BeTrue();

                // release
                contactService.Release(contact.Id, us, ctx).Should().BeFalse();

                // shouldn't be able to lock it again -- ??
                contactService.TryLoadAndLock(contact.Id, us, TimeSpan.FromHours(1), ctx)
                    .Status.Should()
                    .Be(LockAttemptStatus.AlreadyLocked);
            }
        }
        public void ReleaseContact_ExpiredLockExistsForDifferentOwner_NothingHappens(
            IElasticAnalyticsContactService contactService,
            ElasticContact contact,
            ElasticLeaseOwner us,
            ElasticLeaseOwner them,
            ISystemContext ctx,
            IDateTimeController dateTime,
            TestIndexUtils contactIndex)
        {
            using (contactIndex)
            {
                // contact exists, lock expired
                var timeTraveller = (DateTimeTimeTraveller)dateTime;
                using (timeTraveller.NewJourney(-24))
                {
                    contactService.Save(contact, them, false, ctx).Should().BeTrue();
                }

                // release
                contactService.Release(contact.Id, us, ctx);

                // should be able to lock it again
                contactService.TryLoadAndLock(contact.Id, us, TimeSpan.FromHours(1), ctx)
                    .Status.Should()
                    .Be(LockAttemptStatus.Success);
            }
        }