Fix PUBLISH failing when called from Lua scripts#1927
Conversation
The internal Lua processor session was created with subscribeBroker = null,
causing redis.call('PUBLISH', ...) in Lua scripts to fail with 'PUBLISH is
disabled' even when PubSub is enabled (the default).
This blocked all Redisson Java users because Redisson's RLock.unlock()
relies on redis.call('PUBLISH', ...) inside its Lua unlock script.
Pass storeWrapper.subscribeBroker to align with network session behavior.
SUBSCRIBE/PSUBSCRIBE remain blocked by the NoScript bitmap (Redis protocol
compliant). When --no-pubsub is set, Lua PUBLISH still correctly reports
disabled (graceful degradation preserved).
Adds 17 tests covering positive cases, NoScript enforcement, and
concurrency.
There was a problem hiding this comment.
Pull request overview
Fixes a scripting-session configuration bug where Lua redis.call('PUBLISH', ...) failed because the internal RespServerSession used for script execution was created without a SubscribeBroker, diverging from normal network sessions.
Changes:
- Wire
storeWrapper.subscribeBrokerinto the Lua script executionRespServerSessionso publish-side Pub/Sub works when enabled. - Add an extensive Lua Pub/Sub regression suite covering publish success, subscriber counts, pattern subscribers, mixed-command scripts, cache flush, and concurrency, plus NoScript enforcement checks.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 14 comments.
| File | Description |
|---|---|
| libs/server/Lua/SessionScriptCache.cs | Passes the session’s SubscribeBroker into the internal scripting RespServerSession to enable Lua PUBLISH when PubSub is enabled. |
| test/standalone/Garnet.test.scripting/LuaScriptTests.cs | Adds coverage validating Lua-driven PUBLISH behavior (including concurrency and script-cache scenarios) and verifies subscribe commands remain blocked from scripts. |
|
@microsoft-github-policy-service agree |
- Tighten comment in SessionScriptCache.cs to clarify that only publish-side Pub/Sub commands are enabled; SUBSCRIBE/PSUBSCRIBE remain NoScript-blocked. - Dispose all ManualResetEvent instances via 'using var' or explicit Dispose() in finally blocks to avoid leaking OS wait handles across the test suite.
|
Thanks @copilot for the review! All 14 comments addressed in the latest push:
Local validation: dotnet format --verify-no-changes passes, Debug+Release builds are 0-warning, all 102 tests pass. |
kevin-montrose
left a comment
There was a problem hiding this comment.
Simple change, but excessive (and duplicative) tests IMO. Let's trim it down to not bloat CI time and test files as much.
Per @kevin-montrose's feedback, reduce the test suite from 17 cases to 3 focused ones to avoid bloating CI time and overlap with RespPubSubTests: - LuaPublishSucceeds_WhenCalledViaRedisCall: verifies the core fix. - LuaPublishReturnsSubscriberCount: verifies Redis protocol return value. - LuaSubscribe_StillNoScriptBlocked: regression guard for NoScript enforcement. Remove duplicated PubSub-mechanism coverage (multi-subscriber, pattern, unicode, concurrency, etc.) already provided by RespPubSubTests.
Root Cause
SessionScriptCache.cscreates an internalRespServerSessionfor Lua script execution withsubscribeBrokerhardcoded tonull. This causesredis.call('PUBLISH', ...)inside Lua scripts to fail withERR PUBLISH is disabled, even when PubSub is enabled (the default).The bug affects all Redisson Java users because Redisson's
RLock.unlock()relies onredis.call('PUBLISH', ...)inside its Lua unlock script to notify waiters. See Discussion #1628.Description of Change
storeWrapper.subscribeBrokerinstead ofnullto the internal Lua processor inSessionScriptCache.cs, aligning its behavior with the network session created inGarnetProvider.cs.Key Technical Details
enableScripts: falseis intentionally keptfalseto prevent nested EVAL recursion.SubscribeBrokeris fully thread-safe (ConcurrentDictionary,Interlocked).SUBSCRIBE/PSUBSCRIBEremain blocked in Lua by the existing NoScript bitmap (Redis protocol compliant).--no-pubsub,storeWrapper.subscribeBrokerisnull, so LuaPUBLISHstill correctly reports disabled — graceful degradation preserved.Tests Added
Positive cases (10):
LuaPublishSucceeds_WhenCalledViaRedisCallLuaPublishReturnsSubscriberCountLuaPublishToNoSubscribersReturnsZeroLuaPublishMultipleSubscribers_AllReceiveLuaPublish_PSubscribeReceivesLuaPublishMixedWithSetGetLuaPublishSameChannelMultipleTimesLuaPublishUnicodePayloadLuaPublishEmptyPayloadLuaPublishAfterNonPubSubCommandsNoScript enforcement (regression guard, 3):
LuaSubscribe_StillNoScriptBlockedLuaPSubscribe_StillNoScriptBlockedLuaUnsubscribe_StillNoScriptBlockedConcurrency/state (4):
ConcurrentLuaPublish_NoRaceConditionMultipleScriptsSameSession_AllCanPublishLuaPublishPreservesOtherSubscriberStateScriptCachePublish_WorksWithScriptFlushReproduction (before fix)
Checklist
.editorconfig(dotnet format --verify-no-changespasses)ubuntu-latestandwindows-latest(Debug + Release), 0 warningsGarnet.test.scriptingtests pass locallyVersion.propschanges (handled by release automation)Related
Discussion #1628