Beispiel #1
0
        /// <inheritdoc />
        public void Release(SynchronizationToken token, bool throwIfAlreadyReleased = false)
        {
            var triesCount = 0;

            while (triesCount < MaxRetriesNumber)
            {
                try
                {
                    ReleaseInternal(token, throwIfAlreadyReleased);

                    return;
                }
                catch (DbConcurrencyException)
                {
                    // Exception throwing means that synchronization object was updated by another execution:
                    // 1. Another execution decremented Owner Count of this sync object
                    // 2. (Wrong using) Service with the same type released sync object on purpose (we don't handle owners validation very strong, only owner type comparison)

                    _synchronizationObjectRepository.DiscardChanges();

                    // In happy case:
                    // Current synchronization state isn't updated because of parallel updating exception occurring
                    // Current execution should decrement the count of owners of the sync object
                }

                triesCount++;
            }
        }
Beispiel #2
0
        private void ReleaseInternal(SynchronizationToken token, bool throwIfAlreadyReleased)
        {
            var synchronizationObject = _synchronizationObjectRepository.GetById(token.Object.Id, token.Owner.Id);

            if (synchronizationObject == null)
            {
                throw new InvalidOperationException($"Synchronization object not found. SynchronizationObject.Id = '{token.Object.Id}', Owner.Id = '{token.Owner.Id}'");
            }

            if (synchronizationObject.OwnerCount == 0 && throwIfAlreadyReleased)
            {
                throw new InvalidOperationException($"Can not release synchronization object that is already released. SynchronizationObject.Id = '{token.Object.Id}', Owner.Id = '{token.Owner.Id}'");
            }

            var owner = synchronizationObject.Owners.SingleOrDefault(o => o.Id == token.Owner.Id);

            if (owner == null)
            {
                throw new InvalidOperationException($"Synchronization object owner not found. SynchronizationObject.Id = '{token.Object.Id}', Owner.Id = '{token.Owner.Id}'");
            }

            if (!owner.IsActive && throwIfAlreadyReleased)
            {
                throw new InvalidOperationException($"Synchronization object owner is not active. SynchronizationObject.Id = '{token.Object.Id}', Owner.Id = '{token.Owner.Id}'");
            }

            _synchronizationObjectRepository.Release(token.Object.Id, token.Owner.OwnerId);
            _synchronizationObjectRepository.SaveChanges();
        }
 public static bool TryCapture(
     this ISynchronizationService synchronizationService,
     int synchronizationServiceId,
     Guid ownerId,
     out SynchronizationToken token)
 {
     return(synchronizationService.TryCapture(synchronizationServiceId, ownerId.ToString("D").ToLowerInvariant(), out token));
 }
Beispiel #4
0
        private SynchronizationToken Get(string ownerId)
        {
            var synchronizationObject = _synchronizationObjectRepository.GetActiveByOwnerId(ownerId);
            var token = synchronizationObject == null
                ? SynchronizationToken.Empty
                : SynchronizationToken.Create(synchronizationObject, ownerId);

            return(token);
        }
Beispiel #5
0
        private bool TryCaptureInternal(
            SynchronizationServiceConfiguration synchronizationService,
            string ownerId,
            out SynchronizationToken token)
        {
            var synchronizationObject = _synchronizationObjectRepository.GetLastCreated();

            // If the synchronization object isn't captured
            if (!synchronizationObject.ServiceId.HasValue)
            {
                synchronizationObject = _synchronizationObjectRepository.Capture(synchronizationObject.Id, ownerId, synchronizationService.Id);
                _synchronizationObjectRepository.SaveChanges();

                // Exception throwing means that synchronization object was updated (captured) by another service execution

                token = SynchronizationToken.Create(synchronizationObject, ownerId);

                return(true);
            }

            if (synchronizationObject.ServiceId == synchronizationService.Id)
            {
                if (synchronizationService.MaxConcurrencyLevel.HasValue &&
                    synchronizationObject.OwnerCount == synchronizationService.MaxConcurrencyLevel)
                {
                    token = SynchronizationToken.Empty;

                    return(false);
                }

                if (synchronizationObject.Owners.Any(oo => oo.OwnerId == ownerId && oo.IsActive))
                {
                    token = SynchronizationToken.Empty;

                    return(false);
                }

                synchronizationObject = _synchronizationObjectRepository.Capture(synchronizationObject.Id, ownerId);
                _synchronizationObjectRepository.SaveChanges();

                // Exception throwing means that synchronization object was updated by another run execution, there are only 3 cases:
                // 1. Another new incoming run incremented Count of Owners (Captured this object) of this sync object
                // 2. Some owner of this sync object decremented Count of Owners
                // 3. Some owner of this sync object decremented Count of Owners and in case if CountOfOwners == 0 released this object and added new entry to the database

                token = SynchronizationToken.Create(synchronizationObject, ownerId);

                return(true);
            }

            // If synchronization object is captured by another service

            token = SynchronizationToken.Empty;

            return(false);
        }
Beispiel #6
0
        /// <inheritdoc />
        public bool TryCapture(int synchronizationServiceId, string ownerId, out SynchronizationToken token)
        {
            var synchronizationService = GetSynchronizationService(synchronizationServiceId);

            var triesCount = 0;

            while (triesCount < MaxRetriesNumber)
            {
                try
                {
                    return(TryCaptureInternal(synchronizationService, ownerId, out token));
                }
                catch (DbConcurrencyException)
                {
                    _synchronizationObjectRepository.DiscardChanges();
                }

                triesCount++;
            }

            token = SynchronizationToken.Empty;

            return(false);
        }
Beispiel #7
0
        /// <inheritdoc />
        public bool TryCapture(int synchronizationServiceId, string ownerId, out SynchronizationToken token)
        {
            token = SynchronizationToken.Empty;

            return(true);
        }
Beispiel #8
0
 /// <inheritdoc />
 public void Release(SynchronizationToken token, bool throwIfAlreadyReleased = false)
 {
 }