private Task <TResult> ExecuteAsync <TResult>(
     OperationContext context,
     ContentMetadataStoreMode mode,
     ContentMetadataStoreModeFlags modeMask,
     Func <IGlobalCacheStore, Task <TResult> > executeAsync,
     [CallerMemberName] string caller = null)
     where TResult : ResultBase
 {
     return(ExecuteAsync(context, mode, modeMask, executeAsync, (store, execute) => execute(store), caller));
 }
        private static void GetFlagsAndPreferences(ContentMetadataStoreMode mode, ContentMetadataStoreModeFlags modeMask, out ContentMetadataStoreModeFlags redisFlags, out ContentMetadataStoreModeFlags distributedFlags, out bool preferRedis, out bool preferDistributed)
        {
            var modeFlags = mode.MaskFlags(modeMask);

            redisFlags       = modeFlags & ContentMetadataStoreModeFlags.Redis;
            distributedFlags = modeFlags & ContentMetadataStoreModeFlags.Distributed;
            var preference = mode.MaskFlags(ContentMetadataStoreModeFlags.PreferenceMask);

            preferRedis       = preference.HasAllFlags(ContentMetadataStoreModeFlags.PreferRedis) || distributedFlags == 0;
            preferDistributed = preference.HasAllFlags(ContentMetadataStoreModeFlags.PreferDistributed) || redisFlags == 0;
        }
        private async Task <TResult> ExecuteAsync <TResult, TState>(
            OperationContext context,
            ContentMetadataStoreMode mode,
            ContentMetadataStoreModeFlags modeMask,
            TState state,
            Func <IGlobalCacheStore, TState, Task <TResult> > executeAsync,
            string caller)
            where TResult : ResultBase
        {
            ContentMetadataStoreModeFlags redisFlags, distributedFlags;
            bool preferRedis, preferDistributed;

            GetFlagsAndPreferences(mode, modeMask, out redisFlags, out distributedFlags, out preferRedis, out preferDistributed);

            var redisTask       = MeasuredExecuteAsync(_redisStore, redisFlags, state, executeAsync);
            var distributedTask = MeasuredExecuteAsync(_distributedStore, distributedFlags, state, executeAsync);

            string extraEndMessage    = null;
            var    combinedResultTask = context.PerformOperationAsync(
                Tracer,
                async() =>
            {
                var(redisResult, distributedResult) = await WhenBothAsync(redisTask, distributedTask);
                var result      = preferDistributed ? distributedResult : redisResult;
                extraEndMessage = $"Redis={redisResult.message}, Distrib={distributedResult.message}";
                return(result.result);
            },
                caller: caller,
                extraEndMessage: r => extraEndMessage);

            if (preferRedis)
            {
                // If preferring redis, return the redis result without waiting for combined result
                return((await redisTask).result);
            }
            else if (preferDistributed)
            {
                // If preferring distributed, return the distributed result without waiting for combined result
                return((await distributedTask).result);
            }
            else
            {
                return(await combinedResultTask);
            }
        }
        public static ContentMetadataStoreModeFlags MaskFlags(this ContentMetadataStoreMode mode, ContentMetadataStoreModeFlags?mask)
        {
            var maskFlags = mask ?? ContentMetadataStoreModeFlags.All;

            return(mode.Flags() & maskFlags);
        }
 public static ContentMetadataStoreMode Mask(this ContentMetadataStoreMode mode, ContentMetadataStoreModeFlags?mask)
 {
     return((ContentMetadataStoreMode)mode.MaskFlags(mask));
 }
 public static bool HasAllFlags(this ContentMetadataStoreMode mode, ContentMetadataStoreModeFlags flags)
 {
     return(mode.Flags().HasAllFlags(flags));
 }
 public static ContentMetadataStoreModeFlags Flags(this ContentMetadataStoreMode mode)
 {
     return((ContentMetadataStoreModeFlags)mode);
 }
 public Task <TResult> WriteAsync <TResult, TState>(OperationContext context, ContentMetadataStoreMode mode, TState state, Func <IGlobalCacheStore, TState, Task <TResult> > executeAsync, [CallerMemberName] string caller = null)
     where TResult : ResultBase
 {
     return(ExecuteAsync(context, mode, ContentMetadataStoreModeFlags.WriteBoth, state, executeAsync, caller));
 }