//[Test]
        //public void TestOpCountByVersionLocal_DownLevel()
        //{
        //    using (var conn = Config.GetUnsecuredConnection(open: false))
        //    {
        //        conn.SetServerVersion(new Version(2, 6, 0), ServerType.Master);
        //        TestLockOpCountByVersion(conn, 5, false);
        //        TestLockOpCountByVersion(conn, 3, true);
        //        //TestManualLockOpCountByVersion(conn, 5, false);
        //        //TestManualLockOpCountByVersion(conn, 3, true);
        //    }
        //}

        //[Test]
        //public void TestOpCountByVersionRemote()
        //{
        //    using (var conn = Config.GetRemoteConnection(open: false))
        //    {
        //        TestLockOpCountByVersion(conn, 1, false);
        //        TestLockOpCountByVersion(conn, 1, true);
        //        //TestManualLockOpCountByVersion(conn, 1, false);
        //        //TestManualLockOpCountByVersion(conn, 1, true);
        //    }
        //}
        public void TestLockOpCountByVersion(ConnectionMultiplexer conn, int expected, bool existFirst)
        {
            const int DB = 0, LockDuration = 30;
            RedisKey Key = Me();

            var db = conn.GetDatabase(DB);
            db.KeyDelete(Key);
            RedisValue newVal = "us:" + Guid.NewGuid().ToString();
            RedisValue expectedVal = newVal;
            if (existFirst)
            {
                expectedVal = "other:" + Guid.NewGuid().ToString();
                db.StringSet(Key, expectedVal, TimeSpan.FromSeconds(LockDuration));
            }
            long countBefore = GetServer(conn).GetCounters().Interactive.OperationCount;

            var taken = db.LockTake(Key, newVal, TimeSpan.FromSeconds(LockDuration));

            long countAfter = GetServer(conn).GetCounters().Interactive.OperationCount;
            var valAfter = db.StringGet(Key);
            
            Assert.AreEqual(!existFirst, taken, "lock taken");
            Assert.AreEqual(expectedVal, valAfter, "taker");
            Assert.AreEqual(expected, countAfter - countBefore, "expected ops");
            // note we get a ping from GetCounters
        }
        public void Initialize()
        {
            connectionRedis = ConnectionMultiplexer.Connect("localhost:13919,password=senhadoredis");

            customer = new Customer();
            customer.Id = 12;
            customer.Age = 30;
            customer.Name = "Customer";
        }
		public static IEnumerable<IServer> GetServers(
			ConnectionMultiplexer multiplexer,
			ServerEnumerationStrategy serverEnumerationStrategy)
		{
			switch (serverEnumerationStrategy.Mode)
			{
				case ServerEnumerationStrategy.ModeOptions.All:
					var serversAll = new ServerEnumerable(multiplexer,
						serverEnumerationStrategy.TargetRole,
						serverEnumerationStrategy.UnreachableServerAction);
					return serversAll;

				case ServerEnumerationStrategy.ModeOptions.Single:
					var serversSingle = new ServerEnumerable(multiplexer,
						serverEnumerationStrategy.TargetRole,
						serverEnumerationStrategy.UnreachableServerAction);
					return serversSingle.Take(1);

				default:
					throw new NotImplementedException();
			}
		}
Example #4
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplicationInsightsTelemetry();

            services.AddControllers();

            services.AddCors(opt =>
            {
                opt.AddPolicy("CustomCorsPolicy", policy =>
                {
                    policy
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    //.AllowCredentials()
                    .AllowAnyOrigin();
                });
            });

            services.AddSingleton <IConnectionMultiplexer>(c =>
            {
                var configuration = ConfigurationOptions.Parse(Configuration
                                                               .GetConnectionString("Redis"), true);
                return(ConnectionMultiplexer.Connect(configuration));
            });

            services.AddMvc(m =>
            {
                // e.g application/xml
                m.ReturnHttpNotAcceptable = true;
            })
            .SetCompatibilityVersion(CompatibilityVersion.Latest)
            .ConfigureApiBehaviorOptions(options =>
            {
                options.InvalidModelStateResponseFactory = actionContext =>
                {
                    var errors = actionContext.ModelState
                                 .Where(e => e.Value.Errors.Count > 0)
                                 .SelectMany(x => x.Value.Errors)
                                 .Select(x => x.ErrorMessage).ToArray();

                    var errorResponse = new ApiValidationErrorResponse
                    {
                        Errors = errors
                    };

                    return(new BadRequestObjectResult(errorResponse));
                };
            });

            services.AddMediatR(typeof(BaseEntity));
            services.AddAutoMapper(typeof(MappingProfiles));

            services.AddDataPersistenceServices(Configuration);
            services.AddCustomIdentityServices(Configuration);
            services.AddCustomSwaggerServices();
            services.AddCustomApiVersioning();
            services.AddScoped <IPictureUrlResolver, PictureUrlResolver>();

            services.AddScoped <ITokenService, TokenService>();
            services.AddApplicationServices(Configuration);
        }
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration      = context.Services.GetConfiguration();

            Configure <AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();
            });

            context.Services.AddSwaggerGen(
                options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Base API", Version = "v1"
                });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });

            Configure <AbpLocalizationOptions>(options =>
            {
                options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
                options.Languages.Add(new LanguageInfo("en", "en", "English"));
                options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
                options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
                options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
            });

            Configure <AbpAuditingOptions>(options =>
            {
                //options.IsEnabledForGetRequests = true;
                options.ApplicationName = "AuthServer";
            });

            Configure <AppUrlOptions>(options =>
            {
                options.Applications["MVC"].RootUrl = configuration["AppSelfUrl"];
            });

            context.Services.AddAuthentication()
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority            = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = false;
                options.ApiName = configuration["AuthServer:ApiName"];
            });

            Configure <AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "Base:";
            });

            context.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = configuration["Redis:Configuration"];
            });

            if (!hostingEnvironment.IsDevelopment())
            {
                var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
                context.Services
                .AddDataProtection()
                .PersistKeysToStackExchangeRedis(redis, "Base-Protection-Keys");
            }

            #region "配置 CORS 授权策略"
            context.Services.AddCors(options => options.AddPolicy(_defaultCorsPolicyName,
                                                                  builder => builder.WithOrigins(
                                                                      configuration["AllowedHosts"]
                                                                      .Split(",", StringSplitOptions.RemoveEmptyEntries).ToArray()
                                                                      )
                                                                  .AllowAnyHeader()
                                                                  .AllowAnyMethod()));
            #endregion
        }
Example #6
0
        public void MyTest()
        {
            conn = Create();
            var threads = new Thread[30];
            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(Test1);
                threads[i].Name = "thread" + i.ToString();
                //threads[i].Start();
            }

            System.Threading.Thread.Sleep(10000000);
        }
        public RedisCache(string regionName, IDictionary <string, string> properties, RedisCacheElement element, ConnectionMultiplexer connectionMultiplexer, RedisCacheProviderOptions options)
        {
            this.connectionMultiplexer = connectionMultiplexer.ThrowIfNull("connectionMultiplexer");
            this.options = options.ThrowIfNull("options").ShallowCloneAndValidate();

            RegionName = regionName.ThrowIfNull("regionName");

            if (element == null)
            {
                expiry = TimeSpan.FromSeconds(
                    PropertiesHelper.GetInt32(Cfg.Environment.CacheDefaultExpiration, properties, DefaultExpiry)
                    );
            }
            else
            {
                expiry = element.Expiration;
            }

            log.DebugFormat("using expiration : {0} seconds", expiry.TotalSeconds);

            var @namespace = CacheNamePrefix + RegionName;

            CacheNamespace = new RedisNamespace(@namespace);
            SyncInitialGeneration();
        }
Example #8
0
    public MyTest()
    {
        ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");

        this.subscriber = redis.GetSubscriber();
    }
Example #9
0
 public RedisCacheImp()
 {
     connection = ConnectionMultiplexer.Connect(GlobalContext.SystemConfig.RedisConnectionString);
     cache      = connection.GetDatabase();
 }
Example #10
0
 public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis)
 {
     _logger   = loggerFactory.CreateLogger <RedisBasketRepository>();
     _redis    = redis;
     _database = redis.GetDatabase();
 }
 public RedisCartRepository(ConnectionMultiplexer redis)
 {
     _redis    = redis;
     _database = _redis.GetDatabase();
 }
Example #12
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            RegisterAppInsights(services);

            // Add framework services.
            services.AddDbContext <ApplicationDbContext>(options =>
                                                         options.UseSqlServer(Configuration["ConnectionString"],
                                                                              sqlServerOptionsAction: sqlOptions =>
            {
                sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
                sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
            }));

            services.AddIdentity <ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores <ApplicationDbContext>()
            .AddDefaultTokenProviders();

            services.Configure <AppSettings>(Configuration);

            services.AddMvc();

            if (Configuration.GetValue <string>("IsClusterEnv") == bool.TrueString)
            {
                services.AddDataProtection(opts =>
                {
                    opts.ApplicationDiscriminator = "eshop.identity";
                })
                .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
            }

            services.AddHealthChecks(checks =>
            {
                var minutes = 1;
                if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
                {
                    minutes = minutesParsed;
                }
                checks.AddSqlCheck("Identity_Db", Configuration["ConnectionString"], TimeSpan.FromMinutes(minutes));
            });

            services.AddTransient <IEmailSender, AuthMessageSender>();
            services.AddTransient <ISmsSender, AuthMessageSender>();
            services.AddTransient <ILoginService <ApplicationUser>, EFLoginService>();
            services.AddTransient <IRedirectService, RedirectService>();

            var connectionString   = Configuration["ConnectionString"];
            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            // Adds IdentityServer
            services.AddIdentityServer(x => x.IssuerUri = "null")
            .AddSigningCredential(Certificate.Get())
            .AddAspNetIdentity <ApplicationUser>()
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
                                                                             sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
                    sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                });
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString,
                                                                             sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
                    sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                });
            })
            .Services.AddTransient <IProfileService, ProfileService>();

            var container = new ContainerBuilder();

            container.Populate(services);

            return(new AutofacServiceProvider(container.Build()));
        }
Example #13
0
 public Redis()
 {
     redis = ConnectionMultiplexer.Connect("localhost");
 }
Example #14
0
 protected override void AfterTest()
 {
     _api = null;
     _muxr.Dispose();
     _muxr = null;
 }
Example #15
0
        public async Task QueuesAndFlushesAfterReconnecting()
        {
            try
            {
                var options = new ConfigurationOptions()
                {
                    BacklogPolicy      = BacklogPolicy.Default,
                    AbortOnConnectFail = false,
                    ConnectTimeout     = 1000,
                    ConnectRetry       = 2,
                    SyncTimeout        = 10000,
                    KeepAlive          = 10000,
                    AsyncTimeout       = 5000,
                    AllowAdmin         = true,
                    SocketManager      = SocketManager.ThreadPool,
                };
                options.EndPoints.Add(TestConfig.Current.MasterServerAndPort);

                using var muxer = await ConnectionMultiplexer.ConnectAsync(options, Writer);

                muxer.ErrorMessage       += (s, e) => Log($"Error Message {e.EndPoint}: {e.Message}");
                muxer.InternalError      += (s, e) => Log($"Internal Error {e.EndPoint}: {e.Exception.Message}");
                muxer.ConnectionFailed   += (s, a) => Log("Disconnected: " + EndPointCollection.ToString(a.EndPoint));
                muxer.ConnectionRestored += (s, a) => Log("Reconnected: " + EndPointCollection.ToString(a.EndPoint));

                var db = muxer.GetDatabase();
                Writer.WriteLine("Test: Initial (connected) ping");
                await db.PingAsync();

                var server = muxer.GetServerSnapshot()[0];
                var stats  = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, stats.BacklogMessagesPending); // Everything's normal

                // Fail the connection
                Writer.WriteLine("Test: Simulating failure");
                muxer.AllowConnect = false;
                server.SimulateConnectionFailure(SimulatedFailureType.All);
                Assert.False(muxer.IsConnected);

                // Queue up some commands
                Writer.WriteLine("Test: Disconnected pings");

                Task[] pings = new Task[3];
                pings[0] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(1));
                pings[1] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(2));
                pings[2] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(3));
                void disconnectedPings(int id)
                {
                    // No need to delay, we're going to try a disconnected connection immediately so it'll fail...
                    Log($"Pinging (disconnected - {id})");
                    var result = db.Ping();

                    Log($"Pinging (disconnected - {id}) - result: " + result);
                }
                Writer.WriteLine("Test: Disconnected pings issued");

                Assert.False(muxer.IsConnected);
                // Give the tasks time to queue
                await UntilCondition(TimeSpan.FromSeconds(5), () => server.GetBridgeStatus(ConnectionType.Interactive).BacklogMessagesPending >= 3);

                var disconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Log($"Test Stats: (BacklogMessagesPending: {disconnectedStats.BacklogMessagesPending}, TotalBacklogMessagesQueued: {disconnectedStats.TotalBacklogMessagesQueued})");
                Assert.True(disconnectedStats.BacklogMessagesPending >= 3, $"Expected {nameof(disconnectedStats.BacklogMessagesPending)} > 3, got {disconnectedStats.BacklogMessagesPending}");

                Writer.WriteLine("Test: Allowing reconnect");
                muxer.AllowConnect = true;
                Writer.WriteLine("Test: Awaiting reconnect");
                await UntilCondition(TimeSpan.FromSeconds(3), () => muxer.IsConnected).ForAwait();

                Writer.WriteLine("Test: Checking reconnected 1");
                Assert.True(muxer.IsConnected);

                var afterConnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Writer.WriteLine($"Test: BacklogStatus: {afterConnectedStats.BacklogStatus}, BacklogMessagesPending: {afterConnectedStats.BacklogMessagesPending}, IsWriterActive: {afterConnectedStats.IsWriterActive}, MessagesSinceLastHeartbeat: {afterConnectedStats.MessagesSinceLastHeartbeat}, TotalBacklogMessagesQueued: {afterConnectedStats.TotalBacklogMessagesQueued}");

                Writer.WriteLine("Test: Awaiting 3 pings");
                await Task.WhenAll(pings);

                Writer.WriteLine("Test: Checking reconnected 2");
                Assert.True(muxer.IsConnected);
                var reconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, reconnectedStats.BacklogMessagesPending);

                Writer.WriteLine("Test: Pinging again...");
                pings[0] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(4));
                pings[1] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(5));
                pings[2] = RunBlockingSynchronousWithExtraThreadAsync(() => disconnectedPings(6));
                Writer.WriteLine("Test: Last Ping queued");

                // We should see none queued
                Writer.WriteLine("Test: BacklogMessagesPending check");
                Assert.Equal(0, stats.BacklogMessagesPending);
                Writer.WriteLine("Test: Awaiting 3 more pings");
                await Task.WhenAll(pings);

                Writer.WriteLine("Test: Done");
            }
            finally
            {
                ClearAmbientFailures();
            }
        }
Example #16
0
        public async Task FailFast()
        {
            void PrintSnapshot(ConnectionMultiplexer muxer)
            {
                Writer.WriteLine("Snapshot summary:");
                foreach (var server in muxer.GetServerSnapshot())
                {
                    Writer.WriteLine($"  {server.EndPoint}: ");
                    Writer.WriteLine($"     Type: {server.ServerType}");
                    Writer.WriteLine($"     IsConnected: {server.IsConnected}");
                    Writer.WriteLine($"      IsConnecting: {server.IsConnecting}");
                    Writer.WriteLine($"      IsSelectable(allowDisconnected: true): {server.IsSelectable(RedisCommand.PING, true)}");
                    Writer.WriteLine($"      IsSelectable(allowDisconnected: false): {server.IsSelectable(RedisCommand.PING, false)}");
                    Writer.WriteLine($"      UnselectableFlags: {server.GetUnselectableFlags()}");
                    var bridge = server.GetBridge(RedisCommand.PING, create: false);
                    Writer.WriteLine($"      GetBridge: {bridge}");
                    Writer.WriteLine($"        IsConnected: {bridge.IsConnected}");
                    Writer.WriteLine($"        ConnectionState: {bridge.ConnectionState}");
                }
            }

            try
            {
                // Ensuring the FailFast policy errors immediate with no connection available exceptions
                var options = new ConfigurationOptions()
                {
                    BacklogPolicy      = BacklogPolicy.FailFast,
                    AbortOnConnectFail = false,
                    ConnectTimeout     = 1000,
                    ConnectRetry       = 2,
                    SyncTimeout        = 10000,
                    KeepAlive          = 10000,
                    AsyncTimeout       = 5000,
                    AllowAdmin         = true,
                };
                options.EndPoints.Add(TestConfig.Current.MasterServerAndPort);

                using var muxer = await ConnectionMultiplexer.ConnectAsync(options, Writer);

                var db = muxer.GetDatabase();
                Writer.WriteLine("Test: Initial (connected) ping");
                await db.PingAsync();

                var server = muxer.GetServerSnapshot()[0];
                var stats  = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, stats.BacklogMessagesPending); // Everything's normal

                // Fail the connection
                Writer.WriteLine("Test: Simulating failure");
                muxer.AllowConnect = false;
                server.SimulateConnectionFailure(SimulatedFailureType.All);
                Assert.False(muxer.IsConnected);

                // Queue up some commands
                Writer.WriteLine("Test: Disconnected pings");
                await Assert.ThrowsAsync <RedisConnectionException>(() => db.PingAsync());

                var disconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.False(muxer.IsConnected);
                Assert.Equal(0, disconnectedStats.BacklogMessagesPending);

                Writer.WriteLine("Test: Allowing reconnect");
                muxer.AllowConnect = true;
                Writer.WriteLine("Test: Awaiting reconnect");
                await UntilCondition(TimeSpan.FromSeconds(3), () => muxer.IsConnected).ForAwait();

                Writer.WriteLine("Test: Reconnecting");
                Assert.True(muxer.IsConnected);
                Assert.True(server.IsConnected);
                var reconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, reconnectedStats.BacklogMessagesPending);

                _ = db.PingAsync();
                _ = db.PingAsync();
                var lastPing = db.PingAsync();

                // For debug, print out the snapshot and server states
                PrintSnapshot(muxer);

                Assert.NotNull(muxer.SelectServer(Message.Create(-1, CommandFlags.None, RedisCommand.PING)));

                // We should see none queued
                Assert.Equal(0, stats.BacklogMessagesPending);
                await lastPing;
            }
            finally
            {
                ClearAmbientFailures();
            }
        }
Example #17
0
        public async Task QueuesAndFlushesAfterReconnectingAsync()
        {
            try
            {
                var options = new ConfigurationOptions()
                {
                    BacklogPolicy      = BacklogPolicy.Default,
                    AbortOnConnectFail = false,
                    ConnectTimeout     = 1000,
                    ConnectRetry       = 2,
                    SyncTimeout        = 10000,
                    KeepAlive          = 10000,
                    AsyncTimeout       = 5000,
                    AllowAdmin         = true,
                    SocketManager      = SocketManager.ThreadPool,
                };
                options.EndPoints.Add(TestConfig.Current.MasterServerAndPort);

                using var muxer = await ConnectionMultiplexer.ConnectAsync(options, Writer);

                muxer.ErrorMessage       += (s, e) => Log($"Error Message {e.EndPoint}: {e.Message}");
                muxer.InternalError      += (s, e) => Log($"Internal Error {e.EndPoint}: {e.Exception.Message}");
                muxer.ConnectionFailed   += (s, a) => Log("Disconnected: " + EndPointCollection.ToString(a.EndPoint));
                muxer.ConnectionRestored += (s, a) => Log("Reconnected: " + EndPointCollection.ToString(a.EndPoint));

                var db = muxer.GetDatabase();
                Writer.WriteLine("Test: Initial (connected) ping");
                await db.PingAsync();

                var server = muxer.GetServerSnapshot()[0];
                var stats  = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, stats.BacklogMessagesPending); // Everything's normal

                // Fail the connection
                Writer.WriteLine("Test: Simulating failure");
                muxer.AllowConnect = false;
                server.SimulateConnectionFailure(SimulatedFailureType.All);
                Assert.False(muxer.IsConnected);

                // Queue up some commands
                Writer.WriteLine("Test: Disconnected pings");
                var ignoredA = db.PingAsync();
                var ignoredB = db.PingAsync();
                var lastPing = db.PingAsync();

                // TODO: Add specific server call

                var disconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.False(muxer.IsConnected);
                Assert.True(disconnectedStats.BacklogMessagesPending >= 3, $"Expected {nameof(disconnectedStats.BacklogMessagesPending)} > 3, got {disconnectedStats.BacklogMessagesPending}");

                Writer.WriteLine("Test: Allowing reconnect");
                muxer.AllowConnect = true;
                Writer.WriteLine("Test: Awaiting reconnect");
                await UntilCondition(TimeSpan.FromSeconds(3), () => muxer.IsConnected).ForAwait();

                Writer.WriteLine("Test: Checking reconnected 1");
                Assert.True(muxer.IsConnected);

                Writer.WriteLine("Test: ignoredA Status: " + ignoredA.Status);
                Writer.WriteLine("Test: ignoredB Status: " + ignoredB.Status);
                Writer.WriteLine("Test: lastPing Status: " + lastPing.Status);
                var afterConnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Writer.WriteLine($"Test: BacklogStatus: {afterConnectedStats.BacklogStatus}, BacklogMessagesPending: {afterConnectedStats.BacklogMessagesPending}, IsWriterActive: {afterConnectedStats.IsWriterActive}, MessagesSinceLastHeartbeat: {afterConnectedStats.MessagesSinceLastHeartbeat}, TotalBacklogMessagesQueued: {afterConnectedStats.TotalBacklogMessagesQueued}");

                Writer.WriteLine("Test: Awaiting lastPing 1");
                await lastPing;

                Writer.WriteLine("Test: Checking reconnected 2");
                Assert.True(muxer.IsConnected);
                var reconnectedStats = server.GetBridgeStatus(ConnectionType.Interactive);
                Assert.Equal(0, reconnectedStats.BacklogMessagesPending);

                Writer.WriteLine("Test: Pinging again...");
                _ = db.PingAsync();
                _ = db.PingAsync();
                Writer.WriteLine("Test: Last Ping issued");
                lastPing = db.PingAsync();

                // We should see none queued
                Writer.WriteLine("Test: BacklogMessagesPending check");
                Assert.Equal(0, stats.BacklogMessagesPending);
                Writer.WriteLine("Test: Awaiting lastPing 2");
                await lastPing;
                Writer.WriteLine("Test: Done");
            }
            finally
            {
                ClearAmbientFailures();
            }
        }
Example #18
0
 public RedisCacheStore(ConfigurationOptions options)
 {
     _redis = ConnectionMultiplexer.Connect(options);
     _cache = _redis.GetDatabase();
 }
Example #19
0
 public CacheService(ILogger <CacheService> logger)
 {
     _logger   = logger;
     _redis    = ConnectionMultiplexer.Connect(CacheConstants.Host);
     _database = _redis.GetDatabase();
 }
Example #20
0
 public static void AddCacheMissDropMemoryCacheService(this IServiceCollection services, string redisConnection)
 {
     services.AddMemoryCache();
     services.AddSingleton <ConnectionMultiplexer>(ConnectionMultiplexer.Connect(redisConnection));
     services.AddSingleton <IDropCacheService, DropCacheService>();
 }
Example #21
0
 public RedisTests()
 {
     _multiplexer = ConnectionMultiplexer.Connect("bafver.redis.cache.windows.net,ssl=true,password=een9I4OZKFi1sju6OEm9dJefqokLtLxNuVDc0CDzrY8=,allowAdmin=true");
     _multiplexer.GetServer(_multiplexer.GetEndPoints()[0]).FlushDatabase();
     _cacheEngine = new CacheEngine(new RedisCacheProvider(_multiplexer));
 }
 public RedisQueueFactory(ILoggerFactory loggerFactory, ConnectionMultiplexer connection)
 {
     _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
     _connection    = connection;
 }
Example #23
0
 /// <summary>
 /// 构造函数
 /// </summary>
 /// <param name="readWriteHosts">Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true,abortConnect=false</param>
 /// <param name="dbNum">数据库的编号</param>
 public RedisHelper(string readWriteHosts, int dbNum = 0)
 {
     DbNum = dbNum;
     _conn = string.IsNullOrWhiteSpace(readWriteHosts) ? ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(RedisConnectionString)) : ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(readWriteHosts));
     //_conn.ConfigurationChanged += MuxerConfigurationChanged;
     _conn.ConfigurationChanged += ConfigurationChanged;
     //_conn.ConnectionFailed += MuxerConnectionFailed;
     _conn.ConnectionFailed += ConnectionFailed;
     //_conn.ConnectionRestored += MuxerConnectionRestored;
     _conn.ConnectionRestored += ConnectionRestored;
     //_conn.ErrorMessage += MuxerErrorMessage;
     _conn.ErrorMessage += ErrorMessage;
     //_conn.HashSlotMoved += MuxerHashSlotMoved;
     _conn.HashSlotMoved += HashSlotMoved;
     //_conn.InternalError += MuxerInternalError;
     _conn.InternalError += InternalError;
 }
 public RedisCache(string regionName, ConnectionMultiplexer connectionMultiplexer, RedisCacheProviderOptions options)
     : this(regionName, new Dictionary <string, string>(), null, connectionMultiplexer, options)
 {
 }
Example #25
0
        public static IDatabase GetDatabase()
        {
            ConnectionMultiplexer connection = lazyConnection.Value;

            return(RedisDBManager.m_db);
        }
Example #26
0
 static void Main(string[] args)
 {
     ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
     var db         = redis.GetDatabase(0);
     var timeToLive = db.KeyTimeToLive("RedisKeyNameHere");
 }
        // This is a separate method for target=DEBUG purposes.
        // In release builds, the runtime is smart enough to figure out
        //   that the contexts are unreachable and should be collected but in
        //   debug builds... well, it's not very smart.
        object LeaksCollectedAndRePooled_Initialize(ConnectionMultiplexer conn, int threadCount)
        {
            var profiler = new TestProfiler3();
            conn.RegisterProfiler(profiler);

            var perThreadContexts = new List<object>();
            for (var i = 0; i < threadCount; i++)
            {
                perThreadContexts.Add(new object());
            }

            var threads = new List<Thread>();

            var results = new IEnumerable<IProfiledCommand>[threadCount];

            for (var i = 0; i < threadCount; i++)
            {
                var ix = i;
                var thread =
                    new Thread(
                        delegate()
                        {
                            var ctx = perThreadContexts[ix];
                            profiler.RegisterContext(ctx);

                            conn.BeginProfiling(ctx);
                            var db = conn.GetDatabase(ix);

                            var allTasks = new List<Task>();

                            for (var j = 0; j < 1000; j++)
                            {
                                allTasks.Add(db.StringGetAsync("hello" + ix));
                                allTasks.Add(db.StringSetAsync("hello" + ix, "world" + ix));
                            }

                            Task.WaitAll(allTasks.ToArray());

                            // intentionally leaking!
                        }
                    );

                threads.Add(thread);
            }

            threads.ForEach(t => t.Start());
            threads.ForEach(t => t.Join());

            var anyContext = profiler.AnyContext();
            profiler.Reset();

            return anyContext;
        }
Example #28
0
        public void DeslaveGoesToPrimary()
        {
            ConfigurationOptions config = GetMasterSlaveConfig();

            using (var conn = ConnectionMultiplexer.Connect(config))
            {
                var primary   = conn.GetServer(new IPEndPoint(IPAddress.Parse(PrimaryServer), PrimaryPort));
                var secondary = conn.GetServer(new IPEndPoint(IPAddress.Parse(PrimaryServer), SlavePort));

                primary.Ping();
                secondary.Ping();

                primary.MakeMaster(ReplicationChangeOptions.SetTiebreaker);
                secondary.MakeMaster(ReplicationChangeOptions.None);

                primary.Ping();
                secondary.Ping();

                using (var writer = new StringWriter())
                {
                    conn.Configure(writer);
                    string log = writer.ToString();

                    Assert.IsTrue(log.Contains("tie-break is unanimous at " + PrimaryServer + ":" + PrimaryPort), "unanimous");
                }
                // k, so we know everyone loves 6379; is that what we get?

                var      db  = conn.GetDatabase();
                RedisKey key = Me();

                EndPoint demandMaster, preferMaster, preferSlave, demandSlave;
                preferMaster = db.IdentifyEndpoint(key, CommandFlags.PreferMaster);
                demandMaster = db.IdentifyEndpoint(key, CommandFlags.DemandMaster);
                preferSlave  = db.IdentifyEndpoint(key, CommandFlags.PreferSlave);

                Assert.AreEqual(primary.EndPoint, demandMaster, "demand master");
                Assert.AreEqual(primary.EndPoint, preferMaster, "prefer master");
                Assert.AreEqual(primary.EndPoint, preferSlave, "prefer slave");

                try
                {
                    demandSlave = db.IdentifyEndpoint(key, CommandFlags.DemandSlave);
                    Assert.Fail("this should not have worked");
                }
                catch (RedisConnectionException ex)
                {
                    Assert.AreEqual("No connection is available to service this operation: EXISTS DeslaveGoesToPrimary", ex.Message);
                }

                primary.MakeMaster(ReplicationChangeOptions.Broadcast | ReplicationChangeOptions.EnslaveSubordinates | ReplicationChangeOptions.SetTiebreaker);

                primary.Ping();
                secondary.Ping();

                preferMaster = db.IdentifyEndpoint(key, CommandFlags.PreferMaster);
                demandMaster = db.IdentifyEndpoint(key, CommandFlags.DemandMaster);
                preferSlave  = db.IdentifyEndpoint(key, CommandFlags.PreferSlave);
                demandSlave  = db.IdentifyEndpoint(key, CommandFlags.DemandSlave);

                Assert.AreEqual(primary.EndPoint, demandMaster, "demand master");
                Assert.AreEqual(primary.EndPoint, preferMaster, "prefer master");
                Assert.AreEqual(secondary.EndPoint, preferSlave, "prefer slave");
                Assert.AreEqual(secondary.EndPoint, preferSlave, "demand slave slave");
            }
        }
Example #29
0
        public void SendingSecondAndThirdLimitOrderMakesNonTipQueryWorkAfter()
        {
            var quantity = 1;
            var price    = 10000;
            var side     = Side.Bid;
            var market   = new Market(Currency.BTC, Currency.USD);

            var firstLimitOrder =
                new LimitOrder(new OrderInfo(Guid.NewGuid(),
                                             side, quantity), price);

            var exchange = CreateExchangeAndSendFirstLimitOrder(firstLimitOrder);

            var secondLimitOrder =
                new LimitOrder(new OrderInfo(Guid.NewGuid(),
                                             side, quantity), price - 1);
            var orderReq = new LimitOrderRequest(secondLimitOrder,
                                                 LimitOrderRequestType.Normal);

            exchange.SendLimitOrder(orderReq, market);

            var thirdLimitOrder =
                new LimitOrder(new OrderInfo(Guid.NewGuid(),
                                             side, quantity), price - 2);

            orderReq = new LimitOrderRequest(thirdLimitOrder,
                                             LimitOrderRequestType.Normal);
            exchange.SendLimitOrder(orderReq, market);

            var nonTipQuery = new MarketQuery(market, side, false);

            //e.g. {"Market":{"BuyCurrency":{"Case":"BTC"},"SellCurrency":{"Case":"USD"}},"Side":{"Case":"Buy"},"Tip":true}"
            string nontipQueryStr = JsonConvert.SerializeObject(nonTipQuery);

            using (var redis = ConnectionMultiplexer.Connect("localhost"))
            {
                var db = redis.GetDatabase();

                var values = db.StringGet(nontipQueryStr);
                Assert.That(String.IsNullOrEmpty(values), Is.False,
                            "should have nontip tail(not null) in this market");
                var orders = JsonConvert.DeserializeObject <List <string> >(values);
                Assert.That(orders.Count, Is.EqualTo(2),
                            "should have nontip tail of 2 elements in this market now");

                Assert.That(orders[0],
                            Is.EqualTo(secondLimitOrder.OrderInfo.Id.ToString()),
                            "first order in tail is wrong");
                Assert.That(orders[1],
                            Is.EqualTo(thirdLimitOrder.OrderInfo.Id.ToString()),
                            "second order in tail is wrong");

                var order2 = db.StringGet(orders[0]);
                Assert.That(order2.HasValue, Is.EqualTo(true),
                            "should have the second order content");
                Assert.That(order2.IsNull, Is.EqualTo(false),
                            "should have the second order content(not null)");
                var secondLimitOrderSerialized =
                    JsonConvert.SerializeObject(secondLimitOrder);
                Assert.That(order2.ToString(),
                            Is.EqualTo(secondLimitOrderSerialized),
                            "received second order should have same content");

                var order3 = db.StringGet(orders[1]);
                Assert.That(order3.HasValue, Is.EqualTo(true),
                            "should have the third order content");
                Assert.That(order3.IsNull, Is.EqualTo(false),
                            "should have the third order content(not null)");
                var thirdLimitOrderSerialized =
                    JsonConvert.SerializeObject(thirdLimitOrder);
                Assert.That(order3.ToString(),
                            Is.EqualTo(thirdLimitOrderSerialized),
                            "received second order should have same content");
            }
        }
Example #30
0
        public void Run()
        {
            Console.WriteLine("Loggin to file: " + logFile);

            sentinelConnection = GetSentinelConnection();
            if (sentinelConnection.IsConnected)
            {
                redisConnection = GetRedisConnection();
                if (redisConnection.IsConnected)
                {
                    DoTests();
                }
                else
                {
                    Console.WriteLine("Master was not connected, tests stopped.");
                }
            }
            else
            {
                Console.WriteLine("Sentinels was not connected, tests stopped.");
            }
        }
Example #31
0
        static void Ping(ConnectionMultiplexer muxer, IServer pub, ISubscriber sub, int times = 1)
        {
            while (times-- > 0)
            {
                // both use async because we want to drain the completion managers, and the only
                // way to prove that is to use TPL objects
                var t1 = sub.PingAsync();
                var t2 = pub.PingAsync();
                Thread.Sleep(100); // especially useful when testing any-order mode

                if (!Task.WaitAll(new[] { t1, t2 }, muxer.TimeoutMilliseconds * 2)) throw new TimeoutException();
            }
        }
Example #32
0
 /// <summary>
 /// 通过构造器注入
 /// </summary>
 /// <param name="options"></param>
 /// <param name="database"></param>
 public RedisCacheService(RedisCacheOptions options, int database = 0)
 {
     m_Connection = ConnectionMultiplexer.Connect(options.Configuration);
     m_Cache      = m_Connection.GetDatabase(database);
     m_Instance   = options.InstanceName;
 }
Example #33
0
        private Exchange CreateExchangeAndSendFirstLimitOrder
            (LimitOrder limitOrder)
        {
            var exchange = new Exchange(Persistence.Redis);

            var market = new Market(Currency.BTC, Currency.USD);

            // TODO: assert orderbook is empty first
            var orderBook = exchange[market];

            var tipQuery = new MarketQuery(market, limitOrder.OrderInfo.Side, true);

            //e.g. {"Market":{"BuyCurrency":{"Case":"BTC"},"SellCurrency":{"Case":"USD"}},"Side":{"Case":"Buy"},"Tip":true}"
            string tipQueryStr = JsonConvert.SerializeObject(tipQuery);

            using (var redis = ConnectionMultiplexer.Connect("localhost"))
            {
                var db = redis.GetDatabase();

                var value = db.StringGet(tipQueryStr);
                Assert.That(value.HasValue, Is.EqualTo(false),
                            "should be empty market");
                Assert.That(value.IsNull, Is.EqualTo(true),
                            "should be empty(null) market");
            }

            var orderReq =
                new LimitOrderRequest(limitOrder, LimitOrderRequestType.Normal);

            exchange.SendLimitOrder(orderReq, market);

            // TODO: assert orderbook is non-empty now
            var afterOrderBook = exchange[market];

            using (var redis = ConnectionMultiplexer.Connect("localhost"))
            {
                var db = redis.GetDatabase();

                var value = db.StringGet(tipQueryStr);
                Assert.That(value.HasValue, Is.EqualTo(true),
                            "should have a tip in this market");
                Assert.That(value.IsNull, Is.EqualTo(false),
                            "should have a tip(not null) in this market");

                var orderId = value.ToString();
                Assert.That(orderId,
                            Is.EqualTo(limitOrder.OrderInfo.Id.ToString()),
                            "received order should have same ID");

                var order = db.StringGet(orderId);
                Assert.That(order.HasValue, Is.EqualTo(true),
                            "should have the order content");
                Assert.That(order.IsNull, Is.EqualTo(false),
                            "should have the order content(not null)");

                var limitOrderSerialized =
                    JsonConvert.SerializeObject(limitOrder);
                Assert.That(order.ToString(),
                            Is.EqualTo(limitOrderSerialized),
                            "received order should have same content");
            }

            return(exchange);
        }
Example #34
0
 protected IServer GetServer(ConnectionMultiplexer muxer)
 {
     EndPoint[] endpoints = muxer.GetEndPoints();
     IServer result = null;
     foreach(var endpoint in endpoints)
     {
         var server = muxer.GetServer(endpoint);
         if (server.IsSlave || !server.IsConnected) continue;
         if(result != null) throw new InvalidOperationException("Requires exactly one master endpoint (found " + server.EndPoint + " and " + result.EndPoint + ")");
         result = server;
     }
     if(result == null) throw new InvalidOperationException("Requires exactly one master endpoint (found none)");
     return result;
 }
Example #35
0
        public StatsService(DiscordSocketClient client, CommandHandler cmdHandler,
                            IBotCredentials creds, NadekoBot nadeko,
                            IDataCache cache)
        {
            _log    = LogManager.GetCurrentClassLogger();
            _client = client;
            _creds  = creds;
            _redis  = cache.Redis;

            _started = DateTime.UtcNow;
            _client.MessageReceived    += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
            cmdHandler.CommandExecuted += (_, e) => Task.FromResult(Interlocked.Increment(ref _commandsRan));

            _client.ChannelCreated += (c) =>
            {
                var _ = Task.Run(() =>
                {
                    if (c is ITextChannel)
                    {
                        Interlocked.Increment(ref _textChannels);
                    }
                    else if (c is IVoiceChannel)
                    {
                        Interlocked.Increment(ref _voiceChannels);
                    }
                });

                return(Task.CompletedTask);
            };

            _client.ChannelDestroyed += (c) =>
            {
                var _ = Task.Run(() =>
                {
                    if (c is ITextChannel)
                    {
                        Interlocked.Decrement(ref _textChannels);
                    }
                    else if (c is IVoiceChannel)
                    {
                        Interlocked.Decrement(ref _voiceChannels);
                    }
                });

                return(Task.CompletedTask);
            };

            _client.GuildAvailable += (g) =>
            {
                var _ = Task.Run(() =>
                {
                    var tc = g.Channels.Count(cx => cx is ITextChannel);
                    var vc = g.Channels.Count - tc;
                    Interlocked.Add(ref _textChannels, tc);
                    Interlocked.Add(ref _voiceChannels, vc);
                });
                return(Task.CompletedTask);
            };

            _client.JoinedGuild += (g) =>
            {
                var _ = Task.Run(() =>
                {
                    var tc = g.Channels.Count(cx => cx is ITextChannel);
                    var vc = g.Channels.Count - tc;
                    Interlocked.Add(ref _textChannels, tc);
                    Interlocked.Add(ref _voiceChannels, vc);
                });
                return(Task.CompletedTask);
            };

            _client.GuildUnavailable += (g) =>
            {
                var _ = Task.Run(() =>
                {
                    var tc = g.Channels.Count(cx => cx is ITextChannel);
                    var vc = g.Channels.Count - tc;
                    Interlocked.Add(ref _textChannels, -tc);
                    Interlocked.Add(ref _voiceChannels, -vc);
                });

                return(Task.CompletedTask);
            };

            _client.LeftGuild += (g) =>
            {
                var _ = Task.Run(() =>
                {
                    var tc = g.Channels.Count(cx => cx is ITextChannel);
                    var vc = g.Channels.Count - tc;
                    Interlocked.Add(ref _textChannels, -tc);
                    Interlocked.Add(ref _voiceChannels, -vc);
                });

                return(Task.CompletedTask);
            };

            if (_client.ShardId == 0)
            {
                _carbonitexTimer = new Timer(async(state) =>
                {
                    if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
                    {
                        return;
                    }
                    try
                    {
                        using (var http = new HttpClient())
                        {
                            using (var content = new FormUrlEncodedContent(
                                       new Dictionary <string, string> {
                                { "servercount", nadeko.GuildCount.ToString() },
                                { "key", _creds.CarbonKey }
                            }))
                            {
                                content.Headers.Clear();
                                content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

                                await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
                            }
                        }
                    }
                    catch
                    {
                        // ignored
                    }
                }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
            }
#if GLOBAL_NADEKO
            _botlistTimer = new Timer(async(state) =>
            {
                if (string.IsNullOrWhiteSpace(_creds.BotListToken))
                {
                    return;
                }
                try
                {
                    using (var http = new HttpClient())
                    {
                        using (var content = new FormUrlEncodedContent(
                                   new Dictionary <string, string> {
                            { "shard_count", _creds.TotalShards.ToString() },
                            { "shard_id", client.ShardId.ToString() },
                            { "server_count", client.Guilds.Count().ToString() }
                        }))
                        {
                            content.Headers.Clear();
                            content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                            http.DefaultRequestHeaders.Add("Authorization", _creds.BotListToken);

                            await http.PostAsync($"https://discordbots.org/api/bots/{client.CurrentUser.Id}/stats", content).ConfigureAwait(false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error(ex);
                    // ignored
                }
            }, null, TimeSpan.FromMinutes(5), TimeSpan.FromHours(1));
#endif

            var platform = "other";
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                platform = "linux";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                platform = "osx";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                platform = "windows";
            }

            _dataTimer = new Timer(async(state) =>
            {
                try
                {
                    using (var http = new HttpClient())
                    {
                        using (var content = new FormUrlEncodedContent(
                                   new Dictionary <string, string> {
                            { "id", string.Concat(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(_creds.ClientId.ToString())).Select(x => x.ToString("X2"))) },
                            { "guildCount", nadeko.GuildCount.ToString() },
                            { "version", BotVersion },
                            { "platform", platform }
                        }))
                        {
                            content.Headers.Clear();
                            content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

                            await http.PostAsync("https://selfstats.nadekobot.me/", content).ConfigureAwait(false);
                        }
                    }
                }
                catch
                {
                    // ignored
                }
            }, null, TimeSpan.FromSeconds(1), TimeSpan.FromHours(1));
        }
Example #36
0
 public RedisCache(IConfiguration configuration)
 {
     _lazyRedisConn = new Lazy <ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect("localhost:16379"));
 }
 public override Task AfterConnectAsync(ConnectionMultiplexer muxer, Action <string> log)
 {
     Interlocked.Increment(ref Calls);
     log("TestAfterConnectOptionsProvider.AfterConnectAsync!");
     return(Task.CompletedTask);
 }
Example #38
0
 public RedisCacheStore(string configurations)
 {
     _redis = ConnectionMultiplexer.Connect(configurations);
     _cache = _redis.GetDatabase();
 }
Example #39
-1
        private async Task<string> DoStuff(ConnectionMultiplexer conn)
        {
            var db = conn.GetDatabase();

            var timeout = Task.Delay(5000);
            var len = db.ListLengthAsync("list");

            if (await Task.WhenAny(timeout, len) != len)
            {
                return "Timeout getting length";
            }

            
            if ((await len) == 0)
            {
                db.ListRightPush("list", "foo", flags: CommandFlags.FireAndForget);
            }
            var tran = db.CreateTransaction();
            var x = tran.ListRightPopLeftPushAsync("list", "list2");
            var y = tran.SetAddAsync("set", "bar");
            var z = tran.KeyExpireAsync("list2", TimeSpan.FromSeconds(60));
            timeout = Task.Delay(5000);

            var exec = tran.ExecuteAsync();
            // SWAP THESE TWO
            bool ok = await Task.WhenAny(exec, timeout) == exec;
            //bool ok = true;

            if (ok)
            {
                if (await exec)
                {
                    await Task.WhenAll(x, y, z);

                    var db2 = conn.GetDatabase();
                    db2.HashGet("hash", "whatever");
                    return "ok";
                }
                else
                {
                    return "Transaction aborted";
                }
            }
            else
            {
                return "Timeout during exec";
            }
        }