예제 #1
0
        public async Task SortedSetPopMulti_Multi_Async()
        {
            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.SortedSetPop), r => r.SortedSetPop);

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

                db.KeyDelete(key, CommandFlags.FireAndForget);
                db.SortedSetAdd(key, entries, CommandFlags.FireAndForget);

                var last = await db.SortedSetPopAsync(key, Order.Descending).ForAwait();

                Assert.True(last.HasValue);
                Assert.Equal(entries[9], last.Value);
                Assert.Equal(9, db.SortedSetLength(key));

                var moreLasts = await db.SortedSetPopAsync(key, 2, Order.Descending).ForAwait();

                Assert.Equal(2, moreLasts.Length);
                Assert.Equal(entries[8], moreLasts[0]);
                Assert.Equal(entries[7], moreLasts[1]);
                Assert.Equal(7, db.SortedSetLength(key));
            }
        }
예제 #2
0
        public async Task SortedSetPopMulti_Single_Async()
        {
            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.SortedSetPop), r => r.SortedSetPop);

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

                db.KeyDelete(key, CommandFlags.FireAndForget);
                db.SortedSetAdd(key, entries, CommandFlags.FireAndForget);

                var first = await db.SortedSetPopAsync(key).ForAwait();

                Assert.True(first.HasValue);
                Assert.Equal(entries[0], first.Value);
                Assert.Equal(9, db.SortedSetLength(key));

                var moreFirsts = await db.SortedSetPopAsync(key, 1).ForAwait();

                Assert.Single(moreFirsts);
                Assert.Equal(entries[1], moreFirsts[0]);
                Assert.Equal(8, db.SortedSetLength(key));
            }
        }
예제 #3
0
        public void NoInlineReplacement()
        {
            const string Script = "redis.call('set', @key, 'hello@example')";

            using (var conn = Create(allowAdmin: true))
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Scripting), f => f.Scripting);
                var server = conn.GetServer(TestConfig.Current.PrimaryServerAndPort);
                server.ScriptFlush();

                var script = LuaScript.Prepare(Script);

                Assert.Equal("redis.call('set', ARGV[1], 'hello@example')", script.ExecutableScript);

                var db  = conn.GetDatabase();
                var key = Me();
                db.KeyDelete(key, CommandFlags.FireAndForget);

                var p = new { key };

                script.Evaluate(db, p, flags: CommandFlags.FireAndForget);
                var val = db.StringGet(key);
                Assert.Equal("hello@example", val);
            }
        }
예제 #4
0
        public async Task StringGetSetExpiryAbsolute()
        {
            using var muxer = Create();
            Skip.IfMissingFeature(muxer, nameof(RedisFeatures.GetEx), r => r.GetEx);
            var conn = muxer.GetDatabase();
            var key  = Me();

            conn.KeyDelete(key, CommandFlags.FireAndForget);

            conn.StringSet(key, "abc", TimeSpan.FromHours(1));
            var newDate = DateTime.UtcNow.AddMinutes(30);
            var val     = conn.StringGetSetExpiryAsync(key, newDate);
            var valTtl  = conn.KeyTimeToLiveAsync(key);

            Assert.Equal("abc", await val);
            var time = await valTtl;

            Assert.NotNull(time);
            Assert.InRange(time.Value, TimeSpan.FromMinutes(29.8), TimeSpan.FromMinutes(30.2));

            // And ensure our type checking works
            var ex = await Assert.ThrowsAsync <ArgumentException>(() => conn.StringGetSetExpiryAsync(key, new DateTime(100, DateTimeKind.Unspecified)));

            Assert.NotNull(ex);
        }
예제 #5
0
        public void StreamAddMultipleValuePairsWithManualId()
        {
            var id  = "42-0";
            var key = GetUniqueKey("manual_id_multiple_values");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var fields = new NameValueEntry[]
                {
                    new NameValueEntry("field1", "value1"),
                    new NameValueEntry("field2", "value2")
                };

                var messageId = db.StreamAdd(key, fields, id);
                var entries   = db.StreamRange(key);

                Assert.Equal(id, messageId);
                Assert.NotNull(entries);
                Assert.True(entries.Length == 1);
                Assert.Equal(id, entries[0].Id);
            }
        }
예제 #6
0
        public void StreamPendingNoMessagesOrConsumers()
        {
            var key       = GetUniqueKey("stream_pending_empty");
            var groupName = "test_group";

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var id = db.StreamAdd(key, "field1", "value1");
                db.StreamDelete(key, new RedisValue[] { id });

                db.StreamCreateConsumerGroup(key, groupName, "0-0");

                var pendingInfo = db.StreamPending(key, "test_group");

                Assert.Equal(0, pendingInfo.PendingMessageCount);
                Assert.Equal(RedisValue.Null, pendingInfo.LowestPendingMessageId);
                Assert.Equal(RedisValue.Null, pendingInfo.HighestPendingMessageId);
                Assert.NotNull(pendingInfo.Consumers);
                Assert.True(pendingInfo.Consumers.Length == 0);
            }
        }
예제 #7
0
        public void StreamReadEmptyStreams()
        {
            var key1 = GetUniqueKey("read_empty_stream_1");
            var key2 = GetUniqueKey("read_empty_stream_2");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                // Write to a stream to create the key.
                var id1 = db.StreamAdd(key1, "field1", "value1");
                var id2 = db.StreamAdd(key2, "field2", "value2");

                // Delete the key to empty the stream.
                db.StreamDelete(key1, new RedisValue[] { id1 });
                db.StreamDelete(key2, new RedisValue[] { id2 });

                var len1 = db.StreamLength(key1);
                var len2 = db.StreamLength(key2);

                // Read the entire stream from the beginning.
                var entries1 = db.StreamRead(key1, "0-0");
                var entries2 = db.StreamRead(key2, "0-0");

                Assert.True(entries1.Length == 0);
                Assert.True(entries2.Length == 0);

                Assert.Equal(0, len1);
                Assert.Equal(0, len2);
            }
        }
예제 #8
0
        public void StreamGroupConsumerInfoGet()
        {
            var key       = GetUniqueKey("group_consumer_info");
            var group     = "test_group";
            var consumer1 = "test_consumer_1";
            var consumer2 = "test_consumer_2";

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var id1 = db.StreamAdd(key, "field1", "value1");
                var id2 = db.StreamAdd(key, "field2", "value2");
                var id3 = db.StreamAdd(key, "field3", "value3");
                var id4 = db.StreamAdd(key, "field4", "value4");

                db.StreamCreateConsumerGroup(key, group, "-");
                db.StreamReadGroup(key, group, consumer1, count: 1);
                db.StreamReadGroup(key, group, consumer2);

                var consumerInfoList = db.StreamConsumerInfo(key, group);

                Assert.NotNull(consumerInfoList);
                Assert.Equal(2, consumerInfoList.Length);

                Assert.Equal(consumer1, consumerInfoList[0].Name);
                Assert.Equal(consumer2, consumerInfoList[1].Name);

                Assert.Equal(1, consumerInfoList[0].PendingMessageCount);
                Assert.Equal(3, consumerInfoList[1].PendingMessageCount);
            }
        }
예제 #9
0
        public void StreamInfoGetWithEmptyStream()
        {
            var key = GetUniqueKey("stream_info_empty");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                // Add an entry and then delete it so the stream is empty, then run streaminfo
                // to ensure it functions properly on an empty stream. Namely, the first-entry
                // and last-entry messages should be null.

                var id = db.StreamAdd(key, "field1", "value1");
                db.StreamDelete(key, new RedisValue[] { id });

                Assert.Equal(0, db.StreamLength(key));

                var streamInfo = db.StreamInfo(key);

                Assert.True(streamInfo.FirstEntry.IsNull);
                Assert.True(streamInfo.LastEntry.IsNull);
            }
        }
예제 #10
0
        public async Task SetNotExistsAndGet()
        {
            using (var muxer = Create())
            {
                Skip.IfMissingFeature(muxer, nameof(RedisFeatures.SetNotExistsAndGet), r => r.SetNotExistsAndGet);

                var conn   = muxer.GetDatabase();
                var prefix = Me();
                conn.KeyDelete(prefix + "1", CommandFlags.FireAndForget);
                conn.KeyDelete(prefix + "2", CommandFlags.FireAndForget);
                conn.KeyDelete(prefix + "3", CommandFlags.FireAndForget);
                conn.KeyDelete(prefix + "4", CommandFlags.FireAndForget);
                conn.StringSet(prefix + "1", "abc", flags: CommandFlags.FireAndForget);

                var x0 = conn.StringSetAndGetAsync(prefix + "1", "def", when: When.NotExists);
                var x1 = conn.StringSetAndGetAsync(prefix + "2", "def", when: When.NotExists);
                var x2 = conn.StringSetAndGetAsync(prefix + "3", "def", expiry: TimeSpan.FromSeconds(4), when: When.NotExists);
                var x3 = conn.StringSetAndGetAsync(prefix + "4", "def", expiry: TimeSpan.FromMilliseconds(4001), when: When.NotExists);

                var s0 = conn.StringGetAsync(prefix + "1");
                var s1 = conn.StringGetAsync(prefix + "2");

                Assert.Equal("abc", await x0);
                Assert.Equal(RedisValue.Null, await x1);
                Assert.Equal(RedisValue.Null, await x2);
                Assert.Equal(RedisValue.Null, await x3);

                Assert.Equal("abc", await s0);
                Assert.Equal("def", await s1);
            }
        }
예제 #11
0
        public void StreamAddMultipleValuePairsWithAutoId()
        {
            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var key = GetUniqueKey("multiple_value_pairs");

                var fields = new NameValueEntry[]
                {
                    new NameValueEntry("field1", "value1"),
                    new NameValueEntry("field2", "value2")
                };

                var db        = conn.GetDatabase();
                var messageId = db.StreamAdd(key, fields);

                var entries = db.StreamRange(key);

                Assert.True(entries.Length == 1);
                Assert.Equal(messageId, entries[0].Id);
                Assert.True(entries[0].Values.Length == 2);
                Assert.True(entries[0].Values[0].Name == "field1" &&
                            entries[0].Values[0].Value == "value1");
                Assert.True(entries[0].Values[1].Name == "field2" &&
                            entries[0].Values[1].Value == "value2");
            }
        }
예제 #12
0
        public void StreamConsumerGroupReadFromStreamBeginningWithCount()
        {
            var key       = GetUniqueKey("group_read_with_count");
            var groupName = "test_group";

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var id1 = db.StreamAdd(key, "field1", "value1");
                var id2 = db.StreamAdd(key, "field2", "value2");
                var id3 = db.StreamAdd(key, "field3", "value3");
                var id4 = db.StreamAdd(key, "field4", "value4");

                db.StreamCreateConsumerGroup(key, groupName, "-");

                // Start reading after id1.
                var entries = db.StreamReadGroup(key, groupName, "test_consumer", id1, 2);

                // Ensure we only received the requested count and that the IDs match the expected values.
                Assert.True(entries.Length == 2);
                Assert.True(id2 == entries[0].Id);
                Assert.True(id3 == entries[1].Id);
            }
        }
예제 #13
0
        public void StreamReadMultipleStreamsWithEmptyResponse()
        {
            var key1 = GetUniqueKey("read_multi_1");
            var key2 = GetUniqueKey("read_multi_2");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var id1 = db.StreamAdd(key1, "field1", "value1");
                var id2 = db.StreamAdd(key1, "fiedl2", "value2");
                var id3 = db.StreamAdd(key2, "field3", "value3");
                var id4 = db.StreamAdd(key2, "field4", "value4");

                var streamList = new StreamIdPair[]
                {
                    // Read past the end of both streams.
                    new StreamIdPair(key1, id2),
                    new StreamIdPair(key2, id4)
                };

                var streams = db.StreamRead(streamList);

                // We expect an empty response.
                Assert.True(streams.Length == 0);
            }
        }
예제 #14
0
        public void StreamReadMultipleStreamsWithReadPastSecondStream()
        {
            var key1 = GetUniqueKey("read_multi_1");
            var key2 = GetUniqueKey("read_multi_2");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();

                var id1 = db.StreamAdd(key1, "field1", "value1");
                var id2 = db.StreamAdd(key1, "fiedl2", "value2");
                var id3 = db.StreamAdd(key2, "field3", "value3");
                var id4 = db.StreamAdd(key2, "field4", "value4");

                var streamList = new StreamIdPair[2]
                {
                    new StreamIdPair(key1, "0-0"),

                    // read past the end of stream # 2
                    new StreamIdPair(key2, id4)
                };

                var streams = db.StreamRead(streamList);

                // We should only get the first stream back.
                Assert.True(streams.Length == 1);

                Assert.Equal(key1, streams[0].Key);
                Assert.True(streams[0].Entries.Length == 2);
            }
        }
예제 #15
0
        public void CheckLoads(bool async)
        {
            using (var conn0 = Create(allowAdmin: true))
            using (var conn1 = Create(allowAdmin: true))
            {
                Skip.IfMissingFeature(conn0, nameof(RedisFeatures.Scripting), f => f.Scripting);
                // note that these are on different connections (so we wouldn't expect
                // the flush to drop the local cache - assume it is a surprise!)
                var server = conn0.GetServer(TestConfig.Current.MasterServer, TestConfig.Current.MasterPort);
                var db = conn1.GetDatabase();
                const string script = "return 1;";

                // start empty
                server.ScriptFlush();
                Assert.False(server.ScriptExists(script));

                // run once, causes to be cached
                Assert.True((bool)db.ScriptEvaluate(script));
                Assert.True(server.ScriptExists(script));

                // can run again
                Assert.True((bool)db.ScriptEvaluate(script));

                // ditch the scripts; should no longer exist
                db.Ping();
                server.ScriptFlush();
                Assert.False(server.ScriptExists(script));
                db.Ping();

                if (async)
                {
                    // now: fails the first time
                    try
                    {
                        db.Wait(db.ScriptEvaluateAsync(script));
                        Assert.True(false, "ScriptEvaluateAsync should fail");
                    }
                    catch (AggregateException ex)
                    {
                        Assert.Single(ex.InnerExceptions);
                        Assert.IsType<RedisServerException>(ex.InnerExceptions[0]);
                        Assert.Equal("NOSCRIPT No matching script. Please use EVAL.", ex.InnerExceptions[0].Message);
                    }
                }
                else
                {
                    // just works; magic
                    Assert.True((bool)db.ScriptEvaluate(script));
                }

                // but gets marked as unloaded, so we can use it again...
                Assert.True((bool)db.ScriptEvaluate(script));

                // which will cause it to be cached
                Assert.True(server.ScriptExists(script));
            }
        }
예제 #16
0
        public void StreamReadExpectedExceptionNullStreamList()
        {
            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();
                Assert.Throws <ArgumentNullException>(() => db.StreamRead(null));
            }
        }
예제 #17
0
        public void StreamAddSinglePairWithAutoId()
        {
            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db        = conn.GetDatabase();
                var messageId = db.StreamAdd(GetUniqueKey("auto_id"), "field1", "value1");

                Assert.True(messageId != RedisValue.Null && ((string)messageId).Length > 0);
            }
        }
예제 #18
0
        public void StreamReadExpectedExceptionInvalidCountSingleStream()
        {
            var key = GetUniqueKey("read_exception_invalid_count_single");

            using (var conn = Create())
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Streams), r => r.Streams);

                var db = conn.GetDatabase();
                Assert.Throws <ArgumentOutOfRangeException>(() => db.StreamRead(key, "0-0", 0));
            }
        }
예제 #19
0
        public void CompareScriptToDirect()
        {
            const string Script = "return redis.call('incr', KEYS[1])";

            using (var conn = Create(allowAdmin: true))
            {
                Skip.IfMissingFeature(conn, nameof(RedisFeatures.Scripting), f => f.Scripting);
                var server = conn.GetServer(TestConfig.Current.MasterServer, TestConfig.Current.MasterPort);
                server.FlushAllDatabases();
                server.ScriptFlush();

                server.ScriptLoad(Script);
                var db = conn.GetDatabase();
                db.Ping(); // k, we're all up to date now; clean db, minimal script cache

                // we're using a pipeline here, so send 1000 messages, but for timing: only care about the last
                const int LOOP = 5000;
                RedisKey key = "foo";
                RedisKey[] keys = new[] { key }; // script takes an array

                // run via script
                db.KeyDelete(key);
                CollectGarbage();
                var watch = Stopwatch.StartNew();
                for (int i = 1; i < LOOP; i++) // the i=1 is to do all-but-one
                {
                    db.ScriptEvaluate(Script, keys, flags: CommandFlags.FireAndForget);
                }
                var scriptResult = db.ScriptEvaluate(Script, keys); // last one we wait for (no F+F)
                watch.Stop();
                TimeSpan scriptTime = watch.Elapsed;

                // run via raw op
                db.KeyDelete(key);
                CollectGarbage();
                watch = Stopwatch.StartNew();
                for (int i = 1; i < LOOP; i++) // the i=1 is to do all-but-one
                {
                    db.StringIncrement(key, flags: CommandFlags.FireAndForget);
                }
                var directResult = db.StringIncrement(key); // last one we wait for (no F+F)
                watch.Stop();
                TimeSpan directTime = watch.Elapsed;

                Assert.Equal(LOOP, (long)scriptResult);
                Assert.Equal(LOOP, directResult);

                Output.WriteLine("script: {0}ms; direct: {1}ms",
                    scriptTime.TotalMilliseconds,
                    directTime.TotalMilliseconds);
            }
        }