protected override async Task <bool> TimeoutCorrectCreateUpdate(PersistenceRequestHolder <K, E> holder)
        {
            if (holder.Rq.Entity == null || mTransform == null)
            {
                return(false);
            }

            var jsonHolder      = mTransform.JsonMaker(holder.Rq.Entity);
            var alternateHolder = new PersistenceRequestHolder <K, E>(holder.ProfileId, holder.Prq, holder.Prs)
            {
                Rq = new PersistenceRepositoryHolder <K, E> {
                    Key = jsonHolder.Key, Timeout = holder.Rq.Timeout
                },
                Rs = new PersistenceRepositoryHolder <K, E>()
            };

            if (!(await RetrieveEntity(alternateHolder, ProcessRead)))
            {
                return(false);
            }

            holder.Rs.Entity       = alternateHolder.Rs.Entity;
            holder.Rs.Key          = alternateHolder.Rs.Key;
            holder.Rs.KeyReference = alternateHolder.Rs.KeyReference;
            holder.Rs.ResponseCode = mTransform.Version.SupportsVersioning && jsonHolder.Version.Equals(mTransform.Version.EntityVersionAsString(holder.Rs.Entity))
                ? alternateHolder.Rs.ResponseCode
                : holder.Rs.ResponseCode;

            return(holder.Rs.IsSuccess);
        }
示例#2
0
        protected virtual async Task ProcessVersion(PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            IResponseHolder result = null;

            if (mCacheManager.IsActive)
            {
                result = await mCacheManager.VersionRead(mTransform, holder.Rq.Key);
            }

            if (result == null || !result.IsSuccess)
            {
                if (mTransform.Version == null)
                {
                    //If we don't set a version maker then how can we return the version.
                    result = new PersistenceResponseHolder(PersistenceResponse.NotImplemented501)
                    {
                        IsSuccess = false
                    }
                }
                ;
                else
                {
                    result = await InternalVersion(holder.Rq.Key, holder);
                }

                if (mCacheManager.IsActive && !mCacheManager.IsReadOnly && result.IsSuccess)
                {
                    mCacheManager.WriteVersion(mTransform, holder.Rq.Key, result.VersionId);
                }
            }

            ProcessOutputKey(holder.Rq, holder.Rs, result);
        }
示例#3
0
        protected virtual async Task ProcessRead(PersistenceRequestHolder <K, E> holder)
        {
            IResponseHolder <E> result = null;

            if (mCacheManager.IsActive && holder.Rq.Settings.UseCache)
            {
                result = await mCacheManager.Read(mTransform, holder.Rq.Key);
            }

            if (result == null || !result.IsSuccess)
            {
                result = await InternalRead(holder.Rq.Key, holder);

                if (mCacheManager.IsActive && !mCacheManager.IsReadOnly && result.IsSuccess)
                {
                    mCacheManager.Write(mTransform, result.Entity);
                }
            }
            else
            {
                result.IsCacheHit = true;
            }

            ProcessOutputEntity(holder.Rq.Key, holder.Rq, holder.Rs, result);
        }
        protected override async Task <bool> TimeoutCorrectDelete(PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            var alternateHolder = new PersistenceRequestHolder <K, E>(holder.ProfileId, holder.Prq, holder.Prs);

            alternateHolder.Rq = new PersistenceRepositoryHolder <K, E> {
                Key = holder.Rq.Key, KeyReference = holder.Rq.KeyReference, Timeout = holder.Rq.Timeout
            };
            alternateHolder.Rs = new PersistenceRepositoryHolder <K, E>();

            bool byref = alternateHolder.Rq.KeyReference != null && !string.IsNullOrEmpty(alternateHolder.Rq.KeyReference.Item2);

            bool result;

            if (byref)
            {
                result = await RetrieveEntity(alternateHolder, ProcessReadByRef);
            }
            else
            {
                result = await RetrieveEntity(alternateHolder, ProcessRead);
            }

            if (result)
            {
                return(false);
            }

            // We should have a 404 response code here. If not send back the one we got otherwise send back 200 OK
            holder.Rs.Key          = alternateHolder.Rs.Key;
            holder.Rs.KeyReference = alternateHolder.Rs.KeyReference;
            holder.Rs.ResponseCode = alternateHolder.Rs.ResponseCode != 404 ? alternateHolder.Rs.ResponseCode : 200;

            return(holder.Rs.IsSuccess);
        }
示例#5
0
        /// <summary>
        /// This method logs entities to the event source. This method will try indefinitely
        /// as we do not want the Event Source to fail.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType"></param>
        /// <param name="prq"></param>
        /// <param name="rq"></param>
        /// <param name="rs"></param>
        protected async virtual Task LogEventSource <KT, ET>(string actionType, PersistenceRequestHolder <KT, ET> holder)
        {
            // Only pass through the entity if is of the correct entity type. ET might be an entity or it might be a Tuple<K, string>> in which case pass a null
            E entity = typeof(ET) == typeof(E) ? (E)Convert.ChangeType(holder.Rs.Entity, typeof(E)) : default(E);

            await LogEventSource(actionType, holder.Prq.Message.OriginatorKey, holder.Rs.Key, entity, holder.Rq.Settings);
        }
示例#6
0
        /// <summary>
        /// We don't want to pass the exception details back to the calling party as this may
        /// leak sensitive information aboout the application and persistence agent.
        /// This method logs the error and assigns it a trackable id and sends that instead to the
        /// front end.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param Name="action">the entity action.</param>
        /// <param Name="prq">The payload request.</param>
        /// <param Name="ex">The exception.</param>
        /// <param name="rq">The request.</param>
        /// <param Name="rs">The response.</param>
        protected void LogException <KT, ET>(string action, PersistenceRequestHolder <KT, ET> holder, Exception ex)
        {
            try
            {
                var logEvent = new PersistencePayloadLogEvent(holder.Prq, holder.Rq, holder.Rs, LoggingLevel.Info, ex);
                Logger.Log(logEvent);

                Guid   errorId    = Guid.NewGuid();
                string errMessage = string.Format("Exception tracker {0}/{1}/{2}", action, (holder.Prq != null && holder.Prq.Message != null ? holder.Prq.Message.OriginatorKey : string.Empty), errorId);
                holder.Rs.ResponseMessage = errMessage;

                if (holder.Rq != null)
                {
                    errMessage += string.Format("/{0}-{1}", holder.Rq.Key, (holder.Rq.Entity == null) ? string.Empty : holder.Rq.Entity.ToString());
                }

                Logger.LogException(errMessage, ex);
            }
            catch (Exception)
            {
                // Do not fail due to an issue logging
            }

            holder.Rs.ResponseCode    = 500;
            holder.Rs.ResponseMessage = ex.Message;
        }
示例#7
0
 protected virtual async Task <IResponseHolder> InternalVersion(K key, PersistenceRequestHolder <K, Tuple <K, string> > holder)
 {
     return(new PersistenceResponseHolder(PersistenceResponse.NotImplemented501)
     {
         IsSuccess = false
     });
 }
        /// <summary>
        /// Retrieves an entity using the supplied read action (read or read by ref) using the persistence retry policy
        /// </summary>
        /// <param name="rq">Read request</param>
        /// <param name="rs">Read response</param>
        /// <param name="m">Transmission request message</param>
        /// <param name="l">Tranmission response messages</param>
        /// <param name="readAction">Read action</param>
        /// <returns></returns>
        protected virtual async Task <bool> RetrieveEntity(PersistenceRequestHolder <K, E> holder, Func <PersistenceRequestHolder <K, E>, Task> readAction)
        {
            int numberOfRetries = 0;

            int maximumRetries = mPolicy.PersistenceRetryPolicy.GetMaximumRetries(holder.Prq);

            while (numberOfRetries < maximumRetries && !holder.Prq.Cancel.IsCancellationRequested)
            {
                await readAction(holder);

                if (holder.Rs.Entity != null || holder.Rs.ResponseCode == 404)
                {
                    return(holder.Rs.Entity != null);
                }

                await Task.Delay(mPolicy.PersistenceRetryPolicy.GetDelayBetweenRetries(holder.Prq, numberOfRetries));

                numberOfRetries++;
            }

            Collector?.LogMessage(LoggingLevel.Error
                                  , string.Format(
                                      "Unable to retrieve entity after {0} retries, message cancelled({1}) on channel({2}) for request: {3} - response: {4}"
                                      , numberOfRetries
                                      , holder.Prq.Cancel.IsCancellationRequested
                                      , holder.Prq.Message != null ? holder.Prq.Message.ChannelPriority.ToString() : "null"
                                      , holder.Rq
                                      , holder.Rs)
                                  , "DocDb"
                                  );

            return(false);
        }
示例#9
0
        /// <summary>
        /// Records the specified holder response.
        /// </summary>
        /// <typeparam name="KT">The key type.</typeparam>
        /// <typeparam name="ET">The entity type.</typeparam>
        /// <param name="holder">The request holder.</param>
        public virtual void Record <KT, ET>(PersistenceRequestHolder <KT, ET> holder)
        {
            int responseCode = holder.Rs?.ResponseCode ?? 0;

            var stats = mResponses.GetOrAdd(responseCode, new ResponseCodeStatistics(responseCode));

            stats.Record(holder.Extent, holder.Rs);
        }
示例#10
0
        /// <summary>
        /// This is called when the request is retried due to an underlying storage issue.
        /// </summary>
        /// <typeparam name="KT">The key type.</typeparam>
        /// <typeparam name="ET">The entity type.</typeparam>
        /// <param name="holder">The request holder.</param>
        /// <param name="retryStart">The tick count of the retry point.</param>
        protected virtual void ProfileRetry <KT, ET>(PersistenceRequestHolder <KT, ET> holder, int retryStart)
        {
            mPolicy.ResourceConsumer?.Retry(holder.ProfileId, retryStart, holder.Rs.ShouldRetry ? ResourceRetryReason.Other : ResourceRetryReason.Timeout);

            holder.Retry(retryStart);

            StatisticsInternal.RetryIncrement();
        }
        /// <summary>
        /// The internal delete command.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="holder">The request holder.</param>
        /// <returns></returns>
        protected override async Task <IResponseHolder> InternalDelete(K key, PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            if (!Container.Remove(key))
            {
                return(new PersistenceResponseHolder(PersistenceResponse.NotFound404));
            }

            return(new PersistenceResponseHolder(PersistenceResponse.Ok200));
        }
示例#12
0
        //Logging
        #region Log<KT, ET>...
        /// <summary>
        ///
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="action"></param>
        /// <param name="prq"></param>
        /// <param name="rq"></param>
        /// <param name="rs"></param>
        /// <param name="loggingLevel">Logging level</param>
        /// <param name="message"></param>
        protected void Log <KT, ET>(string action, PersistenceRequestHolder <KT, ET> holder
                                    , LoggingLevel loggingLevel = LoggingLevel.Info, string message = null, string category = null)
        {
            var logEvent = new PersistencePayloadLogEvent(holder.Prq, holder.Rq, holder.Rs, loggingLevel)
            {
                Message = message ?? string.Empty, Category = category
            };

            Logger.Log(logEvent);
        }
示例#13
0
        protected virtual async Task ProcessDeleteByRef(PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            var result = await InternalDeleteByRef(holder.Rq.KeyReference, holder);

            if (mCacheManager.IsActive && result.IsSuccess)
            {
                await mCacheManager.Delete(mTransform, mTransform.KeyDeserializer(result.Id));
            }

            ProcessOutputKey(holder.Rq, holder.Rs, result);
        }
示例#14
0
        /// <summary>
        /// Update
        /// </summary>
        /// <param name="rq">The request.</param>
        /// <param name="rs">The response.</param>
        /// <param name="prq">The incoming payload.</param>
        /// <param name="prs">The outgoing payload.</param>
        protected override async Task <IResponseHolder <E> > InternalUpdate(K key, PersistenceRequestHolder <K, E> holder)
        {
            var jsonHolder = mTransform.JsonMaker(holder.Rq.Entity);

            var result = await mStorage.Update(mStorageIdMaker(jsonHolder.Key)
                                               , jsonHolder.ToBlob()
                                               , contentType : "application/json; charset=utf-8"
                                               , version : jsonHolder.Version, directory : mDirectory);

            return(PersistenceResponseFormat(result));
        }
示例#15
0
        protected virtual async Task ProcessDelete(PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            //We presume that the delete will succeed and remove it from the cache before it is processed.
            //Worse case this will result in a cache miss.
            if (mCacheManager.IsActive)
            {
                await mCacheManager.Delete(mTransform, holder.Rq.Key);
            }

            var result = await InternalDelete(holder.Rq.Key, holder);

            ProcessOutputKey(holder.Rq, holder.Rs, result);
        }
示例#16
0
        //Requests
        #region Create
        protected virtual async Task ProcessCreate(PersistenceRequestHolder <K, E> holder)
        {
            K key = mTransform.KeyMaker(holder.Rq.Entity);

            var result = await InternalCreate(key, holder);

            if (mCacheManager.IsActive && !mCacheManager.IsReadOnly && result.IsSuccess)
            {
                mCacheManager.Write(mTransform, result.Entity);
            }

            ProcessOutputEntity(key, holder.Rq, holder.Rs, result);
        }
示例#17
0
        protected async override Task <IResponseHolder <E> > InternalUpdate(K key, PersistenceRequestHolder <K, E> holder)
        {
            if (await mCacheManager.Write(mTransform, holder.Rq.Entity))
            {
                return new PersistenceResponseHolder <E> {
                           IsSuccess = true, StatusCode = 200, Entity = holder.Rq.Entity
                }
            }
            ;

            return(new PersistenceResponseHolder <E> {
                IsSuccess = false, StatusCode = 409
            });
        }
示例#18
0
        protected async override Task <IResponseHolder> InternalDelete(K key, PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            if (await mCacheManager.Delete(mTransform, key))
            {
                return new PersistenceResponseHolder <E> {
                           IsSuccess = true, StatusCode = 200
                }
            }
            ;

            return(new PersistenceResponseHolder <E> {
                IsSuccess = false, StatusCode = 404
            });
        }
示例#19
0
        /// <summary>
        /// This method marks the incoming request as complete.
        /// </summary>
        /// <typeparam name="KT">The key type.</typeparam>
        /// <typeparam name="ET">The entity type.</typeparam>
        /// <param name="holder">The request holder.</param>
        protected virtual void ProfileEnd <KT, ET>(PersistenceRequestHolder <KT, ET> holder)
        {
            mPolicy.ResourceConsumer?.End(holder.ProfileId, holder.Start, holder.result ?? ResourceRequestResult.Unknown);

            IPersistenceRequestHolder ok;

            mRequestsCurrent.TryRemove(holder.ProfileId, out ok);

            PersistenceHandler handler;

            if (SupportedResolve(holder.Prq.Message.ToServiceMessageHeader(), out handler))
            {
                handler.Record(holder);
            }
        }
        /// <summary>
        /// The internal version command.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="holder">The request holder.</param>
        /// <returns></returns>
        protected override async Task <IResponseHolder> InternalVersion(K key, PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            E    entity;
            bool success = Container.TryGetValue(key, out entity);

            if (success)
            {
                JsonHolder <K> jsonHolder = mTransform.JsonMaker(entity);
                return(new PersistenceResponseHolder(PersistenceResponse.Ok200, jsonHolder.Json));
            }
            else
            {
                return(new PersistenceResponseHolder(PersistenceResponse.NotFound404));
            }
        }
        /// <summary>
        /// This is the read implementation.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="holder">The request holder.</param>
        /// <returns></returns>
        protected override async Task <IResponseHolder <E> > InternalRead(K key, PersistenceRequestHolder <K, E> holder)
        {
            E    entity;
            bool success = Container.TryGetValue(key, out entity);

            if (success)
            {
                JsonHolder <K> jsonHolder = mTransform.JsonMaker(entity);
                return(new PersistenceResponseHolder <E>(PersistenceResponse.Ok200, jsonHolder.Json, mTransform.PersistenceEntitySerializer.Deserializer(jsonHolder.Json)));
            }
            else
            {
                return(new PersistenceResponseHolder <E>(PersistenceResponse.NotFound404));
            }
        }
        /// <summary>
        /// This is the create override for the command.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="holder">The entity holder.</param>
        /// <returns>Returns the response encapsulated in a PersistenceResponseHolder object.</returns>
        protected override async Task <IResponseHolder <E> > InternalCreate(K key, PersistenceRequestHolder <K, E> holder)
        {
            E   entity   = holder.Rq.Entity;
            int response = EntityPopulate(key, entity);

            if (response == 201)
            {
                JsonHolder <K> jsonHolder = mTransform.JsonMaker(entity);
                return(new PersistenceResponseHolder <E>(PersistenceResponse.Created201, jsonHolder.Json, mTransform.PersistenceEntitySerializer.Deserializer(jsonHolder.Json)));
            }
            else
            {
                return(new PersistenceResponseHolder <E>(PersistenceResponse.Conflict409));
            }
        }
示例#23
0
        /// <summary>
        /// This is the entity search.
        /// </summary>
        /// <param name="holder">The is the entity search data.</param>
        /// <returns>This is an async task.</returns>
        protected virtual async Task ProcessSearch(PersistenceRequestHolder <SearchRequest, SearchResponse> holder)
        {
            IResponseHolder <SearchResponse> result = null;

            result = await InternalSearch(holder.Rq.Key, holder);

            holder.Rs.Entity = result.Entity;

            holder.Rs.Key = holder.Rq.Key;

            //rs.Settings.VersionId = mTransform.Version?.EntityVersionAsString(rs.Entity);

            //rs.KeyReference = new Tuple<string, string>(rs.Key.ToString(), rs.Settings.VersionId);

            //holder.Rs.ResponseCode = (int)PersistenceResponse.NotImplemented501;
            //holder.Rs.ResponseMessage = "Search is not implemented.";
        }
示例#24
0
        //Profiling
        #region ProfileStart/ProfileEnd/ProfileRetry
        /// <summary>
        /// This method starts the request profile and creates the request holder with the profile id.
        /// </summary>
        /// <typeparam name="KT">The key type.</typeparam>
        /// <typeparam name="ET">The entity type.</typeparam>
        /// <param name="prq">The incoming request.</param>
        /// <param name="prs">The outgoing response.</param>
        /// <returns>Returns the new request holder.</returns>
        protected virtual PersistenceRequestHolder <KT, ET> ProfileStart <KT, ET>(TransmissionPayload prq, List <TransmissionPayload> prs)
        {
            Guid profileId;

            if (mPolicy.ResourceConsumer == null)
            {
                profileId = Guid.NewGuid();
            }
            else
            {
                profileId = mPolicy.ResourceConsumer.Start(prq.Message.ToKey(), prq.Id);
            }

            var holder = new PersistenceRequestHolder <KT, ET>(profileId, prq, prs);

            mRequestsCurrent.TryAdd(holder.ProfileId, holder);

            return(holder);
        }
示例#25
0
        protected virtual async Task ProcessUpdate(PersistenceRequestHolder <K, E> holder)
        {
            K key = mTransform.KeyMaker(holder.Rq.Entity);

            // Remove from the cache first to ensure no change of ending up with a stale cached item
            // if the write to cache fails for any reason
            if (mCacheManager.IsActive)
            {
                mCacheManager.Delete(mTransform, key);
            }

            var result = await InternalUpdate(key, holder);

            if (mCacheManager.IsActive && result.IsSuccess)
            {
                mCacheManager.Write(mTransform, result.Entity);
            }

            ProcessOutputEntity(key, holder.Rq, holder.Rs, result);
        }
        /// <summary>
        /// The internal update command.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="holder">The request holder.</param>
        /// <returns></returns>
        protected override async Task <IResponseHolder <E> > InternalUpdate(K key, PersistenceRequestHolder <K, E> holder)
        {
            E    oldEntity;
            bool successExisting = Container.TryGetValue(key, out oldEntity);

            if (!successExisting)
            {
                return(new PersistenceResponseHolder <E>(PersistenceResponse.NotFound404));
            }

            E newEntity = holder.Rq.Entity;


            var ver = mTransform.Version;

            if (ver.SupportsOptimisticLocking)
            {
                if (ver.EntityVersionAsString(oldEntity) != ver.EntityVersionAsString(newEntity))
                {
                    return(new PersistenceResponseHolder <E>(PersistenceResponse.PreconditionFailed412));
                }
            }

            if (ver.SupportsVersioning)
            {
                ver.EntityVersionUpdate(newEntity);
            }


            Container.Update(key, newEntity, mTransform.ReferenceMaker(newEntity));

            var jsonHolder = mTransform.JsonMaker(newEntity);

            return(new PersistenceResponseHolder <E>(PersistenceResponse.Ok200)
            {
                Content = jsonHolder.Json
                , IsSuccess = true
                , Entity = newEntity
            });
        }
示例#27
0
        protected virtual async Task ProcessVersionByRef(PersistenceRequestHolder <K, Tuple <K, string> > holder)
        {
            IResponseHolder result = null;

            if (mCacheManager.IsActive)
            {
                result = await mCacheManager.VersionRead(mTransform, holder.Rq.KeyReference);
            }

            if (result == null || !result.IsSuccess)
            {
                result = await InternalVersionByRef(holder.Rq.KeyReference, holder);

                if (mCacheManager.IsActive && !mCacheManager.IsReadOnly && result.IsSuccess)
                {
                    mCacheManager.WriteReference(mTransform, holder.Rq.KeyReference, holder.Rq.Key, result.VersionId);
                }
            }
            else
            {
                holder.Rq.Key = mTransform.KeyDeserializer(result.Id); // Pass back the entities actual id in the key field
            }
            ProcessOutputKey(holder.Rq, holder.Rs, result);
        }
        /// <summary>
        /// The internal search command.
        /// </summary>
        /// <param name="key">The search request.</param>
        /// <param name="holder">The request holder.</param>
        /// <returns></returns>
        protected async override Task <IResponseHolder <SearchResponse> > InternalSearch(SearchRequest key, PersistenceRequestHolder <SearchRequest, SearchResponse> holder)
        {
            var query = Container.Values.AsQueryable <E>();

            Expression expression = mTransform.SearchTranslator.Build(key);

            //Execute Expression on Query
            bool success = true; //for the time being since we are not executing any queries

            holder.Rs.Entity = new SearchResponse();
            List <JObject> jObjects = new List <JObject>();

            foreach (var source in query.ToList())
            {
                jObjects.Add(JObject.FromObject(source));
            }
            if (success)
            {
                var resultEntities = query.ToList();
                holder.Rs.Entity.Data = jObjects;
                return(new PersistenceResponseHolder <SearchResponse>(PersistenceResponse.Ok200, null, holder.Rs.Entity));
            }



            //holder.Rs.
            //key.Select
            ////Create the expression parameters
            //ParameterExpression num1 = Expression.Parameter(typeof(E), "num1");
            //ParameterExpression num2 = Expression.Parameter(typeof(E), "num2");

            ////Create the expression parameters
            //ParameterExpression[] parameters = new ParameterExpression[] { num1, num2 };

            ////Create the expression body
            //BinaryExpression body = Expression.Add(num1, num2);
            ////Expression predicateBody = Expression.OrElse(e1, e2);
            ////Create the expression
            //Expression<Func<int, int, int>> expression = Expression.Lambda<Func<int, int, int>>(body, parameters);

            //// Compile the expression
            //Func<int, int, int> compiledExpression = expression.Compile();

            //// Execute the expression.
            //int result = compiledExpression(3, 4);

            return(await base.InternalSearch(key, holder));
        }
示例#29
0
 protected async override Task <IResponseHolder <E> > InternalRead(K key, PersistenceRequestHolder <K, E> holder)
 {
     return(await mCacheManager.Read(mTransform, key));
 }
示例#30
0
 protected async override Task <IResponseHolder> InternalVersionByRef(Tuple <string, string> reference, PersistenceRequestHolder <K, Tuple <K, string> > holder)
 {
     return(await mCacheManager.VersionRead(mTransform, reference));
 }