Skip to content

Commit 7c4ad1e

Browse files
committed
queue pub-sub test (needs toy-server update)
1 parent ed5772d commit 7c4ad1e

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

tests/StackExchange.Redis.Tests/MultiGroupTests/BasicMultiGroupTests.cs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public async Task PubSubRouted()
110110
EndPoint tokyo = new DnsEndPoint("tokyo", 6379);
111111

112112
using var server0 = new InProcessTestServer(endpoint: germany);
113+
Assert.SkipUnless(server0.GetClientConfig().CommandMap.IsAvailable(RedisCommand.PUBLISH), "PUBLISH is not available");
113114
using var server1 = new InProcessTestServer(endpoint: canada);
114115
using var server2 = new InProcessTestServer(endpoint: tokyo);
115116

@@ -194,4 +195,110 @@ void Reset()
194195
Assert.Contains("[conn] chan: jkl", seen); // receives the message from itself
195196
Assert.Contains("[pub2] chan: jkl", seen); // received the message from the multi-group
196197
}
198+
199+
[Fact]
200+
public async Task PubSubOrderedRouted()
201+
{
202+
EndPoint germany = new DnsEndPoint("germany", 6379);
203+
EndPoint canada = new DnsEndPoint("canada", 6379);
204+
EndPoint tokyo = new DnsEndPoint("tokyo", 6379);
205+
206+
using var server0 = new InProcessTestServer(endpoint: germany);
207+
Assert.SkipUnless(server0.GetClientConfig().CommandMap.IsAvailable(RedisCommand.PUBLISH), "PUBLISH is not available");
208+
using var server1 = new InProcessTestServer(endpoint: canada);
209+
using var server2 = new InProcessTestServer(endpoint: tokyo);
210+
211+
HashSet<string> seen = [];
212+
213+
void Seen(string source, RedisChannel channel, RedisValue value)
214+
{
215+
string message = $"[{source}] {channel}: {value}";
216+
lock (seen)
217+
{
218+
seen.Add(message);
219+
}
220+
}
221+
222+
void Reset()
223+
{
224+
lock (seen)
225+
{
226+
seen.Clear();
227+
}
228+
}
229+
230+
void WriteSeen(string source, ChannelMessageQueue queue)
231+
{
232+
_ = Task.Run(async () =>
233+
{
234+
await foreach (var msg in queue)
235+
{
236+
Seen(source, msg.Channel, msg.Message);
237+
}
238+
});
239+
}
240+
241+
RedisChannel channel = RedisChannel.Literal("chan");
242+
var pub0 = (await server0.ConnectAsync()).GetSubscriber();
243+
WriteSeen(nameof(pub0), await pub0.SubscribeAsync(channel));
244+
var pub1 = (await server1.ConnectAsync()).GetSubscriber();
245+
WriteSeen(nameof(pub1), await pub1.SubscribeAsync(channel));
246+
var pub2 = (await server2.ConnectAsync()).GetSubscriber();
247+
WriteSeen(nameof(pub2), await pub2.SubscribeAsync(channel));
248+
249+
ConnectionGroupMember[] members = [
250+
new(server0.GetClientConfig()) { Weight = 2 },
251+
new(server1.GetClientConfig()) { Weight = 9 },
252+
new(server2.GetClientConfig()) { Weight = 3 },
253+
];
254+
await using var conn = await ConnectionMultiplexer.ConnectGroupAsync(members);
255+
Assert.True(conn.IsConnected);
256+
var typed = Assert.IsType<MultiGroupMultiplexer>(conn);
257+
var multi = conn.GetSubscriber();
258+
WriteSeen(nameof(conn), await multi.SubscribeAsync(channel));
259+
260+
// (R.4.1) If multiple member databases are configured, then I want to failover to the one with the highest weight.
261+
var db = conn.GetDatabase();
262+
var ep = await db.IdentifyEndpointAsync();
263+
Assert.Equal(canada, ep);
264+
265+
// now publish via all 4 options, see what happens
266+
Reset();
267+
await pub0.PublishAsync(channel, "abc");
268+
await pub1.PublishAsync(channel, "def");
269+
await pub2.PublishAsync(channel, "ghi");
270+
await multi.PublishAsync(channel, "jkl");
271+
await multi.PingAsync();
272+
273+
// we're expecting just canada, so:
274+
Assert.Equal(6, seen.Count);
275+
Assert.Contains("[pub0] chan: abc", seen);
276+
Assert.Contains("[pub1] chan: def", seen);
277+
Assert.Contains("[pub2] chan: ghi", seen);
278+
Assert.Contains("[conn] chan: def", seen); // receives the message from pub1
279+
Assert.Contains("[conn] chan: jkl", seen); // receives the message from itself
280+
Assert.Contains("[pub1] chan: jkl", seen); // received the message from the multi-group
281+
282+
// change weight and update
283+
members[1].Weight = 1;
284+
typed.SelectPreferredGroup();
285+
ep = await db.IdentifyEndpointAsync();
286+
Assert.Equal(tokyo, ep);
287+
288+
Reset();
289+
await pub0.PublishAsync(channel, "abc");
290+
await pub1.PublishAsync(channel, "def");
291+
await pub2.PublishAsync(channel, "ghi");
292+
await multi.PublishAsync(channel, "jkl");
293+
await multi.PingAsync();
294+
295+
// now we're expecting just tokyo, so:
296+
Assert.Equal(6, seen.Count);
297+
Assert.Contains("[pub0] chan: abc", seen);
298+
Assert.Contains("[pub1] chan: def", seen);
299+
Assert.Contains("[pub2] chan: ghi", seen);
300+
Assert.Contains("[conn] chan: jkl", seen); // receives the message from pub2
301+
Assert.Contains("[conn] chan: jkl", seen); // receives the message from itself
302+
Assert.Contains("[pub2] chan: jkl", seen); // received the message from the multi-group
303+
}
197304
}

0 commit comments

Comments
 (0)