public Attempt <Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
        {
            TypedId <Guid> key;

            try
            {
                _locker.EnterReadLock();
                if (_id2Key.TryGetValue(id, out key) && key.UmbracoObjectType == umbracoObjectType)
                {
                    return(Attempt.Succeed(key.Id));
                }
            }
            finally
            {
                if (_locker.IsReadLockHeld)
                {
                    _locker.ExitReadLock();
                }
            }

            Guid?val;

            using (var uow = _uowProvider.GetUnitOfWork())
            {
                val = uow.Database.ExecuteScalar <Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND nodeObjectType=@nodeObjectType",
                                                         new { id, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
                uow.Commit();
            }

            if (val == null)
            {
                return(Attempt <Guid> .Fail());
            }

            // cache reservations, when something is saved this cache is cleared anyways
            //if (umbracoObjectType == UmbracoObjectTypes.IdReservation)
            //    Attempt.Succeed(val.Value);

            try
            {
                _locker.EnterWriteLock();
                _id2Key[id]        = new TypedId <Guid>(val.Value, umbracoObjectType);;
                _key2Id[val.Value] = new TypedId <int>();
            }
            finally
            {
                if (_locker.IsWriteLockHeld)
                {
                    _locker.ExitWriteLock();
                }
            }

            return(Attempt.Succeed(val.Value));
        }
        public void Setup()
        {
            var serviceProvider = new ServiceCollection()
                                  .AddLogging()
                                  .BuildServiceProvider();

            var logger   = serviceProvider.GetService <ILogger <Repository <TestCounter, string> > >();
            var settings = new MongoDbSettings(MongoDefaultSettings.ConnectionString, "Tests");

            context    = new MongoDbContext(settings);
            repository = new Repository <TestCounter, string>(context, settings, logger);
            id         = TypedId.GetNewId <CounterId>();
            repository.InsertNewAsync(TestCounter.Create(id.Value, 0)).GetAwaiter().GetResult();
        }
        // note - no need for uow, scope would be enough, but a pain to wire
        // note - for pure read-only we might want to *not* enforce a transaction?

        public Attempt <int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
        {
            TypedId <int> id;

            try
            {
                _locker.EnterReadLock();
                if (_key2Id.TryGetValue(key, out id) && id.UmbracoObjectType == umbracoObjectType)
                {
                    return(Attempt.Succeed(id.Id));
                }
            }
            finally
            {
                if (_locker.IsReadLockHeld)
                {
                    _locker.ExitReadLock();
                }
            }

            int?val;

            using (var uow = _uowProvider.GetUnitOfWork())
            {
                val = uow.Database.ExecuteScalar <int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND nodeObjectType=@nodeObjectType",
                                                        new { id = key, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
                uow.Commit();
            }

            if (val == null)
            {
                return(Attempt <int> .Fail());
            }

            try
            {
                _locker.EnterWriteLock();
                _id2Key[val.Value] = new TypedId <Guid>(key, umbracoObjectType);
                _key2Id[key]       = new TypedId <int>(val.Value, umbracoObjectType);
            }
            finally
            {
                if (_locker.IsWriteLockHeld)
                {
                    _locker.ExitWriteLock();
                }
            }

            return(Attempt.Succeed(val.Value));
        }