Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<!-- General information -->
<PropertyGroup>
<Authors>Ugo Lattanzi</Authors>
<VersionPrefix>12.1.0</VersionPrefix>
<VersionPrefix>12.2.0</VersionPrefix>
<!--
<VersionSuffix>pre</VersionSuffix>
-->
Expand Down Expand Up @@ -46,6 +46,10 @@ Features:
Serializer packages (pick one): System.Text.Json, Newtonsoft, MemoryPack, MsgPack, Protobuf, ServiceStack, Utf8Json.
</Description>
<PackageReleaseNotes>
v12.2.0:
- Fixed SearchKeysAsync ignoring database number — SCAN now correctly targets the specified database instead of always scanning DB0 (#651)
- Fixed RemoveByTagAsync not deleting the tag Set key itself, causing a slow memory leak of empty tag Sets in Redis (#650)

v12.1.0:
- Added VectorSet API for AI/ML similarity search (Redis 8.0+): VADD, VSIM, VREM, VCONTAINS, VCARD, VDIM, VGETATTR, VSETATTR, VINFO, VRANDMEMBER, VLINKS
- Added llms.txt for AI coding assistant documentation indexing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ public async Task<long> RemoveByTagAsync(string tag, CommandFlags flag = Command

var keys = await SetMembersAsync<string>(tagKey, flag).ConfigureAwait(false);

return await RemoveAllAsync(keys, flag).ConfigureAwait(false);
var deletedCount = await RemoveAllAsync(keys, flag).ConfigureAwait(false);

await Database.KeyDeleteAsync(tagKey, flag).ConfigureAwait(false);

return deletedCount;
}

private Task<bool> ExecuteAddWithTagsAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -482,25 +481,15 @@ public async Task<IEnumerable<string>> SearchKeysAsync(string pattern)
pattern = $"{keyPrefix}{pattern}";
var keys = new HashSet<string>();

foreach (var unused in ServerIteratorFactory.GetServers(connectionPoolManager.GetConnection(), serverEnumerationStrategy))
foreach (var server in ServerIteratorFactory.GetServers(connectionPoolManager.GetConnection(), serverEnumerationStrategy))
{
ulong nextCursor = 0;
do
{
var redisResult = await unused.ExecuteAsync("SCAN", nextCursor.ToString(CultureInfo.InvariantCulture), "MATCH", pattern, "COUNT", "1000").ConfigureAwait(false);
var innerResult = (RedisResult[])redisResult!;

nextCursor = ulong.Parse((string)innerResult[0]!, CultureInfo.InvariantCulture);

var resultLines = ((string[])innerResult[1]!).ToArray();
keys.UnionWith(resultLines);
}
while (nextCursor != 0);
await foreach (var key in server.KeysAsync(dbNumber, pattern, 1000).ConfigureAwait(false))
keys.Add(key!);
}

return !string.IsNullOrEmpty(keyPrefix)
? keys.Select(k => k[keyPrefix.Length..])
: keys;
? keys.Select(k => k.ToString()[keyPrefix.Length..])
: keys.Select(k => k.ToString());
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,25 @@ public async Task RemoveByTagAsync_ShouldReturnOneDeletedValue_Async()

Assert.Equal(1, result);
}

[Fact]
[Trait("Category", "Tags")]
public async Task RemoveByTagAsync_ShouldDeleteTagKey_Async()
{
const string testKey = "test_key";
const string testValue = "test_value";
var testClass = new Helpers.TestClass<string>(testKey, testValue);
const string testTag = "test_tag";

await Sut.GetDefaultDatabase().AddAsync(testKey, testClass, tags: [testTag]);

var tagKeyName = TagHelper.GenerateTagKey(testTag);
var tagExistsBefore = await db.KeyExistsAsync(tagKeyName);
Assert.True(tagExistsBefore);

await Sut.GetDefaultDatabase().RemoveByTagAsync(testTag);

var tagExistsAfter = await db.KeyExistsAsync(tagKeyName);
Assert.False(tagExistsAfter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,31 @@ public async Task SearchKeys_With_Key_Prefix_Should_Return_Keys_Without_Prefix_A
Assert.Equal(keys[i], values[i].Key);
}

[Fact]
public async Task SearchKeysAsync_Should_Respect_Database_Number_Async()
{
var db1 = Sut.Db1;
var db1Raw = db1.Database;

try
{
await db1Raw.StringSetAsync("db1_key1", "value1");
await db1Raw.StringSetAsync("db1_key2", "value2");

await db.StringSetAsync("db0_key1", serializer.Serialize("value_db0"));

var keysFromDb1 = (await db1.SearchKeysAsync("db1_*")).ToList();

Assert.Equal(2, keysFromDb1.Count);
Assert.Contains("db1_key1", keysFromDb1);
Assert.Contains("db1_key2", keysFromDb1);
}
finally
{
await db1Raw.ExecuteAsync("FLUSHDB");
}
}

[Fact]
public async Task Exist_With_Valid_Object_Should_Return_The_Correct_Instance_Async()
{
Expand Down
Loading