Skip to content

Commit 5453dc0

Browse files
committed
prevent publish on multi-node channels
1 parent 28acdf5 commit 5453dc0

4 files changed

Lines changed: 19 additions & 5 deletions

File tree

src/StackExchange.Redis/RedisChannel.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,17 @@ internal enum RedisChannelOptions
2929
private const RedisChannelOptions EqualityMask =
3030
~(RedisChannelOptions.KeyRouted | RedisChannelOptions.MultiNode);
3131

32-
internal RedisCommand PublishCommand => IsSharded ? RedisCommand.SPUBLISH : RedisCommand.PUBLISH;
32+
internal RedisCommand GetPublishCommand()
33+
{
34+
return (Options & (RedisChannelOptions.Sharded | RedisChannelOptions.MultiNode)) switch
35+
{
36+
RedisChannelOptions.None => RedisCommand.PUBLISH,
37+
RedisChannelOptions.Sharded => RedisCommand.SPUBLISH,
38+
_ => ThrowKeyRouted(),
39+
};
40+
41+
static RedisCommand ThrowKeyRouted() => throw new InvalidOperationException("Publishing is not supported for multi-node channels");
42+
}
3343

3444
/// <summary>
3545
/// Should we use cluster routing for this channel? This applies *either* to sharded (<c>SPUBLISH</c>) scenarios,

src/StackExchange.Redis/RedisDatabase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,15 +1901,15 @@ public Task<LCSMatchResult> StringLongestCommonSubsequenceWithMatchesAsync(Redis
19011901
public long Publish(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None)
19021902
{
19031903
if (channel.IsNullOrEmpty) throw new ArgumentNullException(nameof(channel));
1904-
var msg = Message.Create(-1, flags, channel.PublishCommand, channel, message);
1904+
var msg = Message.Create(-1, flags, channel.GetPublishCommand(), channel, message);
19051905
// if we're actively subscribed: send via that connection (otherwise, follow normal rules)
19061906
return ExecuteSync(msg, ResultProcessor.Int64, server: multiplexer.GetSubscribedServer(channel));
19071907
}
19081908

19091909
public Task<long> PublishAsync(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None)
19101910
{
19111911
if (channel.IsNullOrEmpty) throw new ArgumentNullException(nameof(channel));
1912-
var msg = Message.Create(-1, flags, channel.PublishCommand, channel, message);
1912+
var msg = Message.Create(-1, flags, channel.GetPublishCommand(), channel, message);
19131913
// if we're actively subscribed: send via that connection (otherwise, follow normal rules)
19141914
return ExecuteAsync(msg, ResultProcessor.Int64, server: multiplexer.GetSubscribedServer(channel));
19151915
}

src/StackExchange.Redis/RedisSubscriber.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,15 +393,15 @@ private static void ThrowIfNull(in RedisChannel channel)
393393
public long Publish(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None)
394394
{
395395
ThrowIfNull(channel);
396-
var msg = Message.Create(-1, flags, channel.PublishCommand, channel, message);
396+
var msg = Message.Create(-1, flags, channel.GetPublishCommand(), channel, message);
397397
// if we're actively subscribed: send via that connection (otherwise, follow normal rules)
398398
return ExecuteSync(msg, ResultProcessor.Int64, server: multiplexer.GetSubscribedServer(channel));
399399
}
400400

401401
public Task<long> PublishAsync(RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None)
402402
{
403403
ThrowIfNull(channel);
404-
var msg = Message.Create(-1, flags, channel.PublishCommand, channel, message);
404+
var msg = Message.Create(-1, flags, channel.GetPublishCommand(), channel, message);
405405
// if we're actively subscribed: send via that connection (otherwise, follow normal rules)
406406
return ExecuteAsync(msg, ResultProcessor.Int64, server: multiplexer.GetSubscribedServer(channel));
407407
}

tests/StackExchange.Redis.Tests/KeyNotificationTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ public void Cannot_KeyRoute_KeySpace_SingleKeyIsKeyRouted()
458458
Assert.False(channel.IsMultiNode);
459459
Assert.True(channel.IsKeyRouted);
460460
Assert.True(channel.WithKeyRouting().IsKeyRouted); // no change, still key-routed
461+
Assert.Equal(RedisCommand.PUBLISH, channel.GetPublishCommand());
461462
}
462463

463464
[Fact]
@@ -467,6 +468,7 @@ public void Cannot_KeyRoute_KeySpacePattern()
467468
Assert.True(channel.IsMultiNode);
468469
Assert.False(channel.IsKeyRouted);
469470
Assert.StartsWith("Key routing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.WithKeyRouting()).Message);
471+
Assert.StartsWith("Publishing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.GetPublishCommand()).Message);
470472
}
471473

472474
[Fact]
@@ -476,6 +478,7 @@ public void Cannot_KeyRoute_KeyEvent()
476478
Assert.True(channel.IsMultiNode);
477479
Assert.False(channel.IsKeyRouted);
478480
Assert.StartsWith("Key routing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.WithKeyRouting()).Message);
481+
Assert.StartsWith("Publishing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.GetPublishCommand()).Message);
479482
}
480483

481484
[Fact]
@@ -485,6 +488,7 @@ public void Cannot_KeyRoute_KeyEvent_Custom()
485488
Assert.True(channel.IsMultiNode);
486489
Assert.False(channel.IsKeyRouted);
487490
Assert.StartsWith("Key routing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.WithKeyRouting()).Message);
491+
Assert.StartsWith("Publishing is not supported for multi-node channels", Assert.Throws<InvalidOperationException>(() => channel.GetPublishCommand()).Message);
488492
}
489493

490494
[Fact]

0 commit comments

Comments
 (0)