From 6177dc991768be787fbd4562084e482791b3c7c7 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 1 Feb 2024 11:39:18 +0000 Subject: [PATCH 1/2] fix: connection close hang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix connection Close hanging if CLIENT REPLY is set to OFF or SKIP. This includes a rework of how command actions are handled to use a single map lookup based on generated permutations to improve performance and allow it to be used in both activeConn and conn. Replication of this lookup is need as its impossible to share information between the different Conn interface implementations due to returning interface instead of concrete type. The performance improvements, 33-89% sec/op and eliminating all memory allocations, help to mitigate the impact of double lookup. This also expands the benchmark coverage to allow for wider validation of this change. Fixes #361 go test -run=^$ -bench=BenchmarkLookupCommand -count=10 -benchmem > orig.log benchstat orig.log permute.log goos: linux goarch: amd64 pkg: github.com/gomodule/redigo/redis cpu: 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz │ orig.log │ permute.log │ │ sec/op │ sec/op vs base │ LookupCommandInfoCorrectCase-16 55.89n ± 7% 37.24n ± 2% -33.37% (p=0.000 n=10) LookupCommandInfoMixedCase-16 359.85n ± 9% 38.79n ± 2% -89.22% (p=0.000 n=10) LookupCommandInfoNoMatch-16 262.45n ± 1% 36.98n ± 4% -85.91% (p=0.000 n=10) geomean 174.1n 37.66n -78.37% │ orig.log │ permute.log │ │ B/op │ B/op vs base │ LookupCommandInfoCorrectCase-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LookupCommandInfoMixedCase-16 32.00 ± 0% 0.00 ± 0% -100.00% (p=0.000 n=10) LookupCommandInfoNoMatch-16 8.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) geomean ² ? ² ³ ¹ all samples are equal ² summaries must be >0 to compute geomean ³ ratios must be >0 to compute geomean │ orig.log │ permute.log │ │ allocs/op │ allocs/op vs base │ LookupCommandInfoCorrectCase-16 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ LookupCommandInfoMixedCase-16 4.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) LookupCommandInfoNoMatch-16 2.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) geomean ² ? ² ³ ¹ all samples are equal ² summaries must be >0 to compute geomean ³ ratios must be >0 to compute geomean --- .github/workflows/golangci-lint.yml | 3 +- redis/command_action.gen.go | 2263 +++++++++++++++++++++++++++ redis/command_action_gen.go | 198 +++ redis/commandinfo.go | 55 - redis/commandinfo_test.go | 27 - redis/conn.go | 37 +- redis/conn_test.go | 70 +- redis/connection_state.go | 71 + redis/connection_state_test.go | 195 +++ redis/generate.go | 3 + redis/pool.go | 150 +- redis/pool_test.go | 66 + 12 files changed, 2955 insertions(+), 183 deletions(-) create mode 100644 redis/command_action.gen.go create mode 100644 redis/command_action_gen.go delete mode 100644 redis/commandinfo.go delete mode 100644 redis/commandinfo_test.go create mode 100644 redis/connection_state.go create mode 100644 redis/connection_state_test.go create mode 100644 redis/generate.go diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index ea1e4933..04e9a93b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -20,9 +20,10 @@ jobs: go-version: '1.21' cache: false # Handled by golangci-lint. - - name: Validate go mod + - name: Validate go mod / generate run: | go mod tidy + go generate ./... git --no-pager diff && [[ 0 -eq $(git status --porcelain | wc -l) ]] - name: golangci-lint diff --git a/redis/command_action.gen.go b/redis/command_action.gen.go new file mode 100644 index 00000000..3597e95a --- /dev/null +++ b/redis/command_action.gen.go @@ -0,0 +1,2263 @@ +// Code generated by commandinfo_gen. DO NOT EDIT. + +package redis + +var ( + actionWatch = &commandAction{ + Action: func(state *connectionState) { + *state |= stateWatch + }, + } + actionUnwatch = &commandAction{ + Action: func(state *connectionState) { + *state &^= stateWatch + }, + } + actionMulti = &commandAction{ + Action: func(state *connectionState) { + *state |= stateMulti + }, + } + actionExec = &commandAction{ + Action: func(state *connectionState) { + *state &^= stateWatch | stateMulti + }, + } + actionDiscard = &commandAction{ + Action: func(state *connectionState) { + *state &^= stateWatch | stateMulti + }, + } + actionPsubscribe = &commandAction{ + Action: func(state *connectionState) { + *state |= stateSubscribe + }, + } + actionSubscribe = &commandAction{ + Action: func(state *connectionState) { + *state |= stateSubscribe + }, + } + actionMonitor = &commandAction{ + Action: func(state *connectionState) { + *state |= stateMonitor + }, + } + actionClientReplyOff = &commandAction{ + Action: func(state *connectionState) { + *state |= stateClientReplyOff + }, + } + actionClientReplyOn = &commandAction{ + Action: func(state *connectionState) { + *state &^= stateClientReplyOff | stateClientReplySkip + }, + } + actionClientReplySkip = &commandAction{ + Action: func(state *connectionState) { + if *state&stateClientReplyOff == 0 { + *state |= stateClientReplySkipNext + } + }, + } + actionClientReply = &commandAction{ + Next: map[string]*commandAction{ + "OFF": actionClientReplyOff, + "OFf": actionClientReplyOff, + "OfF": actionClientReplyOff, + "Off": actionClientReplyOff, + "oFF": actionClientReplyOff, + "oFf": actionClientReplyOff, + "ofF": actionClientReplyOff, + "off": actionClientReplyOff, + "ON": actionClientReplyOn, + "On": actionClientReplyOn, + "oN": actionClientReplyOn, + "on": actionClientReplyOn, + "SKIP": actionClientReplySkip, + "SKIp": actionClientReplySkip, + "SKiP": actionClientReplySkip, + "SKip": actionClientReplySkip, + "SkIP": actionClientReplySkip, + "SkIp": actionClientReplySkip, + "SkiP": actionClientReplySkip, + "Skip": actionClientReplySkip, + "sKIP": actionClientReplySkip, + "sKIp": actionClientReplySkip, + "sKiP": actionClientReplySkip, + "sKip": actionClientReplySkip, + "skIP": actionClientReplySkip, + "skIp": actionClientReplySkip, + "skiP": actionClientReplySkip, + "skip": actionClientReplySkip, + }, + } + actionClient = &commandAction{ + Next: map[string]*commandAction{ + "REPLY": actionClientReply, + "REPLy": actionClientReply, + "REPlY": actionClientReply, + "REPly": actionClientReply, + "REpLY": actionClientReply, + "REpLy": actionClientReply, + "REplY": actionClientReply, + "REply": actionClientReply, + "RePLY": actionClientReply, + "RePLy": actionClientReply, + "RePlY": actionClientReply, + "RePly": actionClientReply, + "RepLY": actionClientReply, + "RepLy": actionClientReply, + "ReplY": actionClientReply, + "Reply": actionClientReply, + "rEPLY": actionClientReply, + "rEPLy": actionClientReply, + "rEPlY": actionClientReply, + "rEPly": actionClientReply, + "rEpLY": actionClientReply, + "rEpLy": actionClientReply, + "rEplY": actionClientReply, + "rEply": actionClientReply, + "rePLY": actionClientReply, + "rePLy": actionClientReply, + "rePlY": actionClientReply, + "rePly": actionClientReply, + "repLY": actionClientReply, + "repLy": actionClientReply, + "replY": actionClientReply, + "reply": actionClientReply, + }, + } + activeConnActions = map[string]*commandAction{ + "WATCH": actionWatch, + "WATCh": actionWatch, + "WATcH": actionWatch, + "WATch": actionWatch, + "WAtCH": actionWatch, + "WAtCh": actionWatch, + "WAtcH": actionWatch, + "WAtch": actionWatch, + "WaTCH": actionWatch, + "WaTCh": actionWatch, + "WaTcH": actionWatch, + "WaTch": actionWatch, + "WatCH": actionWatch, + "WatCh": actionWatch, + "WatcH": actionWatch, + "Watch": actionWatch, + "wATCH": actionWatch, + "wATCh": actionWatch, + "wATcH": actionWatch, + "wATch": actionWatch, + "wAtCH": actionWatch, + "wAtCh": actionWatch, + "wAtcH": actionWatch, + "wAtch": actionWatch, + "waTCH": actionWatch, + "waTCh": actionWatch, + "waTcH": actionWatch, + "waTch": actionWatch, + "watCH": actionWatch, + "watCh": actionWatch, + "watcH": actionWatch, + "watch": actionWatch, + "UNWATCH": actionUnwatch, + "UNWATCh": actionUnwatch, + "UNWATcH": actionUnwatch, + "UNWATch": actionUnwatch, + "UNWAtCH": actionUnwatch, + "UNWAtCh": actionUnwatch, + "UNWAtcH": actionUnwatch, + "UNWAtch": actionUnwatch, + "UNWaTCH": actionUnwatch, + "UNWaTCh": actionUnwatch, + "UNWaTcH": actionUnwatch, + "UNWaTch": actionUnwatch, + "UNWatCH": actionUnwatch, + "UNWatCh": actionUnwatch, + "UNWatcH": actionUnwatch, + "UNWatch": actionUnwatch, + "UNwATCH": actionUnwatch, + "UNwATCh": actionUnwatch, + "UNwATcH": actionUnwatch, + "UNwATch": actionUnwatch, + "UNwAtCH": actionUnwatch, + "UNwAtCh": actionUnwatch, + "UNwAtcH": actionUnwatch, + "UNwAtch": actionUnwatch, + "UNwaTCH": actionUnwatch, + "UNwaTCh": actionUnwatch, + "UNwaTcH": actionUnwatch, + "UNwaTch": actionUnwatch, + "UNwatCH": actionUnwatch, + "UNwatCh": actionUnwatch, + "UNwatcH": actionUnwatch, + "UNwatch": actionUnwatch, + "UnWATCH": actionUnwatch, + "UnWATCh": actionUnwatch, + "UnWATcH": actionUnwatch, + "UnWATch": actionUnwatch, + "UnWAtCH": actionUnwatch, + "UnWAtCh": actionUnwatch, + "UnWAtcH": actionUnwatch, + "UnWAtch": actionUnwatch, + "UnWaTCH": actionUnwatch, + "UnWaTCh": actionUnwatch, + "UnWaTcH": actionUnwatch, + "UnWaTch": actionUnwatch, + "UnWatCH": actionUnwatch, + "UnWatCh": actionUnwatch, + "UnWatcH": actionUnwatch, + "UnWatch": actionUnwatch, + "UnwATCH": actionUnwatch, + "UnwATCh": actionUnwatch, + "UnwATcH": actionUnwatch, + "UnwATch": actionUnwatch, + "UnwAtCH": actionUnwatch, + "UnwAtCh": actionUnwatch, + "UnwAtcH": actionUnwatch, + "UnwAtch": actionUnwatch, + "UnwaTCH": actionUnwatch, + "UnwaTCh": actionUnwatch, + "UnwaTcH": actionUnwatch, + "UnwaTch": actionUnwatch, + "UnwatCH": actionUnwatch, + "UnwatCh": actionUnwatch, + "UnwatcH": actionUnwatch, + "Unwatch": actionUnwatch, + "uNWATCH": actionUnwatch, + "uNWATCh": actionUnwatch, + "uNWATcH": actionUnwatch, + "uNWATch": actionUnwatch, + "uNWAtCH": actionUnwatch, + "uNWAtCh": actionUnwatch, + "uNWAtcH": actionUnwatch, + "uNWAtch": actionUnwatch, + "uNWaTCH": actionUnwatch, + "uNWaTCh": actionUnwatch, + "uNWaTcH": actionUnwatch, + "uNWaTch": actionUnwatch, + "uNWatCH": actionUnwatch, + "uNWatCh": actionUnwatch, + "uNWatcH": actionUnwatch, + "uNWatch": actionUnwatch, + "uNwATCH": actionUnwatch, + "uNwATCh": actionUnwatch, + "uNwATcH": actionUnwatch, + "uNwATch": actionUnwatch, + "uNwAtCH": actionUnwatch, + "uNwAtCh": actionUnwatch, + "uNwAtcH": actionUnwatch, + "uNwAtch": actionUnwatch, + "uNwaTCH": actionUnwatch, + "uNwaTCh": actionUnwatch, + "uNwaTcH": actionUnwatch, + "uNwaTch": actionUnwatch, + "uNwatCH": actionUnwatch, + "uNwatCh": actionUnwatch, + "uNwatcH": actionUnwatch, + "uNwatch": actionUnwatch, + "unWATCH": actionUnwatch, + "unWATCh": actionUnwatch, + "unWATcH": actionUnwatch, + "unWATch": actionUnwatch, + "unWAtCH": actionUnwatch, + "unWAtCh": actionUnwatch, + "unWAtcH": actionUnwatch, + "unWAtch": actionUnwatch, + "unWaTCH": actionUnwatch, + "unWaTCh": actionUnwatch, + "unWaTcH": actionUnwatch, + "unWaTch": actionUnwatch, + "unWatCH": actionUnwatch, + "unWatCh": actionUnwatch, + "unWatcH": actionUnwatch, + "unWatch": actionUnwatch, + "unwATCH": actionUnwatch, + "unwATCh": actionUnwatch, + "unwATcH": actionUnwatch, + "unwATch": actionUnwatch, + "unwAtCH": actionUnwatch, + "unwAtCh": actionUnwatch, + "unwAtcH": actionUnwatch, + "unwAtch": actionUnwatch, + "unwaTCH": actionUnwatch, + "unwaTCh": actionUnwatch, + "unwaTcH": actionUnwatch, + "unwaTch": actionUnwatch, + "unwatCH": actionUnwatch, + "unwatCh": actionUnwatch, + "unwatcH": actionUnwatch, + "unwatch": actionUnwatch, + "MULTI": actionMulti, + "MULTi": actionMulti, + "MULtI": actionMulti, + "MULti": actionMulti, + "MUlTI": actionMulti, + "MUlTi": actionMulti, + "MUltI": actionMulti, + "MUlti": actionMulti, + "MuLTI": actionMulti, + "MuLTi": actionMulti, + "MuLtI": actionMulti, + "MuLti": actionMulti, + "MulTI": actionMulti, + "MulTi": actionMulti, + "MultI": actionMulti, + "Multi": actionMulti, + "mULTI": actionMulti, + "mULTi": actionMulti, + "mULtI": actionMulti, + "mULti": actionMulti, + "mUlTI": actionMulti, + "mUlTi": actionMulti, + "mUltI": actionMulti, + "mUlti": actionMulti, + "muLTI": actionMulti, + "muLTi": actionMulti, + "muLtI": actionMulti, + "muLti": actionMulti, + "mulTI": actionMulti, + "mulTi": actionMulti, + "multI": actionMulti, + "multi": actionMulti, + "EXEC": actionExec, + "EXEc": actionExec, + "EXeC": actionExec, + "EXec": actionExec, + "ExEC": actionExec, + "ExEc": actionExec, + "ExeC": actionExec, + "Exec": actionExec, + "eXEC": actionExec, + "eXEc": actionExec, + "eXeC": actionExec, + "eXec": actionExec, + "exEC": actionExec, + "exEc": actionExec, + "exeC": actionExec, + "exec": actionExec, + "DISCARD": actionDiscard, + "DISCARd": actionDiscard, + "DISCArD": actionDiscard, + "DISCArd": actionDiscard, + "DISCaRD": actionDiscard, + "DISCaRd": actionDiscard, + "DISCarD": actionDiscard, + "DISCard": actionDiscard, + "DIScARD": actionDiscard, + "DIScARd": actionDiscard, + "DIScArD": actionDiscard, + "DIScArd": actionDiscard, + "DIScaRD": actionDiscard, + "DIScaRd": actionDiscard, + "DIScarD": actionDiscard, + "DIScard": actionDiscard, + "DIsCARD": actionDiscard, + "DIsCARd": actionDiscard, + "DIsCArD": actionDiscard, + "DIsCArd": actionDiscard, + "DIsCaRD": actionDiscard, + "DIsCaRd": actionDiscard, + "DIsCarD": actionDiscard, + "DIsCard": actionDiscard, + "DIscARD": actionDiscard, + "DIscARd": actionDiscard, + "DIscArD": actionDiscard, + "DIscArd": actionDiscard, + "DIscaRD": actionDiscard, + "DIscaRd": actionDiscard, + "DIscarD": actionDiscard, + "DIscard": actionDiscard, + "DiSCARD": actionDiscard, + "DiSCARd": actionDiscard, + "DiSCArD": actionDiscard, + "DiSCArd": actionDiscard, + "DiSCaRD": actionDiscard, + "DiSCaRd": actionDiscard, + "DiSCarD": actionDiscard, + "DiSCard": actionDiscard, + "DiScARD": actionDiscard, + "DiScARd": actionDiscard, + "DiScArD": actionDiscard, + "DiScArd": actionDiscard, + "DiScaRD": actionDiscard, + "DiScaRd": actionDiscard, + "DiScarD": actionDiscard, + "DiScard": actionDiscard, + "DisCARD": actionDiscard, + "DisCARd": actionDiscard, + "DisCArD": actionDiscard, + "DisCArd": actionDiscard, + "DisCaRD": actionDiscard, + "DisCaRd": actionDiscard, + "DisCarD": actionDiscard, + "DisCard": actionDiscard, + "DiscARD": actionDiscard, + "DiscARd": actionDiscard, + "DiscArD": actionDiscard, + "DiscArd": actionDiscard, + "DiscaRD": actionDiscard, + "DiscaRd": actionDiscard, + "DiscarD": actionDiscard, + "Discard": actionDiscard, + "dISCARD": actionDiscard, + "dISCARd": actionDiscard, + "dISCArD": actionDiscard, + "dISCArd": actionDiscard, + "dISCaRD": actionDiscard, + "dISCaRd": actionDiscard, + "dISCarD": actionDiscard, + "dISCard": actionDiscard, + "dIScARD": actionDiscard, + "dIScARd": actionDiscard, + "dIScArD": actionDiscard, + "dIScArd": actionDiscard, + "dIScaRD": actionDiscard, + "dIScaRd": actionDiscard, + "dIScarD": actionDiscard, + "dIScard": actionDiscard, + "dIsCARD": actionDiscard, + "dIsCARd": actionDiscard, + "dIsCArD": actionDiscard, + "dIsCArd": actionDiscard, + "dIsCaRD": actionDiscard, + "dIsCaRd": actionDiscard, + "dIsCarD": actionDiscard, + "dIsCard": actionDiscard, + "dIscARD": actionDiscard, + "dIscARd": actionDiscard, + "dIscArD": actionDiscard, + "dIscArd": actionDiscard, + "dIscaRD": actionDiscard, + "dIscaRd": actionDiscard, + "dIscarD": actionDiscard, + "dIscard": actionDiscard, + "diSCARD": actionDiscard, + "diSCARd": actionDiscard, + "diSCArD": actionDiscard, + "diSCArd": actionDiscard, + "diSCaRD": actionDiscard, + "diSCaRd": actionDiscard, + "diSCarD": actionDiscard, + "diSCard": actionDiscard, + "diScARD": actionDiscard, + "diScARd": actionDiscard, + "diScArD": actionDiscard, + "diScArd": actionDiscard, + "diScaRD": actionDiscard, + "diScaRd": actionDiscard, + "diScarD": actionDiscard, + "diScard": actionDiscard, + "disCARD": actionDiscard, + "disCARd": actionDiscard, + "disCArD": actionDiscard, + "disCArd": actionDiscard, + "disCaRD": actionDiscard, + "disCaRd": actionDiscard, + "disCarD": actionDiscard, + "disCard": actionDiscard, + "discARD": actionDiscard, + "discARd": actionDiscard, + "discArD": actionDiscard, + "discArd": actionDiscard, + "discaRD": actionDiscard, + "discaRd": actionDiscard, + "discarD": actionDiscard, + "discard": actionDiscard, + "PSUBSCRIBE": actionPsubscribe, + "PSUBSCRIBe": actionPsubscribe, + "PSUBSCRIbE": actionPsubscribe, + "PSUBSCRIbe": actionPsubscribe, + "PSUBSCRiBE": actionPsubscribe, + "PSUBSCRiBe": actionPsubscribe, + "PSUBSCRibE": actionPsubscribe, + "PSUBSCRibe": actionPsubscribe, + "PSUBSCrIBE": actionPsubscribe, + "PSUBSCrIBe": actionPsubscribe, + "PSUBSCrIbE": actionPsubscribe, + "PSUBSCrIbe": actionPsubscribe, + "PSUBSCriBE": actionPsubscribe, + "PSUBSCriBe": actionPsubscribe, + "PSUBSCribE": actionPsubscribe, + "PSUBSCribe": actionPsubscribe, + "PSUBScRIBE": actionPsubscribe, + "PSUBScRIBe": actionPsubscribe, + "PSUBScRIbE": actionPsubscribe, + "PSUBScRIbe": actionPsubscribe, + "PSUBScRiBE": actionPsubscribe, + "PSUBScRiBe": actionPsubscribe, + "PSUBScRibE": actionPsubscribe, + "PSUBScRibe": actionPsubscribe, + "PSUBScrIBE": actionPsubscribe, + "PSUBScrIBe": actionPsubscribe, + "PSUBScrIbE": actionPsubscribe, + "PSUBScrIbe": actionPsubscribe, + "PSUBScriBE": actionPsubscribe, + "PSUBScriBe": actionPsubscribe, + "PSUBScribE": actionPsubscribe, + "PSUBScribe": actionPsubscribe, + "PSUBsCRIBE": actionPsubscribe, + "PSUBsCRIBe": actionPsubscribe, + "PSUBsCRIbE": actionPsubscribe, + "PSUBsCRIbe": actionPsubscribe, + "PSUBsCRiBE": actionPsubscribe, + "PSUBsCRiBe": actionPsubscribe, + "PSUBsCRibE": actionPsubscribe, + "PSUBsCRibe": actionPsubscribe, + "PSUBsCrIBE": actionPsubscribe, + "PSUBsCrIBe": actionPsubscribe, + "PSUBsCrIbE": actionPsubscribe, + "PSUBsCrIbe": actionPsubscribe, + "PSUBsCriBE": actionPsubscribe, + "PSUBsCriBe": actionPsubscribe, + "PSUBsCribE": actionPsubscribe, + "PSUBsCribe": actionPsubscribe, + "PSUBscRIBE": actionPsubscribe, + "PSUBscRIBe": actionPsubscribe, + "PSUBscRIbE": actionPsubscribe, + "PSUBscRIbe": actionPsubscribe, + "PSUBscRiBE": actionPsubscribe, + "PSUBscRiBe": actionPsubscribe, + "PSUBscRibE": actionPsubscribe, + "PSUBscRibe": actionPsubscribe, + "PSUBscrIBE": actionPsubscribe, + "PSUBscrIBe": actionPsubscribe, + "PSUBscrIbE": actionPsubscribe, + "PSUBscrIbe": actionPsubscribe, + "PSUBscriBE": actionPsubscribe, + "PSUBscriBe": actionPsubscribe, + "PSUBscribE": actionPsubscribe, + "PSUBscribe": actionPsubscribe, + "PSUbSCRIBE": actionPsubscribe, + "PSUbSCRIBe": actionPsubscribe, + "PSUbSCRIbE": actionPsubscribe, + "PSUbSCRIbe": actionPsubscribe, + "PSUbSCRiBE": actionPsubscribe, + "PSUbSCRiBe": actionPsubscribe, + "PSUbSCRibE": actionPsubscribe, + "PSUbSCRibe": actionPsubscribe, + "PSUbSCrIBE": actionPsubscribe, + "PSUbSCrIBe": actionPsubscribe, + "PSUbSCrIbE": actionPsubscribe, + "PSUbSCrIbe": actionPsubscribe, + "PSUbSCriBE": actionPsubscribe, + "PSUbSCriBe": actionPsubscribe, + "PSUbSCribE": actionPsubscribe, + "PSUbSCribe": actionPsubscribe, + "PSUbScRIBE": actionPsubscribe, + "PSUbScRIBe": actionPsubscribe, + "PSUbScRIbE": actionPsubscribe, + "PSUbScRIbe": actionPsubscribe, + "PSUbScRiBE": actionPsubscribe, + "PSUbScRiBe": actionPsubscribe, + "PSUbScRibE": actionPsubscribe, + "PSUbScRibe": actionPsubscribe, + "PSUbScrIBE": actionPsubscribe, + "PSUbScrIBe": actionPsubscribe, + "PSUbScrIbE": actionPsubscribe, + "PSUbScrIbe": actionPsubscribe, + "PSUbScriBE": actionPsubscribe, + "PSUbScriBe": actionPsubscribe, + "PSUbScribE": actionPsubscribe, + "PSUbScribe": actionPsubscribe, + "PSUbsCRIBE": actionPsubscribe, + "PSUbsCRIBe": actionPsubscribe, + "PSUbsCRIbE": actionPsubscribe, + "PSUbsCRIbe": actionPsubscribe, + "PSUbsCRiBE": actionPsubscribe, + "PSUbsCRiBe": actionPsubscribe, + "PSUbsCRibE": actionPsubscribe, + "PSUbsCRibe": actionPsubscribe, + "PSUbsCrIBE": actionPsubscribe, + "PSUbsCrIBe": actionPsubscribe, + "PSUbsCrIbE": actionPsubscribe, + "PSUbsCrIbe": actionPsubscribe, + "PSUbsCriBE": actionPsubscribe, + "PSUbsCriBe": actionPsubscribe, + "PSUbsCribE": actionPsubscribe, + "PSUbsCribe": actionPsubscribe, + "PSUbscRIBE": actionPsubscribe, + "PSUbscRIBe": actionPsubscribe, + "PSUbscRIbE": actionPsubscribe, + "PSUbscRIbe": actionPsubscribe, + "PSUbscRiBE": actionPsubscribe, + "PSUbscRiBe": actionPsubscribe, + "PSUbscRibE": actionPsubscribe, + "PSUbscRibe": actionPsubscribe, + "PSUbscrIBE": actionPsubscribe, + "PSUbscrIBe": actionPsubscribe, + "PSUbscrIbE": actionPsubscribe, + "PSUbscrIbe": actionPsubscribe, + "PSUbscriBE": actionPsubscribe, + "PSUbscriBe": actionPsubscribe, + "PSUbscribE": actionPsubscribe, + "PSUbscribe": actionPsubscribe, + "PSuBSCRIBE": actionPsubscribe, + "PSuBSCRIBe": actionPsubscribe, + "PSuBSCRIbE": actionPsubscribe, + "PSuBSCRIbe": actionPsubscribe, + "PSuBSCRiBE": actionPsubscribe, + "PSuBSCRiBe": actionPsubscribe, + "PSuBSCRibE": actionPsubscribe, + "PSuBSCRibe": actionPsubscribe, + "PSuBSCrIBE": actionPsubscribe, + "PSuBSCrIBe": actionPsubscribe, + "PSuBSCrIbE": actionPsubscribe, + "PSuBSCrIbe": actionPsubscribe, + "PSuBSCriBE": actionPsubscribe, + "PSuBSCriBe": actionPsubscribe, + "PSuBSCribE": actionPsubscribe, + "PSuBSCribe": actionPsubscribe, + "PSuBScRIBE": actionPsubscribe, + "PSuBScRIBe": actionPsubscribe, + "PSuBScRIbE": actionPsubscribe, + "PSuBScRIbe": actionPsubscribe, + "PSuBScRiBE": actionPsubscribe, + "PSuBScRiBe": actionPsubscribe, + "PSuBScRibE": actionPsubscribe, + "PSuBScRibe": actionPsubscribe, + "PSuBScrIBE": actionPsubscribe, + "PSuBScrIBe": actionPsubscribe, + "PSuBScrIbE": actionPsubscribe, + "PSuBScrIbe": actionPsubscribe, + "PSuBScriBE": actionPsubscribe, + "PSuBScriBe": actionPsubscribe, + "PSuBScribE": actionPsubscribe, + "PSuBScribe": actionPsubscribe, + "PSuBsCRIBE": actionPsubscribe, + "PSuBsCRIBe": actionPsubscribe, + "PSuBsCRIbE": actionPsubscribe, + "PSuBsCRIbe": actionPsubscribe, + "PSuBsCRiBE": actionPsubscribe, + "PSuBsCRiBe": actionPsubscribe, + "PSuBsCRibE": actionPsubscribe, + "PSuBsCRibe": actionPsubscribe, + "PSuBsCrIBE": actionPsubscribe, + "PSuBsCrIBe": actionPsubscribe, + "PSuBsCrIbE": actionPsubscribe, + "PSuBsCrIbe": actionPsubscribe, + "PSuBsCriBE": actionPsubscribe, + "PSuBsCriBe": actionPsubscribe, + "PSuBsCribE": actionPsubscribe, + "PSuBsCribe": actionPsubscribe, + "PSuBscRIBE": actionPsubscribe, + "PSuBscRIBe": actionPsubscribe, + "PSuBscRIbE": actionPsubscribe, + "PSuBscRIbe": actionPsubscribe, + "PSuBscRiBE": actionPsubscribe, + "PSuBscRiBe": actionPsubscribe, + "PSuBscRibE": actionPsubscribe, + "PSuBscRibe": actionPsubscribe, + "PSuBscrIBE": actionPsubscribe, + "PSuBscrIBe": actionPsubscribe, + "PSuBscrIbE": actionPsubscribe, + "PSuBscrIbe": actionPsubscribe, + "PSuBscriBE": actionPsubscribe, + "PSuBscriBe": actionPsubscribe, + "PSuBscribE": actionPsubscribe, + "PSuBscribe": actionPsubscribe, + "PSubSCRIBE": actionPsubscribe, + "PSubSCRIBe": actionPsubscribe, + "PSubSCRIbE": actionPsubscribe, + "PSubSCRIbe": actionPsubscribe, + "PSubSCRiBE": actionPsubscribe, + "PSubSCRiBe": actionPsubscribe, + "PSubSCRibE": actionPsubscribe, + "PSubSCRibe": actionPsubscribe, + "PSubSCrIBE": actionPsubscribe, + "PSubSCrIBe": actionPsubscribe, + "PSubSCrIbE": actionPsubscribe, + "PSubSCrIbe": actionPsubscribe, + "PSubSCriBE": actionPsubscribe, + "PSubSCriBe": actionPsubscribe, + "PSubSCribE": actionPsubscribe, + "PSubSCribe": actionPsubscribe, + "PSubScRIBE": actionPsubscribe, + "PSubScRIBe": actionPsubscribe, + "PSubScRIbE": actionPsubscribe, + "PSubScRIbe": actionPsubscribe, + "PSubScRiBE": actionPsubscribe, + "PSubScRiBe": actionPsubscribe, + "PSubScRibE": actionPsubscribe, + "PSubScRibe": actionPsubscribe, + "PSubScrIBE": actionPsubscribe, + "PSubScrIBe": actionPsubscribe, + "PSubScrIbE": actionPsubscribe, + "PSubScrIbe": actionPsubscribe, + "PSubScriBE": actionPsubscribe, + "PSubScriBe": actionPsubscribe, + "PSubScribE": actionPsubscribe, + "PSubScribe": actionPsubscribe, + "PSubsCRIBE": actionPsubscribe, + "PSubsCRIBe": actionPsubscribe, + "PSubsCRIbE": actionPsubscribe, + "PSubsCRIbe": actionPsubscribe, + "PSubsCRiBE": actionPsubscribe, + "PSubsCRiBe": actionPsubscribe, + "PSubsCRibE": actionPsubscribe, + "PSubsCRibe": actionPsubscribe, + "PSubsCrIBE": actionPsubscribe, + "PSubsCrIBe": actionPsubscribe, + "PSubsCrIbE": actionPsubscribe, + "PSubsCrIbe": actionPsubscribe, + "PSubsCriBE": actionPsubscribe, + "PSubsCriBe": actionPsubscribe, + "PSubsCribE": actionPsubscribe, + "PSubsCribe": actionPsubscribe, + "PSubscRIBE": actionPsubscribe, + "PSubscRIBe": actionPsubscribe, + "PSubscRIbE": actionPsubscribe, + "PSubscRIbe": actionPsubscribe, + "PSubscRiBE": actionPsubscribe, + "PSubscRiBe": actionPsubscribe, + "PSubscRibE": actionPsubscribe, + "PSubscRibe": actionPsubscribe, + "PSubscrIBE": actionPsubscribe, + "PSubscrIBe": actionPsubscribe, + "PSubscrIbE": actionPsubscribe, + "PSubscrIbe": actionPsubscribe, + "PSubscriBE": actionPsubscribe, + "PSubscriBe": actionPsubscribe, + "PSubscribE": actionPsubscribe, + "PSubscribe": actionPsubscribe, + "PsUBSCRIBE": actionPsubscribe, + "PsUBSCRIBe": actionPsubscribe, + "PsUBSCRIbE": actionPsubscribe, + "PsUBSCRIbe": actionPsubscribe, + "PsUBSCRiBE": actionPsubscribe, + "PsUBSCRiBe": actionPsubscribe, + "PsUBSCRibE": actionPsubscribe, + "PsUBSCRibe": actionPsubscribe, + "PsUBSCrIBE": actionPsubscribe, + "PsUBSCrIBe": actionPsubscribe, + "PsUBSCrIbE": actionPsubscribe, + "PsUBSCrIbe": actionPsubscribe, + "PsUBSCriBE": actionPsubscribe, + "PsUBSCriBe": actionPsubscribe, + "PsUBSCribE": actionPsubscribe, + "PsUBSCribe": actionPsubscribe, + "PsUBScRIBE": actionPsubscribe, + "PsUBScRIBe": actionPsubscribe, + "PsUBScRIbE": actionPsubscribe, + "PsUBScRIbe": actionPsubscribe, + "PsUBScRiBE": actionPsubscribe, + "PsUBScRiBe": actionPsubscribe, + "PsUBScRibE": actionPsubscribe, + "PsUBScRibe": actionPsubscribe, + "PsUBScrIBE": actionPsubscribe, + "PsUBScrIBe": actionPsubscribe, + "PsUBScrIbE": actionPsubscribe, + "PsUBScrIbe": actionPsubscribe, + "PsUBScriBE": actionPsubscribe, + "PsUBScriBe": actionPsubscribe, + "PsUBScribE": actionPsubscribe, + "PsUBScribe": actionPsubscribe, + "PsUBsCRIBE": actionPsubscribe, + "PsUBsCRIBe": actionPsubscribe, + "PsUBsCRIbE": actionPsubscribe, + "PsUBsCRIbe": actionPsubscribe, + "PsUBsCRiBE": actionPsubscribe, + "PsUBsCRiBe": actionPsubscribe, + "PsUBsCRibE": actionPsubscribe, + "PsUBsCRibe": actionPsubscribe, + "PsUBsCrIBE": actionPsubscribe, + "PsUBsCrIBe": actionPsubscribe, + "PsUBsCrIbE": actionPsubscribe, + "PsUBsCrIbe": actionPsubscribe, + "PsUBsCriBE": actionPsubscribe, + "PsUBsCriBe": actionPsubscribe, + "PsUBsCribE": actionPsubscribe, + "PsUBsCribe": actionPsubscribe, + "PsUBscRIBE": actionPsubscribe, + "PsUBscRIBe": actionPsubscribe, + "PsUBscRIbE": actionPsubscribe, + "PsUBscRIbe": actionPsubscribe, + "PsUBscRiBE": actionPsubscribe, + "PsUBscRiBe": actionPsubscribe, + "PsUBscRibE": actionPsubscribe, + "PsUBscRibe": actionPsubscribe, + "PsUBscrIBE": actionPsubscribe, + "PsUBscrIBe": actionPsubscribe, + "PsUBscrIbE": actionPsubscribe, + "PsUBscrIbe": actionPsubscribe, + "PsUBscriBE": actionPsubscribe, + "PsUBscriBe": actionPsubscribe, + "PsUBscribE": actionPsubscribe, + "PsUBscribe": actionPsubscribe, + "PsUbSCRIBE": actionPsubscribe, + "PsUbSCRIBe": actionPsubscribe, + "PsUbSCRIbE": actionPsubscribe, + "PsUbSCRIbe": actionPsubscribe, + "PsUbSCRiBE": actionPsubscribe, + "PsUbSCRiBe": actionPsubscribe, + "PsUbSCRibE": actionPsubscribe, + "PsUbSCRibe": actionPsubscribe, + "PsUbSCrIBE": actionPsubscribe, + "PsUbSCrIBe": actionPsubscribe, + "PsUbSCrIbE": actionPsubscribe, + "PsUbSCrIbe": actionPsubscribe, + "PsUbSCriBE": actionPsubscribe, + "PsUbSCriBe": actionPsubscribe, + "PsUbSCribE": actionPsubscribe, + "PsUbSCribe": actionPsubscribe, + "PsUbScRIBE": actionPsubscribe, + "PsUbScRIBe": actionPsubscribe, + "PsUbScRIbE": actionPsubscribe, + "PsUbScRIbe": actionPsubscribe, + "PsUbScRiBE": actionPsubscribe, + "PsUbScRiBe": actionPsubscribe, + "PsUbScRibE": actionPsubscribe, + "PsUbScRibe": actionPsubscribe, + "PsUbScrIBE": actionPsubscribe, + "PsUbScrIBe": actionPsubscribe, + "PsUbScrIbE": actionPsubscribe, + "PsUbScrIbe": actionPsubscribe, + "PsUbScriBE": actionPsubscribe, + "PsUbScriBe": actionPsubscribe, + "PsUbScribE": actionPsubscribe, + "PsUbScribe": actionPsubscribe, + "PsUbsCRIBE": actionPsubscribe, + "PsUbsCRIBe": actionPsubscribe, + "PsUbsCRIbE": actionPsubscribe, + "PsUbsCRIbe": actionPsubscribe, + "PsUbsCRiBE": actionPsubscribe, + "PsUbsCRiBe": actionPsubscribe, + "PsUbsCRibE": actionPsubscribe, + "PsUbsCRibe": actionPsubscribe, + "PsUbsCrIBE": actionPsubscribe, + "PsUbsCrIBe": actionPsubscribe, + "PsUbsCrIbE": actionPsubscribe, + "PsUbsCrIbe": actionPsubscribe, + "PsUbsCriBE": actionPsubscribe, + "PsUbsCriBe": actionPsubscribe, + "PsUbsCribE": actionPsubscribe, + "PsUbsCribe": actionPsubscribe, + "PsUbscRIBE": actionPsubscribe, + "PsUbscRIBe": actionPsubscribe, + "PsUbscRIbE": actionPsubscribe, + "PsUbscRIbe": actionPsubscribe, + "PsUbscRiBE": actionPsubscribe, + "PsUbscRiBe": actionPsubscribe, + "PsUbscRibE": actionPsubscribe, + "PsUbscRibe": actionPsubscribe, + "PsUbscrIBE": actionPsubscribe, + "PsUbscrIBe": actionPsubscribe, + "PsUbscrIbE": actionPsubscribe, + "PsUbscrIbe": actionPsubscribe, + "PsUbscriBE": actionPsubscribe, + "PsUbscriBe": actionPsubscribe, + "PsUbscribE": actionPsubscribe, + "PsUbscribe": actionPsubscribe, + "PsuBSCRIBE": actionPsubscribe, + "PsuBSCRIBe": actionPsubscribe, + "PsuBSCRIbE": actionPsubscribe, + "PsuBSCRIbe": actionPsubscribe, + "PsuBSCRiBE": actionPsubscribe, + "PsuBSCRiBe": actionPsubscribe, + "PsuBSCRibE": actionPsubscribe, + "PsuBSCRibe": actionPsubscribe, + "PsuBSCrIBE": actionPsubscribe, + "PsuBSCrIBe": actionPsubscribe, + "PsuBSCrIbE": actionPsubscribe, + "PsuBSCrIbe": actionPsubscribe, + "PsuBSCriBE": actionPsubscribe, + "PsuBSCriBe": actionPsubscribe, + "PsuBSCribE": actionPsubscribe, + "PsuBSCribe": actionPsubscribe, + "PsuBScRIBE": actionPsubscribe, + "PsuBScRIBe": actionPsubscribe, + "PsuBScRIbE": actionPsubscribe, + "PsuBScRIbe": actionPsubscribe, + "PsuBScRiBE": actionPsubscribe, + "PsuBScRiBe": actionPsubscribe, + "PsuBScRibE": actionPsubscribe, + "PsuBScRibe": actionPsubscribe, + "PsuBScrIBE": actionPsubscribe, + "PsuBScrIBe": actionPsubscribe, + "PsuBScrIbE": actionPsubscribe, + "PsuBScrIbe": actionPsubscribe, + "PsuBScriBE": actionPsubscribe, + "PsuBScriBe": actionPsubscribe, + "PsuBScribE": actionPsubscribe, + "PsuBScribe": actionPsubscribe, + "PsuBsCRIBE": actionPsubscribe, + "PsuBsCRIBe": actionPsubscribe, + "PsuBsCRIbE": actionPsubscribe, + "PsuBsCRIbe": actionPsubscribe, + "PsuBsCRiBE": actionPsubscribe, + "PsuBsCRiBe": actionPsubscribe, + "PsuBsCRibE": actionPsubscribe, + "PsuBsCRibe": actionPsubscribe, + "PsuBsCrIBE": actionPsubscribe, + "PsuBsCrIBe": actionPsubscribe, + "PsuBsCrIbE": actionPsubscribe, + "PsuBsCrIbe": actionPsubscribe, + "PsuBsCriBE": actionPsubscribe, + "PsuBsCriBe": actionPsubscribe, + "PsuBsCribE": actionPsubscribe, + "PsuBsCribe": actionPsubscribe, + "PsuBscRIBE": actionPsubscribe, + "PsuBscRIBe": actionPsubscribe, + "PsuBscRIbE": actionPsubscribe, + "PsuBscRIbe": actionPsubscribe, + "PsuBscRiBE": actionPsubscribe, + "PsuBscRiBe": actionPsubscribe, + "PsuBscRibE": actionPsubscribe, + "PsuBscRibe": actionPsubscribe, + "PsuBscrIBE": actionPsubscribe, + "PsuBscrIBe": actionPsubscribe, + "PsuBscrIbE": actionPsubscribe, + "PsuBscrIbe": actionPsubscribe, + "PsuBscriBE": actionPsubscribe, + "PsuBscriBe": actionPsubscribe, + "PsuBscribE": actionPsubscribe, + "PsuBscribe": actionPsubscribe, + "PsubSCRIBE": actionPsubscribe, + "PsubSCRIBe": actionPsubscribe, + "PsubSCRIbE": actionPsubscribe, + "PsubSCRIbe": actionPsubscribe, + "PsubSCRiBE": actionPsubscribe, + "PsubSCRiBe": actionPsubscribe, + "PsubSCRibE": actionPsubscribe, + "PsubSCRibe": actionPsubscribe, + "PsubSCrIBE": actionPsubscribe, + "PsubSCrIBe": actionPsubscribe, + "PsubSCrIbE": actionPsubscribe, + "PsubSCrIbe": actionPsubscribe, + "PsubSCriBE": actionPsubscribe, + "PsubSCriBe": actionPsubscribe, + "PsubSCribE": actionPsubscribe, + "PsubSCribe": actionPsubscribe, + "PsubScRIBE": actionPsubscribe, + "PsubScRIBe": actionPsubscribe, + "PsubScRIbE": actionPsubscribe, + "PsubScRIbe": actionPsubscribe, + "PsubScRiBE": actionPsubscribe, + "PsubScRiBe": actionPsubscribe, + "PsubScRibE": actionPsubscribe, + "PsubScRibe": actionPsubscribe, + "PsubScrIBE": actionPsubscribe, + "PsubScrIBe": actionPsubscribe, + "PsubScrIbE": actionPsubscribe, + "PsubScrIbe": actionPsubscribe, + "PsubScriBE": actionPsubscribe, + "PsubScriBe": actionPsubscribe, + "PsubScribE": actionPsubscribe, + "PsubScribe": actionPsubscribe, + "PsubsCRIBE": actionPsubscribe, + "PsubsCRIBe": actionPsubscribe, + "PsubsCRIbE": actionPsubscribe, + "PsubsCRIbe": actionPsubscribe, + "PsubsCRiBE": actionPsubscribe, + "PsubsCRiBe": actionPsubscribe, + "PsubsCRibE": actionPsubscribe, + "PsubsCRibe": actionPsubscribe, + "PsubsCrIBE": actionPsubscribe, + "PsubsCrIBe": actionPsubscribe, + "PsubsCrIbE": actionPsubscribe, + "PsubsCrIbe": actionPsubscribe, + "PsubsCriBE": actionPsubscribe, + "PsubsCriBe": actionPsubscribe, + "PsubsCribE": actionPsubscribe, + "PsubsCribe": actionPsubscribe, + "PsubscRIBE": actionPsubscribe, + "PsubscRIBe": actionPsubscribe, + "PsubscRIbE": actionPsubscribe, + "PsubscRIbe": actionPsubscribe, + "PsubscRiBE": actionPsubscribe, + "PsubscRiBe": actionPsubscribe, + "PsubscRibE": actionPsubscribe, + "PsubscRibe": actionPsubscribe, + "PsubscrIBE": actionPsubscribe, + "PsubscrIBe": actionPsubscribe, + "PsubscrIbE": actionPsubscribe, + "PsubscrIbe": actionPsubscribe, + "PsubscriBE": actionPsubscribe, + "PsubscriBe": actionPsubscribe, + "PsubscribE": actionPsubscribe, + "Psubscribe": actionPsubscribe, + "pSUBSCRIBE": actionPsubscribe, + "pSUBSCRIBe": actionPsubscribe, + "pSUBSCRIbE": actionPsubscribe, + "pSUBSCRIbe": actionPsubscribe, + "pSUBSCRiBE": actionPsubscribe, + "pSUBSCRiBe": actionPsubscribe, + "pSUBSCRibE": actionPsubscribe, + "pSUBSCRibe": actionPsubscribe, + "pSUBSCrIBE": actionPsubscribe, + "pSUBSCrIBe": actionPsubscribe, + "pSUBSCrIbE": actionPsubscribe, + "pSUBSCrIbe": actionPsubscribe, + "pSUBSCriBE": actionPsubscribe, + "pSUBSCriBe": actionPsubscribe, + "pSUBSCribE": actionPsubscribe, + "pSUBSCribe": actionPsubscribe, + "pSUBScRIBE": actionPsubscribe, + "pSUBScRIBe": actionPsubscribe, + "pSUBScRIbE": actionPsubscribe, + "pSUBScRIbe": actionPsubscribe, + "pSUBScRiBE": actionPsubscribe, + "pSUBScRiBe": actionPsubscribe, + "pSUBScRibE": actionPsubscribe, + "pSUBScRibe": actionPsubscribe, + "pSUBScrIBE": actionPsubscribe, + "pSUBScrIBe": actionPsubscribe, + "pSUBScrIbE": actionPsubscribe, + "pSUBScrIbe": actionPsubscribe, + "pSUBScriBE": actionPsubscribe, + "pSUBScriBe": actionPsubscribe, + "pSUBScribE": actionPsubscribe, + "pSUBScribe": actionPsubscribe, + "pSUBsCRIBE": actionPsubscribe, + "pSUBsCRIBe": actionPsubscribe, + "pSUBsCRIbE": actionPsubscribe, + "pSUBsCRIbe": actionPsubscribe, + "pSUBsCRiBE": actionPsubscribe, + "pSUBsCRiBe": actionPsubscribe, + "pSUBsCRibE": actionPsubscribe, + "pSUBsCRibe": actionPsubscribe, + "pSUBsCrIBE": actionPsubscribe, + "pSUBsCrIBe": actionPsubscribe, + "pSUBsCrIbE": actionPsubscribe, + "pSUBsCrIbe": actionPsubscribe, + "pSUBsCriBE": actionPsubscribe, + "pSUBsCriBe": actionPsubscribe, + "pSUBsCribE": actionPsubscribe, + "pSUBsCribe": actionPsubscribe, + "pSUBscRIBE": actionPsubscribe, + "pSUBscRIBe": actionPsubscribe, + "pSUBscRIbE": actionPsubscribe, + "pSUBscRIbe": actionPsubscribe, + "pSUBscRiBE": actionPsubscribe, + "pSUBscRiBe": actionPsubscribe, + "pSUBscRibE": actionPsubscribe, + "pSUBscRibe": actionPsubscribe, + "pSUBscrIBE": actionPsubscribe, + "pSUBscrIBe": actionPsubscribe, + "pSUBscrIbE": actionPsubscribe, + "pSUBscrIbe": actionPsubscribe, + "pSUBscriBE": actionPsubscribe, + "pSUBscriBe": actionPsubscribe, + "pSUBscribE": actionPsubscribe, + "pSUBscribe": actionPsubscribe, + "pSUbSCRIBE": actionPsubscribe, + "pSUbSCRIBe": actionPsubscribe, + "pSUbSCRIbE": actionPsubscribe, + "pSUbSCRIbe": actionPsubscribe, + "pSUbSCRiBE": actionPsubscribe, + "pSUbSCRiBe": actionPsubscribe, + "pSUbSCRibE": actionPsubscribe, + "pSUbSCRibe": actionPsubscribe, + "pSUbSCrIBE": actionPsubscribe, + "pSUbSCrIBe": actionPsubscribe, + "pSUbSCrIbE": actionPsubscribe, + "pSUbSCrIbe": actionPsubscribe, + "pSUbSCriBE": actionPsubscribe, + "pSUbSCriBe": actionPsubscribe, + "pSUbSCribE": actionPsubscribe, + "pSUbSCribe": actionPsubscribe, + "pSUbScRIBE": actionPsubscribe, + "pSUbScRIBe": actionPsubscribe, + "pSUbScRIbE": actionPsubscribe, + "pSUbScRIbe": actionPsubscribe, + "pSUbScRiBE": actionPsubscribe, + "pSUbScRiBe": actionPsubscribe, + "pSUbScRibE": actionPsubscribe, + "pSUbScRibe": actionPsubscribe, + "pSUbScrIBE": actionPsubscribe, + "pSUbScrIBe": actionPsubscribe, + "pSUbScrIbE": actionPsubscribe, + "pSUbScrIbe": actionPsubscribe, + "pSUbScriBE": actionPsubscribe, + "pSUbScriBe": actionPsubscribe, + "pSUbScribE": actionPsubscribe, + "pSUbScribe": actionPsubscribe, + "pSUbsCRIBE": actionPsubscribe, + "pSUbsCRIBe": actionPsubscribe, + "pSUbsCRIbE": actionPsubscribe, + "pSUbsCRIbe": actionPsubscribe, + "pSUbsCRiBE": actionPsubscribe, + "pSUbsCRiBe": actionPsubscribe, + "pSUbsCRibE": actionPsubscribe, + "pSUbsCRibe": actionPsubscribe, + "pSUbsCrIBE": actionPsubscribe, + "pSUbsCrIBe": actionPsubscribe, + "pSUbsCrIbE": actionPsubscribe, + "pSUbsCrIbe": actionPsubscribe, + "pSUbsCriBE": actionPsubscribe, + "pSUbsCriBe": actionPsubscribe, + "pSUbsCribE": actionPsubscribe, + "pSUbsCribe": actionPsubscribe, + "pSUbscRIBE": actionPsubscribe, + "pSUbscRIBe": actionPsubscribe, + "pSUbscRIbE": actionPsubscribe, + "pSUbscRIbe": actionPsubscribe, + "pSUbscRiBE": actionPsubscribe, + "pSUbscRiBe": actionPsubscribe, + "pSUbscRibE": actionPsubscribe, + "pSUbscRibe": actionPsubscribe, + "pSUbscrIBE": actionPsubscribe, + "pSUbscrIBe": actionPsubscribe, + "pSUbscrIbE": actionPsubscribe, + "pSUbscrIbe": actionPsubscribe, + "pSUbscriBE": actionPsubscribe, + "pSUbscriBe": actionPsubscribe, + "pSUbscribE": actionPsubscribe, + "pSUbscribe": actionPsubscribe, + "pSuBSCRIBE": actionPsubscribe, + "pSuBSCRIBe": actionPsubscribe, + "pSuBSCRIbE": actionPsubscribe, + "pSuBSCRIbe": actionPsubscribe, + "pSuBSCRiBE": actionPsubscribe, + "pSuBSCRiBe": actionPsubscribe, + "pSuBSCRibE": actionPsubscribe, + "pSuBSCRibe": actionPsubscribe, + "pSuBSCrIBE": actionPsubscribe, + "pSuBSCrIBe": actionPsubscribe, + "pSuBSCrIbE": actionPsubscribe, + "pSuBSCrIbe": actionPsubscribe, + "pSuBSCriBE": actionPsubscribe, + "pSuBSCriBe": actionPsubscribe, + "pSuBSCribE": actionPsubscribe, + "pSuBSCribe": actionPsubscribe, + "pSuBScRIBE": actionPsubscribe, + "pSuBScRIBe": actionPsubscribe, + "pSuBScRIbE": actionPsubscribe, + "pSuBScRIbe": actionPsubscribe, + "pSuBScRiBE": actionPsubscribe, + "pSuBScRiBe": actionPsubscribe, + "pSuBScRibE": actionPsubscribe, + "pSuBScRibe": actionPsubscribe, + "pSuBScrIBE": actionPsubscribe, + "pSuBScrIBe": actionPsubscribe, + "pSuBScrIbE": actionPsubscribe, + "pSuBScrIbe": actionPsubscribe, + "pSuBScriBE": actionPsubscribe, + "pSuBScriBe": actionPsubscribe, + "pSuBScribE": actionPsubscribe, + "pSuBScribe": actionPsubscribe, + "pSuBsCRIBE": actionPsubscribe, + "pSuBsCRIBe": actionPsubscribe, + "pSuBsCRIbE": actionPsubscribe, + "pSuBsCRIbe": actionPsubscribe, + "pSuBsCRiBE": actionPsubscribe, + "pSuBsCRiBe": actionPsubscribe, + "pSuBsCRibE": actionPsubscribe, + "pSuBsCRibe": actionPsubscribe, + "pSuBsCrIBE": actionPsubscribe, + "pSuBsCrIBe": actionPsubscribe, + "pSuBsCrIbE": actionPsubscribe, + "pSuBsCrIbe": actionPsubscribe, + "pSuBsCriBE": actionPsubscribe, + "pSuBsCriBe": actionPsubscribe, + "pSuBsCribE": actionPsubscribe, + "pSuBsCribe": actionPsubscribe, + "pSuBscRIBE": actionPsubscribe, + "pSuBscRIBe": actionPsubscribe, + "pSuBscRIbE": actionPsubscribe, + "pSuBscRIbe": actionPsubscribe, + "pSuBscRiBE": actionPsubscribe, + "pSuBscRiBe": actionPsubscribe, + "pSuBscRibE": actionPsubscribe, + "pSuBscRibe": actionPsubscribe, + "pSuBscrIBE": actionPsubscribe, + "pSuBscrIBe": actionPsubscribe, + "pSuBscrIbE": actionPsubscribe, + "pSuBscrIbe": actionPsubscribe, + "pSuBscriBE": actionPsubscribe, + "pSuBscriBe": actionPsubscribe, + "pSuBscribE": actionPsubscribe, + "pSuBscribe": actionPsubscribe, + "pSubSCRIBE": actionPsubscribe, + "pSubSCRIBe": actionPsubscribe, + "pSubSCRIbE": actionPsubscribe, + "pSubSCRIbe": actionPsubscribe, + "pSubSCRiBE": actionPsubscribe, + "pSubSCRiBe": actionPsubscribe, + "pSubSCRibE": actionPsubscribe, + "pSubSCRibe": actionPsubscribe, + "pSubSCrIBE": actionPsubscribe, + "pSubSCrIBe": actionPsubscribe, + "pSubSCrIbE": actionPsubscribe, + "pSubSCrIbe": actionPsubscribe, + "pSubSCriBE": actionPsubscribe, + "pSubSCriBe": actionPsubscribe, + "pSubSCribE": actionPsubscribe, + "pSubSCribe": actionPsubscribe, + "pSubScRIBE": actionPsubscribe, + "pSubScRIBe": actionPsubscribe, + "pSubScRIbE": actionPsubscribe, + "pSubScRIbe": actionPsubscribe, + "pSubScRiBE": actionPsubscribe, + "pSubScRiBe": actionPsubscribe, + "pSubScRibE": actionPsubscribe, + "pSubScRibe": actionPsubscribe, + "pSubScrIBE": actionPsubscribe, + "pSubScrIBe": actionPsubscribe, + "pSubScrIbE": actionPsubscribe, + "pSubScrIbe": actionPsubscribe, + "pSubScriBE": actionPsubscribe, + "pSubScriBe": actionPsubscribe, + "pSubScribE": actionPsubscribe, + "pSubScribe": actionPsubscribe, + "pSubsCRIBE": actionPsubscribe, + "pSubsCRIBe": actionPsubscribe, + "pSubsCRIbE": actionPsubscribe, + "pSubsCRIbe": actionPsubscribe, + "pSubsCRiBE": actionPsubscribe, + "pSubsCRiBe": actionPsubscribe, + "pSubsCRibE": actionPsubscribe, + "pSubsCRibe": actionPsubscribe, + "pSubsCrIBE": actionPsubscribe, + "pSubsCrIBe": actionPsubscribe, + "pSubsCrIbE": actionPsubscribe, + "pSubsCrIbe": actionPsubscribe, + "pSubsCriBE": actionPsubscribe, + "pSubsCriBe": actionPsubscribe, + "pSubsCribE": actionPsubscribe, + "pSubsCribe": actionPsubscribe, + "pSubscRIBE": actionPsubscribe, + "pSubscRIBe": actionPsubscribe, + "pSubscRIbE": actionPsubscribe, + "pSubscRIbe": actionPsubscribe, + "pSubscRiBE": actionPsubscribe, + "pSubscRiBe": actionPsubscribe, + "pSubscRibE": actionPsubscribe, + "pSubscRibe": actionPsubscribe, + "pSubscrIBE": actionPsubscribe, + "pSubscrIBe": actionPsubscribe, + "pSubscrIbE": actionPsubscribe, + "pSubscrIbe": actionPsubscribe, + "pSubscriBE": actionPsubscribe, + "pSubscriBe": actionPsubscribe, + "pSubscribE": actionPsubscribe, + "pSubscribe": actionPsubscribe, + "psUBSCRIBE": actionPsubscribe, + "psUBSCRIBe": actionPsubscribe, + "psUBSCRIbE": actionPsubscribe, + "psUBSCRIbe": actionPsubscribe, + "psUBSCRiBE": actionPsubscribe, + "psUBSCRiBe": actionPsubscribe, + "psUBSCRibE": actionPsubscribe, + "psUBSCRibe": actionPsubscribe, + "psUBSCrIBE": actionPsubscribe, + "psUBSCrIBe": actionPsubscribe, + "psUBSCrIbE": actionPsubscribe, + "psUBSCrIbe": actionPsubscribe, + "psUBSCriBE": actionPsubscribe, + "psUBSCriBe": actionPsubscribe, + "psUBSCribE": actionPsubscribe, + "psUBSCribe": actionPsubscribe, + "psUBScRIBE": actionPsubscribe, + "psUBScRIBe": actionPsubscribe, + "psUBScRIbE": actionPsubscribe, + "psUBScRIbe": actionPsubscribe, + "psUBScRiBE": actionPsubscribe, + "psUBScRiBe": actionPsubscribe, + "psUBScRibE": actionPsubscribe, + "psUBScRibe": actionPsubscribe, + "psUBScrIBE": actionPsubscribe, + "psUBScrIBe": actionPsubscribe, + "psUBScrIbE": actionPsubscribe, + "psUBScrIbe": actionPsubscribe, + "psUBScriBE": actionPsubscribe, + "psUBScriBe": actionPsubscribe, + "psUBScribE": actionPsubscribe, + "psUBScribe": actionPsubscribe, + "psUBsCRIBE": actionPsubscribe, + "psUBsCRIBe": actionPsubscribe, + "psUBsCRIbE": actionPsubscribe, + "psUBsCRIbe": actionPsubscribe, + "psUBsCRiBE": actionPsubscribe, + "psUBsCRiBe": actionPsubscribe, + "psUBsCRibE": actionPsubscribe, + "psUBsCRibe": actionPsubscribe, + "psUBsCrIBE": actionPsubscribe, + "psUBsCrIBe": actionPsubscribe, + "psUBsCrIbE": actionPsubscribe, + "psUBsCrIbe": actionPsubscribe, + "psUBsCriBE": actionPsubscribe, + "psUBsCriBe": actionPsubscribe, + "psUBsCribE": actionPsubscribe, + "psUBsCribe": actionPsubscribe, + "psUBscRIBE": actionPsubscribe, + "psUBscRIBe": actionPsubscribe, + "psUBscRIbE": actionPsubscribe, + "psUBscRIbe": actionPsubscribe, + "psUBscRiBE": actionPsubscribe, + "psUBscRiBe": actionPsubscribe, + "psUBscRibE": actionPsubscribe, + "psUBscRibe": actionPsubscribe, + "psUBscrIBE": actionPsubscribe, + "psUBscrIBe": actionPsubscribe, + "psUBscrIbE": actionPsubscribe, + "psUBscrIbe": actionPsubscribe, + "psUBscriBE": actionPsubscribe, + "psUBscriBe": actionPsubscribe, + "psUBscribE": actionPsubscribe, + "psUBscribe": actionPsubscribe, + "psUbSCRIBE": actionPsubscribe, + "psUbSCRIBe": actionPsubscribe, + "psUbSCRIbE": actionPsubscribe, + "psUbSCRIbe": actionPsubscribe, + "psUbSCRiBE": actionPsubscribe, + "psUbSCRiBe": actionPsubscribe, + "psUbSCRibE": actionPsubscribe, + "psUbSCRibe": actionPsubscribe, + "psUbSCrIBE": actionPsubscribe, + "psUbSCrIBe": actionPsubscribe, + "psUbSCrIbE": actionPsubscribe, + "psUbSCrIbe": actionPsubscribe, + "psUbSCriBE": actionPsubscribe, + "psUbSCriBe": actionPsubscribe, + "psUbSCribE": actionPsubscribe, + "psUbSCribe": actionPsubscribe, + "psUbScRIBE": actionPsubscribe, + "psUbScRIBe": actionPsubscribe, + "psUbScRIbE": actionPsubscribe, + "psUbScRIbe": actionPsubscribe, + "psUbScRiBE": actionPsubscribe, + "psUbScRiBe": actionPsubscribe, + "psUbScRibE": actionPsubscribe, + "psUbScRibe": actionPsubscribe, + "psUbScrIBE": actionPsubscribe, + "psUbScrIBe": actionPsubscribe, + "psUbScrIbE": actionPsubscribe, + "psUbScrIbe": actionPsubscribe, + "psUbScriBE": actionPsubscribe, + "psUbScriBe": actionPsubscribe, + "psUbScribE": actionPsubscribe, + "psUbScribe": actionPsubscribe, + "psUbsCRIBE": actionPsubscribe, + "psUbsCRIBe": actionPsubscribe, + "psUbsCRIbE": actionPsubscribe, + "psUbsCRIbe": actionPsubscribe, + "psUbsCRiBE": actionPsubscribe, + "psUbsCRiBe": actionPsubscribe, + "psUbsCRibE": actionPsubscribe, + "psUbsCRibe": actionPsubscribe, + "psUbsCrIBE": actionPsubscribe, + "psUbsCrIBe": actionPsubscribe, + "psUbsCrIbE": actionPsubscribe, + "psUbsCrIbe": actionPsubscribe, + "psUbsCriBE": actionPsubscribe, + "psUbsCriBe": actionPsubscribe, + "psUbsCribE": actionPsubscribe, + "psUbsCribe": actionPsubscribe, + "psUbscRIBE": actionPsubscribe, + "psUbscRIBe": actionPsubscribe, + "psUbscRIbE": actionPsubscribe, + "psUbscRIbe": actionPsubscribe, + "psUbscRiBE": actionPsubscribe, + "psUbscRiBe": actionPsubscribe, + "psUbscRibE": actionPsubscribe, + "psUbscRibe": actionPsubscribe, + "psUbscrIBE": actionPsubscribe, + "psUbscrIBe": actionPsubscribe, + "psUbscrIbE": actionPsubscribe, + "psUbscrIbe": actionPsubscribe, + "psUbscriBE": actionPsubscribe, + "psUbscriBe": actionPsubscribe, + "psUbscribE": actionPsubscribe, + "psUbscribe": actionPsubscribe, + "psuBSCRIBE": actionPsubscribe, + "psuBSCRIBe": actionPsubscribe, + "psuBSCRIbE": actionPsubscribe, + "psuBSCRIbe": actionPsubscribe, + "psuBSCRiBE": actionPsubscribe, + "psuBSCRiBe": actionPsubscribe, + "psuBSCRibE": actionPsubscribe, + "psuBSCRibe": actionPsubscribe, + "psuBSCrIBE": actionPsubscribe, + "psuBSCrIBe": actionPsubscribe, + "psuBSCrIbE": actionPsubscribe, + "psuBSCrIbe": actionPsubscribe, + "psuBSCriBE": actionPsubscribe, + "psuBSCriBe": actionPsubscribe, + "psuBSCribE": actionPsubscribe, + "psuBSCribe": actionPsubscribe, + "psuBScRIBE": actionPsubscribe, + "psuBScRIBe": actionPsubscribe, + "psuBScRIbE": actionPsubscribe, + "psuBScRIbe": actionPsubscribe, + "psuBScRiBE": actionPsubscribe, + "psuBScRiBe": actionPsubscribe, + "psuBScRibE": actionPsubscribe, + "psuBScRibe": actionPsubscribe, + "psuBScrIBE": actionPsubscribe, + "psuBScrIBe": actionPsubscribe, + "psuBScrIbE": actionPsubscribe, + "psuBScrIbe": actionPsubscribe, + "psuBScriBE": actionPsubscribe, + "psuBScriBe": actionPsubscribe, + "psuBScribE": actionPsubscribe, + "psuBScribe": actionPsubscribe, + "psuBsCRIBE": actionPsubscribe, + "psuBsCRIBe": actionPsubscribe, + "psuBsCRIbE": actionPsubscribe, + "psuBsCRIbe": actionPsubscribe, + "psuBsCRiBE": actionPsubscribe, + "psuBsCRiBe": actionPsubscribe, + "psuBsCRibE": actionPsubscribe, + "psuBsCRibe": actionPsubscribe, + "psuBsCrIBE": actionPsubscribe, + "psuBsCrIBe": actionPsubscribe, + "psuBsCrIbE": actionPsubscribe, + "psuBsCrIbe": actionPsubscribe, + "psuBsCriBE": actionPsubscribe, + "psuBsCriBe": actionPsubscribe, + "psuBsCribE": actionPsubscribe, + "psuBsCribe": actionPsubscribe, + "psuBscRIBE": actionPsubscribe, + "psuBscRIBe": actionPsubscribe, + "psuBscRIbE": actionPsubscribe, + "psuBscRIbe": actionPsubscribe, + "psuBscRiBE": actionPsubscribe, + "psuBscRiBe": actionPsubscribe, + "psuBscRibE": actionPsubscribe, + "psuBscRibe": actionPsubscribe, + "psuBscrIBE": actionPsubscribe, + "psuBscrIBe": actionPsubscribe, + "psuBscrIbE": actionPsubscribe, + "psuBscrIbe": actionPsubscribe, + "psuBscriBE": actionPsubscribe, + "psuBscriBe": actionPsubscribe, + "psuBscribE": actionPsubscribe, + "psuBscribe": actionPsubscribe, + "psubSCRIBE": actionPsubscribe, + "psubSCRIBe": actionPsubscribe, + "psubSCRIbE": actionPsubscribe, + "psubSCRIbe": actionPsubscribe, + "psubSCRiBE": actionPsubscribe, + "psubSCRiBe": actionPsubscribe, + "psubSCRibE": actionPsubscribe, + "psubSCRibe": actionPsubscribe, + "psubSCrIBE": actionPsubscribe, + "psubSCrIBe": actionPsubscribe, + "psubSCrIbE": actionPsubscribe, + "psubSCrIbe": actionPsubscribe, + "psubSCriBE": actionPsubscribe, + "psubSCriBe": actionPsubscribe, + "psubSCribE": actionPsubscribe, + "psubSCribe": actionPsubscribe, + "psubScRIBE": actionPsubscribe, + "psubScRIBe": actionPsubscribe, + "psubScRIbE": actionPsubscribe, + "psubScRIbe": actionPsubscribe, + "psubScRiBE": actionPsubscribe, + "psubScRiBe": actionPsubscribe, + "psubScRibE": actionPsubscribe, + "psubScRibe": actionPsubscribe, + "psubScrIBE": actionPsubscribe, + "psubScrIBe": actionPsubscribe, + "psubScrIbE": actionPsubscribe, + "psubScrIbe": actionPsubscribe, + "psubScriBE": actionPsubscribe, + "psubScriBe": actionPsubscribe, + "psubScribE": actionPsubscribe, + "psubScribe": actionPsubscribe, + "psubsCRIBE": actionPsubscribe, + "psubsCRIBe": actionPsubscribe, + "psubsCRIbE": actionPsubscribe, + "psubsCRIbe": actionPsubscribe, + "psubsCRiBE": actionPsubscribe, + "psubsCRiBe": actionPsubscribe, + "psubsCRibE": actionPsubscribe, + "psubsCRibe": actionPsubscribe, + "psubsCrIBE": actionPsubscribe, + "psubsCrIBe": actionPsubscribe, + "psubsCrIbE": actionPsubscribe, + "psubsCrIbe": actionPsubscribe, + "psubsCriBE": actionPsubscribe, + "psubsCriBe": actionPsubscribe, + "psubsCribE": actionPsubscribe, + "psubsCribe": actionPsubscribe, + "psubscRIBE": actionPsubscribe, + "psubscRIBe": actionPsubscribe, + "psubscRIbE": actionPsubscribe, + "psubscRIbe": actionPsubscribe, + "psubscRiBE": actionPsubscribe, + "psubscRiBe": actionPsubscribe, + "psubscRibE": actionPsubscribe, + "psubscRibe": actionPsubscribe, + "psubscrIBE": actionPsubscribe, + "psubscrIBe": actionPsubscribe, + "psubscrIbE": actionPsubscribe, + "psubscrIbe": actionPsubscribe, + "psubscriBE": actionPsubscribe, + "psubscriBe": actionPsubscribe, + "psubscribE": actionPsubscribe, + "psubscribe": actionPsubscribe, + "SUBSCRIBE": actionSubscribe, + "SUBSCRIBe": actionSubscribe, + "SUBSCRIbE": actionSubscribe, + "SUBSCRIbe": actionSubscribe, + "SUBSCRiBE": actionSubscribe, + "SUBSCRiBe": actionSubscribe, + "SUBSCRibE": actionSubscribe, + "SUBSCRibe": actionSubscribe, + "SUBSCrIBE": actionSubscribe, + "SUBSCrIBe": actionSubscribe, + "SUBSCrIbE": actionSubscribe, + "SUBSCrIbe": actionSubscribe, + "SUBSCriBE": actionSubscribe, + "SUBSCriBe": actionSubscribe, + "SUBSCribE": actionSubscribe, + "SUBSCribe": actionSubscribe, + "SUBScRIBE": actionSubscribe, + "SUBScRIBe": actionSubscribe, + "SUBScRIbE": actionSubscribe, + "SUBScRIbe": actionSubscribe, + "SUBScRiBE": actionSubscribe, + "SUBScRiBe": actionSubscribe, + "SUBScRibE": actionSubscribe, + "SUBScRibe": actionSubscribe, + "SUBScrIBE": actionSubscribe, + "SUBScrIBe": actionSubscribe, + "SUBScrIbE": actionSubscribe, + "SUBScrIbe": actionSubscribe, + "SUBScriBE": actionSubscribe, + "SUBScriBe": actionSubscribe, + "SUBScribE": actionSubscribe, + "SUBScribe": actionSubscribe, + "SUBsCRIBE": actionSubscribe, + "SUBsCRIBe": actionSubscribe, + "SUBsCRIbE": actionSubscribe, + "SUBsCRIbe": actionSubscribe, + "SUBsCRiBE": actionSubscribe, + "SUBsCRiBe": actionSubscribe, + "SUBsCRibE": actionSubscribe, + "SUBsCRibe": actionSubscribe, + "SUBsCrIBE": actionSubscribe, + "SUBsCrIBe": actionSubscribe, + "SUBsCrIbE": actionSubscribe, + "SUBsCrIbe": actionSubscribe, + "SUBsCriBE": actionSubscribe, + "SUBsCriBe": actionSubscribe, + "SUBsCribE": actionSubscribe, + "SUBsCribe": actionSubscribe, + "SUBscRIBE": actionSubscribe, + "SUBscRIBe": actionSubscribe, + "SUBscRIbE": actionSubscribe, + "SUBscRIbe": actionSubscribe, + "SUBscRiBE": actionSubscribe, + "SUBscRiBe": actionSubscribe, + "SUBscRibE": actionSubscribe, + "SUBscRibe": actionSubscribe, + "SUBscrIBE": actionSubscribe, + "SUBscrIBe": actionSubscribe, + "SUBscrIbE": actionSubscribe, + "SUBscrIbe": actionSubscribe, + "SUBscriBE": actionSubscribe, + "SUBscriBe": actionSubscribe, + "SUBscribE": actionSubscribe, + "SUBscribe": actionSubscribe, + "SUbSCRIBE": actionSubscribe, + "SUbSCRIBe": actionSubscribe, + "SUbSCRIbE": actionSubscribe, + "SUbSCRIbe": actionSubscribe, + "SUbSCRiBE": actionSubscribe, + "SUbSCRiBe": actionSubscribe, + "SUbSCRibE": actionSubscribe, + "SUbSCRibe": actionSubscribe, + "SUbSCrIBE": actionSubscribe, + "SUbSCrIBe": actionSubscribe, + "SUbSCrIbE": actionSubscribe, + "SUbSCrIbe": actionSubscribe, + "SUbSCriBE": actionSubscribe, + "SUbSCriBe": actionSubscribe, + "SUbSCribE": actionSubscribe, + "SUbSCribe": actionSubscribe, + "SUbScRIBE": actionSubscribe, + "SUbScRIBe": actionSubscribe, + "SUbScRIbE": actionSubscribe, + "SUbScRIbe": actionSubscribe, + "SUbScRiBE": actionSubscribe, + "SUbScRiBe": actionSubscribe, + "SUbScRibE": actionSubscribe, + "SUbScRibe": actionSubscribe, + "SUbScrIBE": actionSubscribe, + "SUbScrIBe": actionSubscribe, + "SUbScrIbE": actionSubscribe, + "SUbScrIbe": actionSubscribe, + "SUbScriBE": actionSubscribe, + "SUbScriBe": actionSubscribe, + "SUbScribE": actionSubscribe, + "SUbScribe": actionSubscribe, + "SUbsCRIBE": actionSubscribe, + "SUbsCRIBe": actionSubscribe, + "SUbsCRIbE": actionSubscribe, + "SUbsCRIbe": actionSubscribe, + "SUbsCRiBE": actionSubscribe, + "SUbsCRiBe": actionSubscribe, + "SUbsCRibE": actionSubscribe, + "SUbsCRibe": actionSubscribe, + "SUbsCrIBE": actionSubscribe, + "SUbsCrIBe": actionSubscribe, + "SUbsCrIbE": actionSubscribe, + "SUbsCrIbe": actionSubscribe, + "SUbsCriBE": actionSubscribe, + "SUbsCriBe": actionSubscribe, + "SUbsCribE": actionSubscribe, + "SUbsCribe": actionSubscribe, + "SUbscRIBE": actionSubscribe, + "SUbscRIBe": actionSubscribe, + "SUbscRIbE": actionSubscribe, + "SUbscRIbe": actionSubscribe, + "SUbscRiBE": actionSubscribe, + "SUbscRiBe": actionSubscribe, + "SUbscRibE": actionSubscribe, + "SUbscRibe": actionSubscribe, + "SUbscrIBE": actionSubscribe, + "SUbscrIBe": actionSubscribe, + "SUbscrIbE": actionSubscribe, + "SUbscrIbe": actionSubscribe, + "SUbscriBE": actionSubscribe, + "SUbscriBe": actionSubscribe, + "SUbscribE": actionSubscribe, + "SUbscribe": actionSubscribe, + "SuBSCRIBE": actionSubscribe, + "SuBSCRIBe": actionSubscribe, + "SuBSCRIbE": actionSubscribe, + "SuBSCRIbe": actionSubscribe, + "SuBSCRiBE": actionSubscribe, + "SuBSCRiBe": actionSubscribe, + "SuBSCRibE": actionSubscribe, + "SuBSCRibe": actionSubscribe, + "SuBSCrIBE": actionSubscribe, + "SuBSCrIBe": actionSubscribe, + "SuBSCrIbE": actionSubscribe, + "SuBSCrIbe": actionSubscribe, + "SuBSCriBE": actionSubscribe, + "SuBSCriBe": actionSubscribe, + "SuBSCribE": actionSubscribe, + "SuBSCribe": actionSubscribe, + "SuBScRIBE": actionSubscribe, + "SuBScRIBe": actionSubscribe, + "SuBScRIbE": actionSubscribe, + "SuBScRIbe": actionSubscribe, + "SuBScRiBE": actionSubscribe, + "SuBScRiBe": actionSubscribe, + "SuBScRibE": actionSubscribe, + "SuBScRibe": actionSubscribe, + "SuBScrIBE": actionSubscribe, + "SuBScrIBe": actionSubscribe, + "SuBScrIbE": actionSubscribe, + "SuBScrIbe": actionSubscribe, + "SuBScriBE": actionSubscribe, + "SuBScriBe": actionSubscribe, + "SuBScribE": actionSubscribe, + "SuBScribe": actionSubscribe, + "SuBsCRIBE": actionSubscribe, + "SuBsCRIBe": actionSubscribe, + "SuBsCRIbE": actionSubscribe, + "SuBsCRIbe": actionSubscribe, + "SuBsCRiBE": actionSubscribe, + "SuBsCRiBe": actionSubscribe, + "SuBsCRibE": actionSubscribe, + "SuBsCRibe": actionSubscribe, + "SuBsCrIBE": actionSubscribe, + "SuBsCrIBe": actionSubscribe, + "SuBsCrIbE": actionSubscribe, + "SuBsCrIbe": actionSubscribe, + "SuBsCriBE": actionSubscribe, + "SuBsCriBe": actionSubscribe, + "SuBsCribE": actionSubscribe, + "SuBsCribe": actionSubscribe, + "SuBscRIBE": actionSubscribe, + "SuBscRIBe": actionSubscribe, + "SuBscRIbE": actionSubscribe, + "SuBscRIbe": actionSubscribe, + "SuBscRiBE": actionSubscribe, + "SuBscRiBe": actionSubscribe, + "SuBscRibE": actionSubscribe, + "SuBscRibe": actionSubscribe, + "SuBscrIBE": actionSubscribe, + "SuBscrIBe": actionSubscribe, + "SuBscrIbE": actionSubscribe, + "SuBscrIbe": actionSubscribe, + "SuBscriBE": actionSubscribe, + "SuBscriBe": actionSubscribe, + "SuBscribE": actionSubscribe, + "SuBscribe": actionSubscribe, + "SubSCRIBE": actionSubscribe, + "SubSCRIBe": actionSubscribe, + "SubSCRIbE": actionSubscribe, + "SubSCRIbe": actionSubscribe, + "SubSCRiBE": actionSubscribe, + "SubSCRiBe": actionSubscribe, + "SubSCRibE": actionSubscribe, + "SubSCRibe": actionSubscribe, + "SubSCrIBE": actionSubscribe, + "SubSCrIBe": actionSubscribe, + "SubSCrIbE": actionSubscribe, + "SubSCrIbe": actionSubscribe, + "SubSCriBE": actionSubscribe, + "SubSCriBe": actionSubscribe, + "SubSCribE": actionSubscribe, + "SubSCribe": actionSubscribe, + "SubScRIBE": actionSubscribe, + "SubScRIBe": actionSubscribe, + "SubScRIbE": actionSubscribe, + "SubScRIbe": actionSubscribe, + "SubScRiBE": actionSubscribe, + "SubScRiBe": actionSubscribe, + "SubScRibE": actionSubscribe, + "SubScRibe": actionSubscribe, + "SubScrIBE": actionSubscribe, + "SubScrIBe": actionSubscribe, + "SubScrIbE": actionSubscribe, + "SubScrIbe": actionSubscribe, + "SubScriBE": actionSubscribe, + "SubScriBe": actionSubscribe, + "SubScribE": actionSubscribe, + "SubScribe": actionSubscribe, + "SubsCRIBE": actionSubscribe, + "SubsCRIBe": actionSubscribe, + "SubsCRIbE": actionSubscribe, + "SubsCRIbe": actionSubscribe, + "SubsCRiBE": actionSubscribe, + "SubsCRiBe": actionSubscribe, + "SubsCRibE": actionSubscribe, + "SubsCRibe": actionSubscribe, + "SubsCrIBE": actionSubscribe, + "SubsCrIBe": actionSubscribe, + "SubsCrIbE": actionSubscribe, + "SubsCrIbe": actionSubscribe, + "SubsCriBE": actionSubscribe, + "SubsCriBe": actionSubscribe, + "SubsCribE": actionSubscribe, + "SubsCribe": actionSubscribe, + "SubscRIBE": actionSubscribe, + "SubscRIBe": actionSubscribe, + "SubscRIbE": actionSubscribe, + "SubscRIbe": actionSubscribe, + "SubscRiBE": actionSubscribe, + "SubscRiBe": actionSubscribe, + "SubscRibE": actionSubscribe, + "SubscRibe": actionSubscribe, + "SubscrIBE": actionSubscribe, + "SubscrIBe": actionSubscribe, + "SubscrIbE": actionSubscribe, + "SubscrIbe": actionSubscribe, + "SubscriBE": actionSubscribe, + "SubscriBe": actionSubscribe, + "SubscribE": actionSubscribe, + "Subscribe": actionSubscribe, + "sUBSCRIBE": actionSubscribe, + "sUBSCRIBe": actionSubscribe, + "sUBSCRIbE": actionSubscribe, + "sUBSCRIbe": actionSubscribe, + "sUBSCRiBE": actionSubscribe, + "sUBSCRiBe": actionSubscribe, + "sUBSCRibE": actionSubscribe, + "sUBSCRibe": actionSubscribe, + "sUBSCrIBE": actionSubscribe, + "sUBSCrIBe": actionSubscribe, + "sUBSCrIbE": actionSubscribe, + "sUBSCrIbe": actionSubscribe, + "sUBSCriBE": actionSubscribe, + "sUBSCriBe": actionSubscribe, + "sUBSCribE": actionSubscribe, + "sUBSCribe": actionSubscribe, + "sUBScRIBE": actionSubscribe, + "sUBScRIBe": actionSubscribe, + "sUBScRIbE": actionSubscribe, + "sUBScRIbe": actionSubscribe, + "sUBScRiBE": actionSubscribe, + "sUBScRiBe": actionSubscribe, + "sUBScRibE": actionSubscribe, + "sUBScRibe": actionSubscribe, + "sUBScrIBE": actionSubscribe, + "sUBScrIBe": actionSubscribe, + "sUBScrIbE": actionSubscribe, + "sUBScrIbe": actionSubscribe, + "sUBScriBE": actionSubscribe, + "sUBScriBe": actionSubscribe, + "sUBScribE": actionSubscribe, + "sUBScribe": actionSubscribe, + "sUBsCRIBE": actionSubscribe, + "sUBsCRIBe": actionSubscribe, + "sUBsCRIbE": actionSubscribe, + "sUBsCRIbe": actionSubscribe, + "sUBsCRiBE": actionSubscribe, + "sUBsCRiBe": actionSubscribe, + "sUBsCRibE": actionSubscribe, + "sUBsCRibe": actionSubscribe, + "sUBsCrIBE": actionSubscribe, + "sUBsCrIBe": actionSubscribe, + "sUBsCrIbE": actionSubscribe, + "sUBsCrIbe": actionSubscribe, + "sUBsCriBE": actionSubscribe, + "sUBsCriBe": actionSubscribe, + "sUBsCribE": actionSubscribe, + "sUBsCribe": actionSubscribe, + "sUBscRIBE": actionSubscribe, + "sUBscRIBe": actionSubscribe, + "sUBscRIbE": actionSubscribe, + "sUBscRIbe": actionSubscribe, + "sUBscRiBE": actionSubscribe, + "sUBscRiBe": actionSubscribe, + "sUBscRibE": actionSubscribe, + "sUBscRibe": actionSubscribe, + "sUBscrIBE": actionSubscribe, + "sUBscrIBe": actionSubscribe, + "sUBscrIbE": actionSubscribe, + "sUBscrIbe": actionSubscribe, + "sUBscriBE": actionSubscribe, + "sUBscriBe": actionSubscribe, + "sUBscribE": actionSubscribe, + "sUBscribe": actionSubscribe, + "sUbSCRIBE": actionSubscribe, + "sUbSCRIBe": actionSubscribe, + "sUbSCRIbE": actionSubscribe, + "sUbSCRIbe": actionSubscribe, + "sUbSCRiBE": actionSubscribe, + "sUbSCRiBe": actionSubscribe, + "sUbSCRibE": actionSubscribe, + "sUbSCRibe": actionSubscribe, + "sUbSCrIBE": actionSubscribe, + "sUbSCrIBe": actionSubscribe, + "sUbSCrIbE": actionSubscribe, + "sUbSCrIbe": actionSubscribe, + "sUbSCriBE": actionSubscribe, + "sUbSCriBe": actionSubscribe, + "sUbSCribE": actionSubscribe, + "sUbSCribe": actionSubscribe, + "sUbScRIBE": actionSubscribe, + "sUbScRIBe": actionSubscribe, + "sUbScRIbE": actionSubscribe, + "sUbScRIbe": actionSubscribe, + "sUbScRiBE": actionSubscribe, + "sUbScRiBe": actionSubscribe, + "sUbScRibE": actionSubscribe, + "sUbScRibe": actionSubscribe, + "sUbScrIBE": actionSubscribe, + "sUbScrIBe": actionSubscribe, + "sUbScrIbE": actionSubscribe, + "sUbScrIbe": actionSubscribe, + "sUbScriBE": actionSubscribe, + "sUbScriBe": actionSubscribe, + "sUbScribE": actionSubscribe, + "sUbScribe": actionSubscribe, + "sUbsCRIBE": actionSubscribe, + "sUbsCRIBe": actionSubscribe, + "sUbsCRIbE": actionSubscribe, + "sUbsCRIbe": actionSubscribe, + "sUbsCRiBE": actionSubscribe, + "sUbsCRiBe": actionSubscribe, + "sUbsCRibE": actionSubscribe, + "sUbsCRibe": actionSubscribe, + "sUbsCrIBE": actionSubscribe, + "sUbsCrIBe": actionSubscribe, + "sUbsCrIbE": actionSubscribe, + "sUbsCrIbe": actionSubscribe, + "sUbsCriBE": actionSubscribe, + "sUbsCriBe": actionSubscribe, + "sUbsCribE": actionSubscribe, + "sUbsCribe": actionSubscribe, + "sUbscRIBE": actionSubscribe, + "sUbscRIBe": actionSubscribe, + "sUbscRIbE": actionSubscribe, + "sUbscRIbe": actionSubscribe, + "sUbscRiBE": actionSubscribe, + "sUbscRiBe": actionSubscribe, + "sUbscRibE": actionSubscribe, + "sUbscRibe": actionSubscribe, + "sUbscrIBE": actionSubscribe, + "sUbscrIBe": actionSubscribe, + "sUbscrIbE": actionSubscribe, + "sUbscrIbe": actionSubscribe, + "sUbscriBE": actionSubscribe, + "sUbscriBe": actionSubscribe, + "sUbscribE": actionSubscribe, + "sUbscribe": actionSubscribe, + "suBSCRIBE": actionSubscribe, + "suBSCRIBe": actionSubscribe, + "suBSCRIbE": actionSubscribe, + "suBSCRIbe": actionSubscribe, + "suBSCRiBE": actionSubscribe, + "suBSCRiBe": actionSubscribe, + "suBSCRibE": actionSubscribe, + "suBSCRibe": actionSubscribe, + "suBSCrIBE": actionSubscribe, + "suBSCrIBe": actionSubscribe, + "suBSCrIbE": actionSubscribe, + "suBSCrIbe": actionSubscribe, + "suBSCriBE": actionSubscribe, + "suBSCriBe": actionSubscribe, + "suBSCribE": actionSubscribe, + "suBSCribe": actionSubscribe, + "suBScRIBE": actionSubscribe, + "suBScRIBe": actionSubscribe, + "suBScRIbE": actionSubscribe, + "suBScRIbe": actionSubscribe, + "suBScRiBE": actionSubscribe, + "suBScRiBe": actionSubscribe, + "suBScRibE": actionSubscribe, + "suBScRibe": actionSubscribe, + "suBScrIBE": actionSubscribe, + "suBScrIBe": actionSubscribe, + "suBScrIbE": actionSubscribe, + "suBScrIbe": actionSubscribe, + "suBScriBE": actionSubscribe, + "suBScriBe": actionSubscribe, + "suBScribE": actionSubscribe, + "suBScribe": actionSubscribe, + "suBsCRIBE": actionSubscribe, + "suBsCRIBe": actionSubscribe, + "suBsCRIbE": actionSubscribe, + "suBsCRIbe": actionSubscribe, + "suBsCRiBE": actionSubscribe, + "suBsCRiBe": actionSubscribe, + "suBsCRibE": actionSubscribe, + "suBsCRibe": actionSubscribe, + "suBsCrIBE": actionSubscribe, + "suBsCrIBe": actionSubscribe, + "suBsCrIbE": actionSubscribe, + "suBsCrIbe": actionSubscribe, + "suBsCriBE": actionSubscribe, + "suBsCriBe": actionSubscribe, + "suBsCribE": actionSubscribe, + "suBsCribe": actionSubscribe, + "suBscRIBE": actionSubscribe, + "suBscRIBe": actionSubscribe, + "suBscRIbE": actionSubscribe, + "suBscRIbe": actionSubscribe, + "suBscRiBE": actionSubscribe, + "suBscRiBe": actionSubscribe, + "suBscRibE": actionSubscribe, + "suBscRibe": actionSubscribe, + "suBscrIBE": actionSubscribe, + "suBscrIBe": actionSubscribe, + "suBscrIbE": actionSubscribe, + "suBscrIbe": actionSubscribe, + "suBscriBE": actionSubscribe, + "suBscriBe": actionSubscribe, + "suBscribE": actionSubscribe, + "suBscribe": actionSubscribe, + "subSCRIBE": actionSubscribe, + "subSCRIBe": actionSubscribe, + "subSCRIbE": actionSubscribe, + "subSCRIbe": actionSubscribe, + "subSCRiBE": actionSubscribe, + "subSCRiBe": actionSubscribe, + "subSCRibE": actionSubscribe, + "subSCRibe": actionSubscribe, + "subSCrIBE": actionSubscribe, + "subSCrIBe": actionSubscribe, + "subSCrIbE": actionSubscribe, + "subSCrIbe": actionSubscribe, + "subSCriBE": actionSubscribe, + "subSCriBe": actionSubscribe, + "subSCribE": actionSubscribe, + "subSCribe": actionSubscribe, + "subScRIBE": actionSubscribe, + "subScRIBe": actionSubscribe, + "subScRIbE": actionSubscribe, + "subScRIbe": actionSubscribe, + "subScRiBE": actionSubscribe, + "subScRiBe": actionSubscribe, + "subScRibE": actionSubscribe, + "subScRibe": actionSubscribe, + "subScrIBE": actionSubscribe, + "subScrIBe": actionSubscribe, + "subScrIbE": actionSubscribe, + "subScrIbe": actionSubscribe, + "subScriBE": actionSubscribe, + "subScriBe": actionSubscribe, + "subScribE": actionSubscribe, + "subScribe": actionSubscribe, + "subsCRIBE": actionSubscribe, + "subsCRIBe": actionSubscribe, + "subsCRIbE": actionSubscribe, + "subsCRIbe": actionSubscribe, + "subsCRiBE": actionSubscribe, + "subsCRiBe": actionSubscribe, + "subsCRibE": actionSubscribe, + "subsCRibe": actionSubscribe, + "subsCrIBE": actionSubscribe, + "subsCrIBe": actionSubscribe, + "subsCrIbE": actionSubscribe, + "subsCrIbe": actionSubscribe, + "subsCriBE": actionSubscribe, + "subsCriBe": actionSubscribe, + "subsCribE": actionSubscribe, + "subsCribe": actionSubscribe, + "subscRIBE": actionSubscribe, + "subscRIBe": actionSubscribe, + "subscRIbE": actionSubscribe, + "subscRIbe": actionSubscribe, + "subscRiBE": actionSubscribe, + "subscRiBe": actionSubscribe, + "subscRibE": actionSubscribe, + "subscRibe": actionSubscribe, + "subscrIBE": actionSubscribe, + "subscrIBe": actionSubscribe, + "subscrIbE": actionSubscribe, + "subscrIbe": actionSubscribe, + "subscriBE": actionSubscribe, + "subscriBe": actionSubscribe, + "subscribE": actionSubscribe, + "subscribe": actionSubscribe, + "MONITOR": actionMonitor, + "MONITOr": actionMonitor, + "MONIToR": actionMonitor, + "MONITor": actionMonitor, + "MONItOR": actionMonitor, + "MONItOr": actionMonitor, + "MONItoR": actionMonitor, + "MONItor": actionMonitor, + "MONiTOR": actionMonitor, + "MONiTOr": actionMonitor, + "MONiToR": actionMonitor, + "MONiTor": actionMonitor, + "MONitOR": actionMonitor, + "MONitOr": actionMonitor, + "MONitoR": actionMonitor, + "MONitor": actionMonitor, + "MOnITOR": actionMonitor, + "MOnITOr": actionMonitor, + "MOnIToR": actionMonitor, + "MOnITor": actionMonitor, + "MOnItOR": actionMonitor, + "MOnItOr": actionMonitor, + "MOnItoR": actionMonitor, + "MOnItor": actionMonitor, + "MOniTOR": actionMonitor, + "MOniTOr": actionMonitor, + "MOniToR": actionMonitor, + "MOniTor": actionMonitor, + "MOnitOR": actionMonitor, + "MOnitOr": actionMonitor, + "MOnitoR": actionMonitor, + "MOnitor": actionMonitor, + "MoNITOR": actionMonitor, + "MoNITOr": actionMonitor, + "MoNIToR": actionMonitor, + "MoNITor": actionMonitor, + "MoNItOR": actionMonitor, + "MoNItOr": actionMonitor, + "MoNItoR": actionMonitor, + "MoNItor": actionMonitor, + "MoNiTOR": actionMonitor, + "MoNiTOr": actionMonitor, + "MoNiToR": actionMonitor, + "MoNiTor": actionMonitor, + "MoNitOR": actionMonitor, + "MoNitOr": actionMonitor, + "MoNitoR": actionMonitor, + "MoNitor": actionMonitor, + "MonITOR": actionMonitor, + "MonITOr": actionMonitor, + "MonIToR": actionMonitor, + "MonITor": actionMonitor, + "MonItOR": actionMonitor, + "MonItOr": actionMonitor, + "MonItoR": actionMonitor, + "MonItor": actionMonitor, + "MoniTOR": actionMonitor, + "MoniTOr": actionMonitor, + "MoniToR": actionMonitor, + "MoniTor": actionMonitor, + "MonitOR": actionMonitor, + "MonitOr": actionMonitor, + "MonitoR": actionMonitor, + "Monitor": actionMonitor, + "mONITOR": actionMonitor, + "mONITOr": actionMonitor, + "mONIToR": actionMonitor, + "mONITor": actionMonitor, + "mONItOR": actionMonitor, + "mONItOr": actionMonitor, + "mONItoR": actionMonitor, + "mONItor": actionMonitor, + "mONiTOR": actionMonitor, + "mONiTOr": actionMonitor, + "mONiToR": actionMonitor, + "mONiTor": actionMonitor, + "mONitOR": actionMonitor, + "mONitOr": actionMonitor, + "mONitoR": actionMonitor, + "mONitor": actionMonitor, + "mOnITOR": actionMonitor, + "mOnITOr": actionMonitor, + "mOnIToR": actionMonitor, + "mOnITor": actionMonitor, + "mOnItOR": actionMonitor, + "mOnItOr": actionMonitor, + "mOnItoR": actionMonitor, + "mOnItor": actionMonitor, + "mOniTOR": actionMonitor, + "mOniTOr": actionMonitor, + "mOniToR": actionMonitor, + "mOniTor": actionMonitor, + "mOnitOR": actionMonitor, + "mOnitOr": actionMonitor, + "mOnitoR": actionMonitor, + "mOnitor": actionMonitor, + "moNITOR": actionMonitor, + "moNITOr": actionMonitor, + "moNIToR": actionMonitor, + "moNITor": actionMonitor, + "moNItOR": actionMonitor, + "moNItOr": actionMonitor, + "moNItoR": actionMonitor, + "moNItor": actionMonitor, + "moNiTOR": actionMonitor, + "moNiTOr": actionMonitor, + "moNiToR": actionMonitor, + "moNiTor": actionMonitor, + "moNitOR": actionMonitor, + "moNitOr": actionMonitor, + "moNitoR": actionMonitor, + "moNitor": actionMonitor, + "monITOR": actionMonitor, + "monITOr": actionMonitor, + "monIToR": actionMonitor, + "monITor": actionMonitor, + "monItOR": actionMonitor, + "monItOr": actionMonitor, + "monItoR": actionMonitor, + "monItor": actionMonitor, + "moniTOR": actionMonitor, + "moniTOr": actionMonitor, + "moniToR": actionMonitor, + "moniTor": actionMonitor, + "monitOR": actionMonitor, + "monitOr": actionMonitor, + "monitoR": actionMonitor, + "monitor": actionMonitor, + "CLIENT": actionClient, + "CLIENt": actionClient, + "CLIEnT": actionClient, + "CLIEnt": actionClient, + "CLIeNT": actionClient, + "CLIeNt": actionClient, + "CLIenT": actionClient, + "CLIent": actionClient, + "CLiENT": actionClient, + "CLiENt": actionClient, + "CLiEnT": actionClient, + "CLiEnt": actionClient, + "CLieNT": actionClient, + "CLieNt": actionClient, + "CLienT": actionClient, + "CLient": actionClient, + "ClIENT": actionClient, + "ClIENt": actionClient, + "ClIEnT": actionClient, + "ClIEnt": actionClient, + "ClIeNT": actionClient, + "ClIeNt": actionClient, + "ClIenT": actionClient, + "ClIent": actionClient, + "CliENT": actionClient, + "CliENt": actionClient, + "CliEnT": actionClient, + "CliEnt": actionClient, + "ClieNT": actionClient, + "ClieNt": actionClient, + "ClienT": actionClient, + "Client": actionClient, + "cLIENT": actionClient, + "cLIENt": actionClient, + "cLIEnT": actionClient, + "cLIEnt": actionClient, + "cLIeNT": actionClient, + "cLIeNt": actionClient, + "cLIenT": actionClient, + "cLIent": actionClient, + "cLiENT": actionClient, + "cLiENt": actionClient, + "cLiEnT": actionClient, + "cLiEnt": actionClient, + "cLieNT": actionClient, + "cLieNt": actionClient, + "cLienT": actionClient, + "cLient": actionClient, + "clIENT": actionClient, + "clIENt": actionClient, + "clIEnT": actionClient, + "clIEnt": actionClient, + "clIeNT": actionClient, + "clIeNt": actionClient, + "clIenT": actionClient, + "clIent": actionClient, + "cliENT": actionClient, + "cliENt": actionClient, + "cliEnT": actionClient, + "cliEnt": actionClient, + "clieNT": actionClient, + "clieNt": actionClient, + "clienT": actionClient, + "client": actionClient, + } + connActions = map[string]*commandAction{ + "CLIENT": actionClient, + "CLIENt": actionClient, + "CLIEnT": actionClient, + "CLIEnt": actionClient, + "CLIeNT": actionClient, + "CLIeNt": actionClient, + "CLIenT": actionClient, + "CLIent": actionClient, + "CLiENT": actionClient, + "CLiENt": actionClient, + "CLiEnT": actionClient, + "CLiEnt": actionClient, + "CLieNT": actionClient, + "CLieNt": actionClient, + "CLienT": actionClient, + "CLient": actionClient, + "ClIENT": actionClient, + "ClIENt": actionClient, + "ClIEnT": actionClient, + "ClIEnt": actionClient, + "ClIeNT": actionClient, + "ClIeNt": actionClient, + "ClIenT": actionClient, + "ClIent": actionClient, + "CliENT": actionClient, + "CliENt": actionClient, + "CliEnT": actionClient, + "CliEnt": actionClient, + "ClieNT": actionClient, + "ClieNt": actionClient, + "ClienT": actionClient, + "Client": actionClient, + "cLIENT": actionClient, + "cLIENt": actionClient, + "cLIEnT": actionClient, + "cLIEnt": actionClient, + "cLIeNT": actionClient, + "cLIeNt": actionClient, + "cLIenT": actionClient, + "cLIent": actionClient, + "cLiENT": actionClient, + "cLiENt": actionClient, + "cLiEnT": actionClient, + "cLiEnt": actionClient, + "cLieNT": actionClient, + "cLieNt": actionClient, + "cLienT": actionClient, + "cLient": actionClient, + "clIENT": actionClient, + "clIENt": actionClient, + "clIEnT": actionClient, + "clIEnt": actionClient, + "clIeNT": actionClient, + "clIeNt": actionClient, + "clIenT": actionClient, + "clIent": actionClient, + "cliENT": actionClient, + "cliENt": actionClient, + "cliEnT": actionClient, + "cliEnt": actionClient, + "clieNT": actionClient, + "clieNt": actionClient, + "clienT": actionClient, + "client": actionClient, + } +) diff --git a/redis/command_action_gen.go b/redis/command_action_gen.go new file mode 100644 index 00000000..71075080 --- /dev/null +++ b/redis/command_action_gen.go @@ -0,0 +1,198 @@ +// command_action_gen generates maps and actions for command processing. +//go:build generate + +package main + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strings" + "text/template" + "unicode" +) + +// commandInfo represents a command which requires a special action +// on a connection when run. +type commandInfo struct { + Name string + Variable string + Action string + State string + Permutations []string + Next []*commandInfo +} + +// newCommandInfo create a new commandInfo. +func newCommandInfo(name, action string) *commandInfo { + return &commandInfo{ + Name: name, + Action: action, + } +} + +var activeConnCommands = &commandInfo{ + Variable: "activeConnActions", + Next: []*commandInfo{ + newCommandInfo("watch", "*state |= stateWatch"), + newCommandInfo("unwatch", "*state &^= stateWatch"), + newCommandInfo("multi", "*state |= stateMulti"), + newCommandInfo("exec", "*state &^= stateWatch|stateMulti"), + newCommandInfo("discard", "*state &^= stateWatch|stateMulti"), + newCommandInfo("psubscribe", "*state |= stateSubscribe"), + newCommandInfo("subscribe", "*state |= stateSubscribe"), + newCommandInfo("monitor", "*state |= stateMonitor"), + { + Name: "client", + Next: []*commandInfo{ + { + Name: "reply", + Next: []*commandInfo{ + newCommandInfo("off", "*state |= stateClientReplyOff"), + newCommandInfo("on", "*state &^= stateClientReplyOff|stateClientReplySkip"), + newCommandInfo("skip", `if *state&stateClientReplyOff == 0 { + *state |= stateClientReplySkipNext + }`), + }, + }, + }, + }, + }, +} + +var connCommands = &commandInfo{ + Variable: "connActions", + Next: []*commandInfo{ + { + Name: "client", + Variable: "actionClient", + }, + }, +} + +const baseTemplate = ` +{{define "base" -}} +// Code generated by commandinfo_gen. DO NOT EDIT. + +package redis + +var ( + {{- template "var" .ActiveConns}} + {{- template "var" .Conns}} +) +{{end}} + +{{define "var" -}} + {{if .Next}} + {{- range .Next -}} + {{template "var" .}} + {{- end}} + {{- if eq .Name ""}} + {{.Variable}} = map[string]*commandAction{ + {{- range .Next}} + {{- $ci := . -}} + {{range .Permutations}} + "{{.}}": {{$ci.Variable}}, + {{- end}} + {{- end}} + } + {{- else}} + {{.Variable}} = &commandAction{ + Next: map[string]*commandAction{ + {{- range .Next}} + {{- $ci := . -}} + {{range .Permutations}} + "{{.}}": {{$ci.Variable}}, + {{- end}} + {{- end}} + }, + } + {{- end -}} + {{- end -}} + {{- if .Action}} + {{.Variable}} = &commandAction{ + Action: func(state *connectionState) { + {{.Action}} + }, + } + {{- end -}} +{{end}} +` + +// permute returns all combinations of upper and lower case src. +func permute(src, dest []rune) []string { + if len(src) == 0 { + return []string{string(dest)} + } + + upper := unicode.ToUpper(src[0]) + lower := unicode.ToLower(src[0]) + src = src[1:] + if upper == lower { + return permute(src, append(dest, upper)) + } + + return append( + permute(src, append(dest, upper)), + permute(src, append(dest, lower))..., + ) +} + +// processCommands processes commands setting their variable names +// and permutations. +func processCommands(parent string, commands []*commandInfo) { + for _, ci := range commands { + prefix := parent + if ci.Variable == "" { + ci.Variable = parent + strings.Title(ci.Name) + prefix = ci.Variable + } + if ci.Next != nil { + processCommands(prefix, ci.Next) + } + ci.Permutations = permute([]rune(ci.Name), nil) + } +} + +// generate generates the details required for commands and their +// possible named permutations to optimise lookups for performance. +func generate() error { + processCommands("action", []*commandInfo{connCommands}) + processCommands("action", []*commandInfo{activeConnCommands}) + + var buf bytes.Buffer + tmpl, err := template.New("base").Parse(baseTemplate) + if err != nil { + return fmt.Errorf("parse template: %w", err) + } + + data := struct { + ActiveConns *commandInfo + Conns *commandInfo + }{ + ActiveConns: activeConnCommands, + Conns: connCommands, + } + if err = tmpl.Execute(&buf, data); err != nil { + return fmt.Errorf("execute template: %w", err) + } + + formatted, err := format.Source(buf.Bytes()) + if err != nil { + return fmt.Errorf("format code %s: %w", buf.String(), err) + } + + if err = os.WriteFile("command_action.gen.go", formatted, 0666); err != nil { + return fmt.Errorf("write code: %w", err) + } + + return nil +} + +func main() { + if err := generate(); err != nil { + log.Fatal(err) + } +} diff --git a/redis/commandinfo.go b/redis/commandinfo.go deleted file mode 100644 index b6df6a25..00000000 --- a/redis/commandinfo.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "strings" -) - -const ( - connectionWatchState = 1 << iota - connectionMultiState - connectionSubscribeState - connectionMonitorState -) - -type commandInfo struct { - // Set or Clear these states on connection. - Set, Clear int -} - -var commandInfos = map[string]commandInfo{ - "WATCH": {Set: connectionWatchState}, - "UNWATCH": {Clear: connectionWatchState}, - "MULTI": {Set: connectionMultiState}, - "EXEC": {Clear: connectionWatchState | connectionMultiState}, - "DISCARD": {Clear: connectionWatchState | connectionMultiState}, - "PSUBSCRIBE": {Set: connectionSubscribeState}, - "SUBSCRIBE": {Set: connectionSubscribeState}, - "MONITOR": {Set: connectionMonitorState}, -} - -func init() { - for n, ci := range commandInfos { - commandInfos[strings.ToLower(n)] = ci - } -} - -func lookupCommandInfo(commandName string) commandInfo { - if ci, ok := commandInfos[commandName]; ok { - return ci - } - return commandInfos[strings.ToUpper(commandName)] -} diff --git a/redis/commandinfo_test.go b/redis/commandinfo_test.go deleted file mode 100644 index 799b9292..00000000 --- a/redis/commandinfo_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package redis - -import "testing" - -func TestLookupCommandInfo(t *testing.T) { - for _, n := range []string{"watch", "WATCH", "wAtch"} { - if lookupCommandInfo(n) == (commandInfo{}) { - t.Errorf("LookupCommandInfo(%q) = CommandInfo{}, expected non-zero value", n) - } - } -} - -func benchmarkLookupCommandInfo(b *testing.B, names ...string) { - for i := 0; i < b.N; i++ { - for _, c := range names { - lookupCommandInfo(c) - } - } -} - -func BenchmarkLookupCommandInfoCorrectCase(b *testing.B) { - benchmarkLookupCommandInfo(b, "watch", "WATCH", "monitor", "MONITOR") -} - -func BenchmarkLookupCommandInfoMixedCase(b *testing.B) { - benchmarkLookupCommandInfo(b, "wAtch", "WeTCH", "monItor", "MONiTOR") -} diff --git a/redis/conn.go b/redis/conn.go index 753644b1..57380b97 100644 --- a/redis/conn.go +++ b/redis/conn.go @@ -37,10 +37,13 @@ var ( // conn is the low-level implementation of Conn type conn struct { // Shared + conn net.Conn + + // Mutex protected fields. mu sync.Mutex - pending int err error - conn net.Conn + pending int + state connectionState // Read readTimeout time.Duration @@ -679,10 +682,18 @@ func (c *conn) readReply() (interface{}, error) { return nil, protocolError("unexpected response line") } +func (c *conn) stateUpdate(cmd string, args ...interface{}) { + c.state.update(connActions, cmd, args...) +} + func (c *conn) Send(cmd string, args ...interface{}) error { c.mu.Lock() - c.pending += 1 + c.stateUpdate(cmd, args...) + if c.state&(stateClientReplyOff|stateClientReplySkipNext|stateClientReplySkip) == 0 { + c.pending += 1 + } c.mu.Unlock() + if c.writeTimeout != 0 { if err := c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil { return c.fatal(err) @@ -745,13 +756,14 @@ func (c *conn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err if timeout != 0 { deadline = time.Now().Add(timeout) } - if err := c.conn.SetReadDeadline(deadline); err != nil { + if err = c.conn.SetReadDeadline(deadline); err != nil { return nil, c.fatal(err) } if reply, err = c.readReply(); err != nil { return nil, c.fatal(err) } + // When using pub/sub, the number of receives can be greater than the // number of sends. To enable normal use of the connection after // unsubscribing from all channels, we do not decrement pending to a @@ -764,10 +776,12 @@ func (c *conn) ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err c.pending -= 1 } c.mu.Unlock() + if err, ok := reply.(Error); ok { return nil, err } - return + + return reply, nil } func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) { @@ -805,9 +819,15 @@ func (c *conn) DoContext(ctx context.Context, cmd string, args ...interface{}) ( } func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) { + var doPending int c.mu.Lock() + c.stateUpdate(cmd, args...) pending := c.pending c.pending = 0 + if cmd != "" && c.state&(stateClientReplyOff|stateClientReplySkipNext|stateClientReplySkip) == 0 { + // Do is expecting a reply. + doPending = 1 + } c.mu.Unlock() if cmd == "" && pending == 0 { @@ -839,6 +859,7 @@ func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...inte } if cmd == "" { + // Empty command indicates we want to ensure unread replies from Send are read. reply := make([]interface{}, pending) for i := range reply { r, e := c.readReply() @@ -850,16 +871,20 @@ func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...inte return reply, nil } + // Read all pending replies, from previous Send and the current Do. var err error var reply interface{} - for i := 0; i <= pending; i++ { + pending += doPending + for i := 0; i < pending; i++ { var e error if reply, e = c.readReply(); e != nil { return nil, c.fatal(e) } if e, ok := reply.(Error); ok && err == nil { + // First non-nil error is the error we will return. err = e } } + return reply, err } diff --git a/redis/conn_test.go b/redis/conn_test.go index 0c942ce2..12b8ff7f 100644 --- a/redis/conn_test.go +++ b/redis/conn_test.go @@ -23,10 +23,10 @@ import ( "io" "math" "net" - "sync" "os" "reflect" "strings" + "sync" "testing" "time" @@ -974,33 +974,55 @@ func TestExecError(t *testing.T) { } } -func BenchmarkDoEmpty(b *testing.B) { - b.StopTimer() +func BenchmarkConnDo(b *testing.B) { c, err := redis.DialDefaultServer() - if err != nil { - b.Fatal(err) - } + require.NoError(b, err) defer c.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, err := c.Do(""); err != nil { - b.Fatal(err) - } - } -} -func BenchmarkDoPing(b *testing.B) { - b.StopTimer() - c, err := redis.DialDefaultServer() - if err != nil { - b.Fatal(err) + // Setup required data. + _, err = c.Do("MSET", "foo", "bar", "bar", "baz") + require.NoError(b, err) + _, err = c.Do("HMSET", "hfoo", "bar", "baz", "qux", "quux", "thing", "bob") + require.NoError(b, err) + + tests := map[string]struct { + cmd string + args []interface{} + }{ + "set": { + cmd: "SET", + args: []interface{}{"foo", "bar"}, + }, + "get": { + cmd: "GET", + args: []interface{}{"foo"}, + }, + "mget": { + cmd: "MGET", + args: []interface{}{"foo", "bar"}, + }, + "hmset": { + cmd: "HMSET", + args: []interface{}{"hfoo", "bar", "baz", "qux", "baz1", "qux1", "stuff"}, + }, + "hgetall": { + cmd: "HGETALL", + args: []interface{}{"hfoo"}, + }, + "blank": { + cmd: "", + }, + "ping": { + cmd: "PING", + }, } - defer c.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, err := c.Do("PING"); err != nil { - b.Fatal(err) - } + for name, tc := range tests { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, err := c.Do(tc.cmd, tc.args...) + require.NoError(b, err) + } + }) } } diff --git a/redis/connection_state.go b/redis/connection_state.go new file mode 100644 index 00000000..35c45ccf --- /dev/null +++ b/redis/connection_state.go @@ -0,0 +1,71 @@ +// Copyright 2014 Gary Burd +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +package redis + +// connectionState represents a connection state. +type connectionState uint8 + +const ( + stateWatch connectionState = 1 << iota + stateMulti + stateSubscribe + stateMonitor + stateClientReplyOff + stateClientReplySkipNext + stateClientReplySkip +) + +// commandAction represents an action to be taken when processing a command. +type commandAction struct { + Action func(*connectionState) + + // Next specifies sub actions for given arguments. + Next map[string]*commandAction +} + +// update updates the connection state based on the command and arguments if needed. +func (cs *connectionState) update(info map[string]*commandAction, first string, args ...interface{}) { + *cs &^= stateClientReplySkip + if *cs&stateClientReplySkipNext != 0 { + *cs |= stateClientReplySkip + *cs &^= stateClientReplySkipNext + } + + ci, ok := info[first] + if !ok { + // No match. + return + } + + if ci.Action != nil { + // Match with no more args. + ci.Action(cs) + return + } + + if len(args) == 0 { + // No match due to lack of args. + return + } + + first, ok = args[0].(string) + if !ok { + // No match due type miss-match. + return + } + + // Check the next argument. + cs.update(ci.Next, first, args[1:]...) +} diff --git a/redis/connection_state_test.go b/redis/connection_state_test.go new file mode 100644 index 00000000..f3a60d01 --- /dev/null +++ b/redis/connection_state_test.go @@ -0,0 +1,195 @@ +package redis + +import ( + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +type lookupTest struct { + state connectionState + expected connectionState + commandName string + args []interface{} + info map[string]*commandAction +} + +func buildLookupTests(tests map[string]lookupTest, root, infos map[string]*commandAction, args ...string) { + for cmd, ci := range infos { + if cmd != strings.ToLower(cmd) { + // Skip non lower case commands as we only need to test one case per action. + continue + } + + cmdArgs := append(args, cmd) + if ci.Next != nil { + buildLookupTests(tests, root, ci.Next, cmdArgs...) + continue + } + + t := lookupTest{ + commandName: cmdArgs[0], + args: make([]interface{}, len(cmdArgs)-1), + info: root, + } + for i, arg := range cmdArgs[1:] { + t.args[i] = arg + } + var state connectionState + ci.Action(&state) + if state != 0 { + // Action is a Set. + t.expected = state + } else { + // Action is a Clear. + state = ^connectionState(0) + ci.Action(&state) + t.state = ^state + } + + tests[strings.Join(cmdArgs, "-")] = t + } +} + +func TestConnectionStateUpdate(t *testing.T) { + tests := make(map[string]lookupTest) + buildLookupTests(tests, activeConnActions, activeConnActions) + buildLookupTests(tests, connActions, connActions) + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + tc.state.update(tc.info, tc.commandName, tc.args...) + require.Equal(t, tc.expected, tc.state) + }) + } +} + +func benchmarkStateUpdate(b *testing.B, names ...string) { + var state connectionState + for i := 0; i < b.N; i++ { + for _, cmd := range names { + state.update(activeConnActions, cmd) + } + } +} + +func BenchmarkConnectionStateUpdateCorrectCase(b *testing.B) { + benchmarkStateUpdate(b, "watch", "WATCH", "monitor", "MONITOR") +} + +func BenchmarkConnectionStateUpdateMixedCase(b *testing.B) { + benchmarkStateUpdate(b, "wAtch", "WeTCH", "monItor", "MONiTOR") +} + +func BenchmarkConnectionStateUpdateNoMatch(b *testing.B) { + benchmarkStateUpdate(b, "GET", "SET", "HMGET", "HMSET") +} + +func TestClientReply(t *testing.T) { + p := &Pool{ + MaxIdle: 1, + MaxActive: 2, + Dial: func() (Conn, error) { + return DialDefaultServer() + }, + } + defer p.Close() + + closeCheck := func(t *testing.T, c Conn) { + t.Helper() + + done := make(chan error) + go func() { + done <- c.Close() + }() + + select { + case err := <-done: + require.NoError(t, err) + case <-time.After(time.Second): + t.Fatal("timeout waiting for connection close") + } + } + + var defaultState connectionState + tests := map[string]func(t *testing.T){ + "off": func(t *testing.T) { + c := p.Get() + defer closeCheck(t, c) + + err := c.Send("CLIENT", "REPLY", "OFF") + require.NoError(t, err) + require.Equal(t, stateClientReplyOff, c.(*activeConn).state) + + err = c.Send("ECHO", "first") + require.NoError(t, err) + require.Equal(t, stateClientReplyOff, c.(*activeConn).state) + + _, err = c.Do("CLIENT", "REPLY", "ON") + require.NoError(t, err) + require.Equal(t, defaultState, c.(*activeConn).state) + + reply, err := String(c.Do("ECHO", "second")) + require.NoError(t, err) + require.Equal(t, "second", reply) + }, + "off-skip": func(t *testing.T) { + c := p.Get() + defer closeCheck(t, c) + + err := c.Send("CLIENT", "REPLY", "OFF") + require.NoError(t, err) + require.Equal(t, stateClientReplyOff, c.(*activeConn).state) + + err = c.Send("ECHO", "first") + require.NoError(t, err) + require.Equal(t, stateClientReplyOff, c.(*activeConn).state) + + // Skip should be ignored as we are already in a off state. + err = c.Send("CLIENT", "REPLY", "SKIP") + require.NoError(t, err) + require.Equal(t, stateClientReplyOff, c.(*activeConn).state) + + _, err = c.Do("CLIENT", "REPLY", "ON") + require.NoError(t, err) + require.Equal(t, defaultState, c.(*activeConn).state) + + reply, err := String(c.Do("ECHO", "second")) + require.NoError(t, err) + require.Equal(t, "second", reply) + }, + "skip": func(t *testing.T) { + c := p.Get() + defer closeCheck(t, c) + + err := c.Send("CLIENT", "REPLY", "SKIP") + require.NoError(t, err) + require.Equal(t, stateClientReplySkipNext, c.(*activeConn).state) + + err = c.Send("ECHO", "first") + require.NoError(t, err) + require.Equal(t, stateClientReplySkip, c.(*activeConn).state) + + err = c.Send("ECHO", "second") + require.NoError(t, err) + require.Equal(t, defaultState, c.(*activeConn).state) + + err = c.Flush() + require.NoError(t, err) + + reply, err := String(c.Receive()) + require.NoError(t, err) + require.Equal(t, "second", reply) + + reply, err = String(c.Do("ECHO", "third")) + require.NoError(t, err) + require.Equal(t, "third", reply) + }, + } + + for name, tc := range tests { + t.Run(name, tc) + } +} diff --git a/redis/generate.go b/redis/generate.go new file mode 100644 index 00000000..9a10f2a3 --- /dev/null +++ b/redis/generate.go @@ -0,0 +1,3 @@ +package redis + +//go:generate go run command_action_gen.go diff --git a/redis/pool.go b/redis/pool.go index d7bb71e0..113ce76e 100644 --- a/redis/pool.go +++ b/redis/pool.go @@ -51,72 +51,71 @@ var ( // request handlers using a package level variable. The pool configuration used // here is an example, not a recommendation. // -// func newPool(addr string) *redis.Pool { -// return &redis.Pool{ -// MaxIdle: 3, -// IdleTimeout: 240 * time.Second, -// // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial. -// Dial: func () (redis.Conn, error) { return redis.Dial("tcp", addr) }, -// } -// } +// func newPool(addr string) *redis.Pool { +// return &redis.Pool{ +// MaxIdle: 3, +// IdleTimeout: 240 * time.Second, +// // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial. +// Dial: func () (redis.Conn, error) { return redis.Dial("tcp", addr) }, +// } +// } // -// var ( -// pool *redis.Pool -// redisServer = flag.String("redisServer", ":6379", "") -// ) +// var ( +// pool *redis.Pool +// redisServer = flag.String("redisServer", ":6379", "") +// ) // -// func main() { -// flag.Parse() -// pool = newPool(*redisServer) -// ... -// } +// func main() { +// flag.Parse() +// pool = newPool(*redisServer) +// ... +// } // // A request handler gets a connection from the pool and closes the connection // when the handler is done: // -// func serveHome(w http.ResponseWriter, r *http.Request) { -// conn := pool.Get() -// defer conn.Close() -// ... -// } +// func serveHome(w http.ResponseWriter, r *http.Request) { +// conn := pool.Get() +// defer conn.Close() +// ... +// } // // Use the Dial function to authenticate connections with the AUTH command or // select a database with the SELECT command: // -// pool := &redis.Pool{ -// // Other pool configuration not shown in this example. -// Dial: func () (redis.Conn, error) { -// c, err := redis.Dial("tcp", server) -// if err != nil { -// return nil, err -// } -// if _, err := c.Do("AUTH", password); err != nil { -// c.Close() -// return nil, err -// } -// if _, err := c.Do("SELECT", db); err != nil { -// c.Close() -// return nil, err -// } -// return c, nil -// }, -// } +// pool := &redis.Pool{ +// // Other pool configuration not shown in this example. +// Dial: func () (redis.Conn, error) { +// c, err := redis.Dial("tcp", server) +// if err != nil { +// return nil, err +// } +// if _, err := c.Do("AUTH", password); err != nil { +// c.Close() +// return nil, err +// } +// if _, err := c.Do("SELECT", db); err != nil { +// c.Close() +// return nil, err +// } +// return c, nil +// }, +// } // // Use the TestOnBorrow function to check the health of an idle connection // before the connection is returned to the application. This example PINGs // connections that have been idle more than a minute: // -// pool := &redis.Pool{ -// // Other pool configuration not shown in this example. -// TestOnBorrow: func(c redis.Conn, t time.Time) error { -// if time.Since(t) < time.Minute { -// return nil -// } -// _, err := c.Do("PING") -// return err -// }, -// } -// +// pool := &redis.Pool{ +// // Other pool configuration not shown in this example. +// TestOnBorrow: func(c redis.Conn, t time.Time) error { +// if time.Since(t) < time.Minute { +// return nil +// } +// _, err := c.Do("PING") +// return err +// }, +// } type Pool struct { // Dial is an application supplied function for creating and configuring a // connection. @@ -269,6 +268,7 @@ type PoolStats struct { // ActiveCount is the number of connections in the pool. The count includes // idle connections and connections in use. ActiveCount int + // IdleCount is the number of idle connections in the pool. IdleCount int @@ -429,7 +429,7 @@ func (p *Pool) put(pc *poolConn, forceClose bool) error { type activeConn struct { p *Pool pc *poolConn - state int + state connectionState } var ( @@ -449,6 +449,10 @@ func initSentinel() { } } +func (ac *activeConn) stateUpdate(cmd string, args ...interface{}) { + ac.state.update(activeConnActions, cmd, args...) +} + func (ac *activeConn) firstError(errs ...error) error { for _, err := range errs[:len(errs)-1] { if err != nil { @@ -465,14 +469,18 @@ func (ac *activeConn) Close() (err error) { } ac.pc = nil - if ac.state&connectionMultiState != 0 { - err = pc.c.Send("DISCARD") - ac.state &^= (connectionMultiState | connectionWatchState) - } else if ac.state&connectionWatchState != 0 { - err = pc.c.Send("UNWATCH") - ac.state &^= connectionWatchState + // Return the connection to a clean state if possible. + if ac.state&(stateClientReplyOff|stateClientReplySkip) != 0 { + err = pc.c.Send("CLIENT", "REPLY", "ON") } - if ac.state&connectionSubscribeState != 0 { + + if ac.state&stateMulti != 0 { + err = ac.firstError(err, pc.c.Send("DISCARD")) + } else if ac.state&stateWatch != 0 { + err = ac.firstError(err, pc.c.Send("UNWATCH")) + } + + if ac.state&stateSubscribe != 0 { err = ac.firstError(err, pc.c.Send("UNSUBSCRIBE"), pc.c.Send("PUNSUBSCRIBE"), @@ -491,11 +499,13 @@ func (ac *activeConn) Close() (err error) { break } if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) { - ac.state &^= connectionSubscribeState + ac.state &^= stateSubscribe break } } } + + // Ensure any pending reads have completed. _, err2 := pc.c.Do("") return ac.firstError( err, @@ -517,13 +527,13 @@ func (ac *activeConn) DoContext(ctx context.Context, commandName string, args .. if pc == nil { return nil, errConnClosed } - cwt, ok := pc.c.(ConnWithContext) + cwc, ok := pc.c.(ConnWithContext) if !ok { return nil, errContextNotSupported } - ci := lookupCommandInfo(commandName) - ac.state = (ac.state | ci.Set) &^ ci.Clear - return cwt.DoContext(ctx, commandName, args...) + ac.stateUpdate(commandName, args...) + + return cwc.DoContext(ctx, commandName, args...) } func (ac *activeConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) { @@ -531,8 +541,8 @@ func (ac *activeConn) Do(commandName string, args ...interface{}) (reply interfa if pc == nil { return nil, errConnClosed } - ci := lookupCommandInfo(commandName) - ac.state = (ac.state | ci.Set) &^ ci.Clear + ac.stateUpdate(commandName, args...) + return pc.c.Do(commandName, args...) } @@ -545,8 +555,8 @@ func (ac *activeConn) DoWithTimeout(timeout time.Duration, commandName string, a if !ok { return nil, errTimeoutNotSupported } - ci := lookupCommandInfo(commandName) - ac.state = (ac.state | ci.Set) &^ ci.Clear + ac.stateUpdate(commandName, args...) + return cwt.DoWithTimeout(timeout, commandName, args...) } @@ -555,8 +565,8 @@ func (ac *activeConn) Send(commandName string, args ...interface{}) error { if pc == nil { return errConnClosed } - ci := lookupCommandInfo(commandName) - ac.state = (ac.state | ci.Set) &^ ci.Clear + ac.stateUpdate(commandName, args...) + return pc.c.Send(commandName, args...) } diff --git a/redis/pool_test.go b/redis/pool_test.go index f420b124..b8572370 100644 --- a/redis/pool_test.go +++ b/redis/pool_test.go @@ -807,6 +807,72 @@ func BenchmarkPoolGet(b *testing.B) { } } +func BenchmarkPoolDo(b *testing.B) { + p := redis.Pool{ + MaxIdle: 2, + Dial: func() (redis.Conn, error) { + return redis.DialDefaultServer() + }, + } + + func() { + // Setup required data. + c := p.Get() + require.NoError(b, c.Err()) + defer func() { + require.NoError(b, c.Close()) + }() + + _, err = c.Do("MSET", "foo", "bar", "bar", "baz") + require.NoError(b, err) + _, err = c.Do("HMSET", "hfoo", "bar", "baz", "qux", "quux", "thing", "bob") + require.NoError(b, err) + }() + + tests := map[string]struct { + cmd string + args []interface{} + }{ + "set": { + cmd: "SET", + args: []interface{}{"foo", "bar"}, + }, + "get": { + cmd: "GET", + args: []interface{}{"foo"}, + }, + "mget": { + cmd: "MGET", + args: []interface{}{"foo", "bar"}, + }, + "hmset": { + cmd: "HMSET", + args: []interface{}{"hfoo", "bar", "baz", "qux", "baz1", "qux1", "stuff"}, + }, + "hgetall": { + cmd: "HGETALL", + args: []interface{}{"hfoo"}, + }, + "blank": { + cmd: "", + }, + "ping": { + cmd: "PING", + }, + } + for name, tc := range tests { + b.Run(name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + c := p.Get() + _, err := c.Do(tc.cmd, tc.args...) + require.NoError(b, err) + err = c.Close() + require.NoError(b, err) + } + }) + } +} + func BenchmarkPoolGetErr(b *testing.B) { b.StopTimer() p := redis.Pool{Dial: func() (redis.Conn, error) { return redis.DialDefaultServer() }, MaxIdle: 2} From f5f94cf1c2437e07fd7d0cdad446df68b058f213 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Sat, 3 Feb 2024 14:30:53 +0000 Subject: [PATCH 2/2] fix: add support for newer state impacting command Add support for newer command which impact the state of a client connection hence need special handling when returning connections to the pool. Also add missing type assertions for ConnWithContext on connection types. --- redis/command_action.gen.go | 3368 +++++++++++++++++++++++++++----- redis/command_action_gen.go | 53 +- redis/conn.go | 3 +- redis/connection_state.go | 53 +- redis/connection_state_test.go | 191 +- redis/pool.go | 154 +- redis/pool_test.go | 4 +- 7 files changed, 3276 insertions(+), 550 deletions(-) diff --git a/redis/command_action.gen.go b/redis/command_action.gen.go index 3597e95a..e3603fc0 100644 --- a/redis/command_action.gen.go +++ b/redis/command_action.gen.go @@ -3,60 +3,72 @@ package redis var ( - actionWatch = &commandAction{ - Action: func(state *connectionState) { - *state |= stateWatch - }, - } - actionUnwatch = &commandAction{ - Action: func(state *connectionState) { - *state &^= stateWatch + actionClientNoEvictOn = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateClientNoEvict }, } - actionMulti = &commandAction{ - Action: func(state *connectionState) { - *state |= stateMulti - }, - } - actionExec = &commandAction{ - Action: func(state *connectionState) { - *state &^= stateWatch | stateMulti + actionClientNoEvictOff = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateClientNoEvict }, } - actionDiscard = &commandAction{ - Action: func(state *connectionState) { - *state &^= stateWatch | stateMulti + actionClientNoEvict = &commandAction{ + Next: map[string]*commandAction{ + "ON": actionClientNoEvictOn, + "On": actionClientNoEvictOn, + "oN": actionClientNoEvictOn, + "on": actionClientNoEvictOn, + "OFF": actionClientNoEvictOff, + "OFf": actionClientNoEvictOff, + "OfF": actionClientNoEvictOff, + "Off": actionClientNoEvictOff, + "oFF": actionClientNoEvictOff, + "oFf": actionClientNoEvictOff, + "ofF": actionClientNoEvictOff, + "off": actionClientNoEvictOff, }, } - actionPsubscribe = &commandAction{ - Action: func(state *connectionState) { - *state |= stateSubscribe + actionClientNoTouchOn = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateClientNoTouch }, } - actionSubscribe = &commandAction{ - Action: func(state *connectionState) { - *state |= stateSubscribe + actionClientNoTouchOff = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateClientNoTouch }, } - actionMonitor = &commandAction{ - Action: func(state *connectionState) { - *state |= stateMonitor + actionClientNoTouch = &commandAction{ + Next: map[string]*commandAction{ + "ON": actionClientNoTouchOn, + "On": actionClientNoTouchOn, + "oN": actionClientNoTouchOn, + "on": actionClientNoTouchOn, + "OFF": actionClientNoTouchOff, + "OFf": actionClientNoTouchOff, + "OfF": actionClientNoTouchOff, + "Off": actionClientNoTouchOff, + "oFF": actionClientNoTouchOff, + "oFf": actionClientNoTouchOff, + "ofF": actionClientNoTouchOff, + "off": actionClientNoTouchOff, }, } actionClientReplyOff = &commandAction{ - Action: func(state *connectionState) { - *state |= stateClientReplyOff + Action: func(cs *connectionState) { + *cs |= stateClientReplyOff }, } actionClientReplyOn = &commandAction{ - Action: func(state *connectionState) { - *state &^= stateClientReplyOff | stateClientReplySkip + Action: func(cs *connectionState) { + *cs &^= stateClientReplyOff | stateClientReplySkipNext | stateClientReplySkip }, } actionClientReplySkip = &commandAction{ - Action: func(state *connectionState) { - if *state&stateClientReplyOff == 0 { - *state |= stateClientReplySkipNext + Action: func(cs *connectionState) { + if *cs&stateClientReplyOff == 0 { + *cs |= stateClientReplySkipNext } }, } @@ -92,251 +104,705 @@ var ( "skip": actionClientReplySkip, }, } + actionClientTrackingOn = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateClientTracking + }, + } + actionClientTrackingOff = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateClientTracking + }, + } + actionClientTracking = &commandAction{ + Next: map[string]*commandAction{ + "ON": actionClientTrackingOn, + "On": actionClientTrackingOn, + "oN": actionClientTrackingOn, + "on": actionClientTrackingOn, + "OFF": actionClientTrackingOff, + "OFf": actionClientTrackingOff, + "OfF": actionClientTrackingOff, + "Off": actionClientTrackingOff, + "oFF": actionClientTrackingOff, + "oFf": actionClientTrackingOff, + "ofF": actionClientTrackingOff, + "off": actionClientTrackingOff, + }, + } actionClient = &commandAction{ Next: map[string]*commandAction{ - "REPLY": actionClientReply, - "REPLy": actionClientReply, - "REPlY": actionClientReply, - "REPly": actionClientReply, - "REpLY": actionClientReply, - "REpLy": actionClientReply, - "REplY": actionClientReply, - "REply": actionClientReply, - "RePLY": actionClientReply, - "RePLy": actionClientReply, - "RePlY": actionClientReply, - "RePly": actionClientReply, - "RepLY": actionClientReply, - "RepLy": actionClientReply, - "ReplY": actionClientReply, - "Reply": actionClientReply, - "rEPLY": actionClientReply, - "rEPLy": actionClientReply, - "rEPlY": actionClientReply, - "rEPly": actionClientReply, - "rEpLY": actionClientReply, - "rEpLy": actionClientReply, - "rEplY": actionClientReply, - "rEply": actionClientReply, - "rePLY": actionClientReply, - "rePLy": actionClientReply, - "rePlY": actionClientReply, - "rePly": actionClientReply, - "repLY": actionClientReply, - "repLy": actionClientReply, - "replY": actionClientReply, - "reply": actionClientReply, + "NO-EVICT": actionClientNoEvict, + "NO-EVICt": actionClientNoEvict, + "NO-EVIcT": actionClientNoEvict, + "NO-EVIct": actionClientNoEvict, + "NO-EViCT": actionClientNoEvict, + "NO-EViCt": actionClientNoEvict, + "NO-EVicT": actionClientNoEvict, + "NO-EVict": actionClientNoEvict, + "NO-EvICT": actionClientNoEvict, + "NO-EvICt": actionClientNoEvict, + "NO-EvIcT": actionClientNoEvict, + "NO-EvIct": actionClientNoEvict, + "NO-EviCT": actionClientNoEvict, + "NO-EviCt": actionClientNoEvict, + "NO-EvicT": actionClientNoEvict, + "NO-Evict": actionClientNoEvict, + "NO-eVICT": actionClientNoEvict, + "NO-eVICt": actionClientNoEvict, + "NO-eVIcT": actionClientNoEvict, + "NO-eVIct": actionClientNoEvict, + "NO-eViCT": actionClientNoEvict, + "NO-eViCt": actionClientNoEvict, + "NO-eVicT": actionClientNoEvict, + "NO-eVict": actionClientNoEvict, + "NO-evICT": actionClientNoEvict, + "NO-evICt": actionClientNoEvict, + "NO-evIcT": actionClientNoEvict, + "NO-evIct": actionClientNoEvict, + "NO-eviCT": actionClientNoEvict, + "NO-eviCt": actionClientNoEvict, + "NO-evicT": actionClientNoEvict, + "NO-evict": actionClientNoEvict, + "No-EVICT": actionClientNoEvict, + "No-EVICt": actionClientNoEvict, + "No-EVIcT": actionClientNoEvict, + "No-EVIct": actionClientNoEvict, + "No-EViCT": actionClientNoEvict, + "No-EViCt": actionClientNoEvict, + "No-EVicT": actionClientNoEvict, + "No-EVict": actionClientNoEvict, + "No-EvICT": actionClientNoEvict, + "No-EvICt": actionClientNoEvict, + "No-EvIcT": actionClientNoEvict, + "No-EvIct": actionClientNoEvict, + "No-EviCT": actionClientNoEvict, + "No-EviCt": actionClientNoEvict, + "No-EvicT": actionClientNoEvict, + "No-Evict": actionClientNoEvict, + "No-eVICT": actionClientNoEvict, + "No-eVICt": actionClientNoEvict, + "No-eVIcT": actionClientNoEvict, + "No-eVIct": actionClientNoEvict, + "No-eViCT": actionClientNoEvict, + "No-eViCt": actionClientNoEvict, + "No-eVicT": actionClientNoEvict, + "No-eVict": actionClientNoEvict, + "No-evICT": actionClientNoEvict, + "No-evICt": actionClientNoEvict, + "No-evIcT": actionClientNoEvict, + "No-evIct": actionClientNoEvict, + "No-eviCT": actionClientNoEvict, + "No-eviCt": actionClientNoEvict, + "No-evicT": actionClientNoEvict, + "No-evict": actionClientNoEvict, + "nO-EVICT": actionClientNoEvict, + "nO-EVICt": actionClientNoEvict, + "nO-EVIcT": actionClientNoEvict, + "nO-EVIct": actionClientNoEvict, + "nO-EViCT": actionClientNoEvict, + "nO-EViCt": actionClientNoEvict, + "nO-EVicT": actionClientNoEvict, + "nO-EVict": actionClientNoEvict, + "nO-EvICT": actionClientNoEvict, + "nO-EvICt": actionClientNoEvict, + "nO-EvIcT": actionClientNoEvict, + "nO-EvIct": actionClientNoEvict, + "nO-EviCT": actionClientNoEvict, + "nO-EviCt": actionClientNoEvict, + "nO-EvicT": actionClientNoEvict, + "nO-Evict": actionClientNoEvict, + "nO-eVICT": actionClientNoEvict, + "nO-eVICt": actionClientNoEvict, + "nO-eVIcT": actionClientNoEvict, + "nO-eVIct": actionClientNoEvict, + "nO-eViCT": actionClientNoEvict, + "nO-eViCt": actionClientNoEvict, + "nO-eVicT": actionClientNoEvict, + "nO-eVict": actionClientNoEvict, + "nO-evICT": actionClientNoEvict, + "nO-evICt": actionClientNoEvict, + "nO-evIcT": actionClientNoEvict, + "nO-evIct": actionClientNoEvict, + "nO-eviCT": actionClientNoEvict, + "nO-eviCt": actionClientNoEvict, + "nO-evicT": actionClientNoEvict, + "nO-evict": actionClientNoEvict, + "no-EVICT": actionClientNoEvict, + "no-EVICt": actionClientNoEvict, + "no-EVIcT": actionClientNoEvict, + "no-EVIct": actionClientNoEvict, + "no-EViCT": actionClientNoEvict, + "no-EViCt": actionClientNoEvict, + "no-EVicT": actionClientNoEvict, + "no-EVict": actionClientNoEvict, + "no-EvICT": actionClientNoEvict, + "no-EvICt": actionClientNoEvict, + "no-EvIcT": actionClientNoEvict, + "no-EvIct": actionClientNoEvict, + "no-EviCT": actionClientNoEvict, + "no-EviCt": actionClientNoEvict, + "no-EvicT": actionClientNoEvict, + "no-Evict": actionClientNoEvict, + "no-eVICT": actionClientNoEvict, + "no-eVICt": actionClientNoEvict, + "no-eVIcT": actionClientNoEvict, + "no-eVIct": actionClientNoEvict, + "no-eViCT": actionClientNoEvict, + "no-eViCt": actionClientNoEvict, + "no-eVicT": actionClientNoEvict, + "no-eVict": actionClientNoEvict, + "no-evICT": actionClientNoEvict, + "no-evICt": actionClientNoEvict, + "no-evIcT": actionClientNoEvict, + "no-evIct": actionClientNoEvict, + "no-eviCT": actionClientNoEvict, + "no-eviCt": actionClientNoEvict, + "no-evicT": actionClientNoEvict, + "no-evict": actionClientNoEvict, + "NO-TOUCH": actionClientNoTouch, + "NO-TOUCh": actionClientNoTouch, + "NO-TOUcH": actionClientNoTouch, + "NO-TOUch": actionClientNoTouch, + "NO-TOuCH": actionClientNoTouch, + "NO-TOuCh": actionClientNoTouch, + "NO-TOucH": actionClientNoTouch, + "NO-TOuch": actionClientNoTouch, + "NO-ToUCH": actionClientNoTouch, + "NO-ToUCh": actionClientNoTouch, + "NO-ToUcH": actionClientNoTouch, + "NO-ToUch": actionClientNoTouch, + "NO-TouCH": actionClientNoTouch, + "NO-TouCh": actionClientNoTouch, + "NO-ToucH": actionClientNoTouch, + "NO-Touch": actionClientNoTouch, + "NO-tOUCH": actionClientNoTouch, + "NO-tOUCh": actionClientNoTouch, + "NO-tOUcH": actionClientNoTouch, + "NO-tOUch": actionClientNoTouch, + "NO-tOuCH": actionClientNoTouch, + "NO-tOuCh": actionClientNoTouch, + "NO-tOucH": actionClientNoTouch, + "NO-tOuch": actionClientNoTouch, + "NO-toUCH": actionClientNoTouch, + "NO-toUCh": actionClientNoTouch, + "NO-toUcH": actionClientNoTouch, + "NO-toUch": actionClientNoTouch, + "NO-touCH": actionClientNoTouch, + "NO-touCh": actionClientNoTouch, + "NO-toucH": actionClientNoTouch, + "NO-touch": actionClientNoTouch, + "No-TOUCH": actionClientNoTouch, + "No-TOUCh": actionClientNoTouch, + "No-TOUcH": actionClientNoTouch, + "No-TOUch": actionClientNoTouch, + "No-TOuCH": actionClientNoTouch, + "No-TOuCh": actionClientNoTouch, + "No-TOucH": actionClientNoTouch, + "No-TOuch": actionClientNoTouch, + "No-ToUCH": actionClientNoTouch, + "No-ToUCh": actionClientNoTouch, + "No-ToUcH": actionClientNoTouch, + "No-ToUch": actionClientNoTouch, + "No-TouCH": actionClientNoTouch, + "No-TouCh": actionClientNoTouch, + "No-ToucH": actionClientNoTouch, + "No-Touch": actionClientNoTouch, + "No-tOUCH": actionClientNoTouch, + "No-tOUCh": actionClientNoTouch, + "No-tOUcH": actionClientNoTouch, + "No-tOUch": actionClientNoTouch, + "No-tOuCH": actionClientNoTouch, + "No-tOuCh": actionClientNoTouch, + "No-tOucH": actionClientNoTouch, + "No-tOuch": actionClientNoTouch, + "No-toUCH": actionClientNoTouch, + "No-toUCh": actionClientNoTouch, + "No-toUcH": actionClientNoTouch, + "No-toUch": actionClientNoTouch, + "No-touCH": actionClientNoTouch, + "No-touCh": actionClientNoTouch, + "No-toucH": actionClientNoTouch, + "No-touch": actionClientNoTouch, + "nO-TOUCH": actionClientNoTouch, + "nO-TOUCh": actionClientNoTouch, + "nO-TOUcH": actionClientNoTouch, + "nO-TOUch": actionClientNoTouch, + "nO-TOuCH": actionClientNoTouch, + "nO-TOuCh": actionClientNoTouch, + "nO-TOucH": actionClientNoTouch, + "nO-TOuch": actionClientNoTouch, + "nO-ToUCH": actionClientNoTouch, + "nO-ToUCh": actionClientNoTouch, + "nO-ToUcH": actionClientNoTouch, + "nO-ToUch": actionClientNoTouch, + "nO-TouCH": actionClientNoTouch, + "nO-TouCh": actionClientNoTouch, + "nO-ToucH": actionClientNoTouch, + "nO-Touch": actionClientNoTouch, + "nO-tOUCH": actionClientNoTouch, + "nO-tOUCh": actionClientNoTouch, + "nO-tOUcH": actionClientNoTouch, + "nO-tOUch": actionClientNoTouch, + "nO-tOuCH": actionClientNoTouch, + "nO-tOuCh": actionClientNoTouch, + "nO-tOucH": actionClientNoTouch, + "nO-tOuch": actionClientNoTouch, + "nO-toUCH": actionClientNoTouch, + "nO-toUCh": actionClientNoTouch, + "nO-toUcH": actionClientNoTouch, + "nO-toUch": actionClientNoTouch, + "nO-touCH": actionClientNoTouch, + "nO-touCh": actionClientNoTouch, + "nO-toucH": actionClientNoTouch, + "nO-touch": actionClientNoTouch, + "no-TOUCH": actionClientNoTouch, + "no-TOUCh": actionClientNoTouch, + "no-TOUcH": actionClientNoTouch, + "no-TOUch": actionClientNoTouch, + "no-TOuCH": actionClientNoTouch, + "no-TOuCh": actionClientNoTouch, + "no-TOucH": actionClientNoTouch, + "no-TOuch": actionClientNoTouch, + "no-ToUCH": actionClientNoTouch, + "no-ToUCh": actionClientNoTouch, + "no-ToUcH": actionClientNoTouch, + "no-ToUch": actionClientNoTouch, + "no-TouCH": actionClientNoTouch, + "no-TouCh": actionClientNoTouch, + "no-ToucH": actionClientNoTouch, + "no-Touch": actionClientNoTouch, + "no-tOUCH": actionClientNoTouch, + "no-tOUCh": actionClientNoTouch, + "no-tOUcH": actionClientNoTouch, + "no-tOUch": actionClientNoTouch, + "no-tOuCH": actionClientNoTouch, + "no-tOuCh": actionClientNoTouch, + "no-tOucH": actionClientNoTouch, + "no-tOuch": actionClientNoTouch, + "no-toUCH": actionClientNoTouch, + "no-toUCh": actionClientNoTouch, + "no-toUcH": actionClientNoTouch, + "no-toUch": actionClientNoTouch, + "no-touCH": actionClientNoTouch, + "no-touCh": actionClientNoTouch, + "no-toucH": actionClientNoTouch, + "no-touch": actionClientNoTouch, + "REPLY": actionClientReply, + "REPLy": actionClientReply, + "REPlY": actionClientReply, + "REPly": actionClientReply, + "REpLY": actionClientReply, + "REpLy": actionClientReply, + "REplY": actionClientReply, + "REply": actionClientReply, + "RePLY": actionClientReply, + "RePLy": actionClientReply, + "RePlY": actionClientReply, + "RePly": actionClientReply, + "RepLY": actionClientReply, + "RepLy": actionClientReply, + "ReplY": actionClientReply, + "Reply": actionClientReply, + "rEPLY": actionClientReply, + "rEPLy": actionClientReply, + "rEPlY": actionClientReply, + "rEPly": actionClientReply, + "rEpLY": actionClientReply, + "rEpLy": actionClientReply, + "rEplY": actionClientReply, + "rEply": actionClientReply, + "rePLY": actionClientReply, + "rePLy": actionClientReply, + "rePlY": actionClientReply, + "rePly": actionClientReply, + "repLY": actionClientReply, + "repLy": actionClientReply, + "replY": actionClientReply, + "reply": actionClientReply, + "TRACKING": actionClientTracking, + "TRACKINg": actionClientTracking, + "TRACKInG": actionClientTracking, + "TRACKIng": actionClientTracking, + "TRACKiNG": actionClientTracking, + "TRACKiNg": actionClientTracking, + "TRACKinG": actionClientTracking, + "TRACKing": actionClientTracking, + "TRACkING": actionClientTracking, + "TRACkINg": actionClientTracking, + "TRACkInG": actionClientTracking, + "TRACkIng": actionClientTracking, + "TRACkiNG": actionClientTracking, + "TRACkiNg": actionClientTracking, + "TRACkinG": actionClientTracking, + "TRACking": actionClientTracking, + "TRAcKING": actionClientTracking, + "TRAcKINg": actionClientTracking, + "TRAcKInG": actionClientTracking, + "TRAcKIng": actionClientTracking, + "TRAcKiNG": actionClientTracking, + "TRAcKiNg": actionClientTracking, + "TRAcKinG": actionClientTracking, + "TRAcKing": actionClientTracking, + "TRAckING": actionClientTracking, + "TRAckINg": actionClientTracking, + "TRAckInG": actionClientTracking, + "TRAckIng": actionClientTracking, + "TRAckiNG": actionClientTracking, + "TRAckiNg": actionClientTracking, + "TRAckinG": actionClientTracking, + "TRAcking": actionClientTracking, + "TRaCKING": actionClientTracking, + "TRaCKINg": actionClientTracking, + "TRaCKInG": actionClientTracking, + "TRaCKIng": actionClientTracking, + "TRaCKiNG": actionClientTracking, + "TRaCKiNg": actionClientTracking, + "TRaCKinG": actionClientTracking, + "TRaCKing": actionClientTracking, + "TRaCkING": actionClientTracking, + "TRaCkINg": actionClientTracking, + "TRaCkInG": actionClientTracking, + "TRaCkIng": actionClientTracking, + "TRaCkiNG": actionClientTracking, + "TRaCkiNg": actionClientTracking, + "TRaCkinG": actionClientTracking, + "TRaCking": actionClientTracking, + "TRacKING": actionClientTracking, + "TRacKINg": actionClientTracking, + "TRacKInG": actionClientTracking, + "TRacKIng": actionClientTracking, + "TRacKiNG": actionClientTracking, + "TRacKiNg": actionClientTracking, + "TRacKinG": actionClientTracking, + "TRacKing": actionClientTracking, + "TRackING": actionClientTracking, + "TRackINg": actionClientTracking, + "TRackInG": actionClientTracking, + "TRackIng": actionClientTracking, + "TRackiNG": actionClientTracking, + "TRackiNg": actionClientTracking, + "TRackinG": actionClientTracking, + "TRacking": actionClientTracking, + "TrACKING": actionClientTracking, + "TrACKINg": actionClientTracking, + "TrACKInG": actionClientTracking, + "TrACKIng": actionClientTracking, + "TrACKiNG": actionClientTracking, + "TrACKiNg": actionClientTracking, + "TrACKinG": actionClientTracking, + "TrACKing": actionClientTracking, + "TrACkING": actionClientTracking, + "TrACkINg": actionClientTracking, + "TrACkInG": actionClientTracking, + "TrACkIng": actionClientTracking, + "TrACkiNG": actionClientTracking, + "TrACkiNg": actionClientTracking, + "TrACkinG": actionClientTracking, + "TrACking": actionClientTracking, + "TrAcKING": actionClientTracking, + "TrAcKINg": actionClientTracking, + "TrAcKInG": actionClientTracking, + "TrAcKIng": actionClientTracking, + "TrAcKiNG": actionClientTracking, + "TrAcKiNg": actionClientTracking, + "TrAcKinG": actionClientTracking, + "TrAcKing": actionClientTracking, + "TrAckING": actionClientTracking, + "TrAckINg": actionClientTracking, + "TrAckInG": actionClientTracking, + "TrAckIng": actionClientTracking, + "TrAckiNG": actionClientTracking, + "TrAckiNg": actionClientTracking, + "TrAckinG": actionClientTracking, + "TrAcking": actionClientTracking, + "TraCKING": actionClientTracking, + "TraCKINg": actionClientTracking, + "TraCKInG": actionClientTracking, + "TraCKIng": actionClientTracking, + "TraCKiNG": actionClientTracking, + "TraCKiNg": actionClientTracking, + "TraCKinG": actionClientTracking, + "TraCKing": actionClientTracking, + "TraCkING": actionClientTracking, + "TraCkINg": actionClientTracking, + "TraCkInG": actionClientTracking, + "TraCkIng": actionClientTracking, + "TraCkiNG": actionClientTracking, + "TraCkiNg": actionClientTracking, + "TraCkinG": actionClientTracking, + "TraCking": actionClientTracking, + "TracKING": actionClientTracking, + "TracKINg": actionClientTracking, + "TracKInG": actionClientTracking, + "TracKIng": actionClientTracking, + "TracKiNG": actionClientTracking, + "TracKiNg": actionClientTracking, + "TracKinG": actionClientTracking, + "TracKing": actionClientTracking, + "TrackING": actionClientTracking, + "TrackINg": actionClientTracking, + "TrackInG": actionClientTracking, + "TrackIng": actionClientTracking, + "TrackiNG": actionClientTracking, + "TrackiNg": actionClientTracking, + "TrackinG": actionClientTracking, + "Tracking": actionClientTracking, + "tRACKING": actionClientTracking, + "tRACKINg": actionClientTracking, + "tRACKInG": actionClientTracking, + "tRACKIng": actionClientTracking, + "tRACKiNG": actionClientTracking, + "tRACKiNg": actionClientTracking, + "tRACKinG": actionClientTracking, + "tRACKing": actionClientTracking, + "tRACkING": actionClientTracking, + "tRACkINg": actionClientTracking, + "tRACkInG": actionClientTracking, + "tRACkIng": actionClientTracking, + "tRACkiNG": actionClientTracking, + "tRACkiNg": actionClientTracking, + "tRACkinG": actionClientTracking, + "tRACking": actionClientTracking, + "tRAcKING": actionClientTracking, + "tRAcKINg": actionClientTracking, + "tRAcKInG": actionClientTracking, + "tRAcKIng": actionClientTracking, + "tRAcKiNG": actionClientTracking, + "tRAcKiNg": actionClientTracking, + "tRAcKinG": actionClientTracking, + "tRAcKing": actionClientTracking, + "tRAckING": actionClientTracking, + "tRAckINg": actionClientTracking, + "tRAckInG": actionClientTracking, + "tRAckIng": actionClientTracking, + "tRAckiNG": actionClientTracking, + "tRAckiNg": actionClientTracking, + "tRAckinG": actionClientTracking, + "tRAcking": actionClientTracking, + "tRaCKING": actionClientTracking, + "tRaCKINg": actionClientTracking, + "tRaCKInG": actionClientTracking, + "tRaCKIng": actionClientTracking, + "tRaCKiNG": actionClientTracking, + "tRaCKiNg": actionClientTracking, + "tRaCKinG": actionClientTracking, + "tRaCKing": actionClientTracking, + "tRaCkING": actionClientTracking, + "tRaCkINg": actionClientTracking, + "tRaCkInG": actionClientTracking, + "tRaCkIng": actionClientTracking, + "tRaCkiNG": actionClientTracking, + "tRaCkiNg": actionClientTracking, + "tRaCkinG": actionClientTracking, + "tRaCking": actionClientTracking, + "tRacKING": actionClientTracking, + "tRacKINg": actionClientTracking, + "tRacKInG": actionClientTracking, + "tRacKIng": actionClientTracking, + "tRacKiNG": actionClientTracking, + "tRacKiNg": actionClientTracking, + "tRacKinG": actionClientTracking, + "tRacKing": actionClientTracking, + "tRackING": actionClientTracking, + "tRackINg": actionClientTracking, + "tRackInG": actionClientTracking, + "tRackIng": actionClientTracking, + "tRackiNG": actionClientTracking, + "tRackiNg": actionClientTracking, + "tRackinG": actionClientTracking, + "tRacking": actionClientTracking, + "trACKING": actionClientTracking, + "trACKINg": actionClientTracking, + "trACKInG": actionClientTracking, + "trACKIng": actionClientTracking, + "trACKiNG": actionClientTracking, + "trACKiNg": actionClientTracking, + "trACKinG": actionClientTracking, + "trACKing": actionClientTracking, + "trACkING": actionClientTracking, + "trACkINg": actionClientTracking, + "trACkInG": actionClientTracking, + "trACkIng": actionClientTracking, + "trACkiNG": actionClientTracking, + "trACkiNg": actionClientTracking, + "trACkinG": actionClientTracking, + "trACking": actionClientTracking, + "trAcKING": actionClientTracking, + "trAcKINg": actionClientTracking, + "trAcKInG": actionClientTracking, + "trAcKIng": actionClientTracking, + "trAcKiNG": actionClientTracking, + "trAcKiNg": actionClientTracking, + "trAcKinG": actionClientTracking, + "trAcKing": actionClientTracking, + "trAckING": actionClientTracking, + "trAckINg": actionClientTracking, + "trAckInG": actionClientTracking, + "trAckIng": actionClientTracking, + "trAckiNG": actionClientTracking, + "trAckiNg": actionClientTracking, + "trAckinG": actionClientTracking, + "trAcking": actionClientTracking, + "traCKING": actionClientTracking, + "traCKINg": actionClientTracking, + "traCKInG": actionClientTracking, + "traCKIng": actionClientTracking, + "traCKiNG": actionClientTracking, + "traCKiNg": actionClientTracking, + "traCKinG": actionClientTracking, + "traCKing": actionClientTracking, + "traCkING": actionClientTracking, + "traCkINg": actionClientTracking, + "traCkInG": actionClientTracking, + "traCkIng": actionClientTracking, + "traCkiNG": actionClientTracking, + "traCkiNg": actionClientTracking, + "traCkinG": actionClientTracking, + "traCking": actionClientTracking, + "tracKING": actionClientTracking, + "tracKINg": actionClientTracking, + "tracKInG": actionClientTracking, + "tracKIng": actionClientTracking, + "tracKiNG": actionClientTracking, + "tracKiNg": actionClientTracking, + "tracKinG": actionClientTracking, + "tracKing": actionClientTracking, + "trackING": actionClientTracking, + "trackINg": actionClientTracking, + "trackInG": actionClientTracking, + "trackIng": actionClientTracking, + "trackiNG": actionClientTracking, + "trackiNg": actionClientTracking, + "trackinG": actionClientTracking, + "tracking": actionClientTracking, + }, + } + actionDiscard = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateWatch | stateMulti + }, + } + actionExec = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateWatch | stateMulti + }, + } + actionMonitor = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateMonitor + }, + } + actionMulti = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateMulti + }, + } + actionPsubscribe = &commandAction{ + Action: func(cs *connectionState) { + *cs |= statePsubscribe + }, + } + actionSsubscribe = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateSsubscribe + }, + } + actionSubscribe = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateSubscribe + }, + } + actionUnwatch = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateWatch + }, + } + actionReadonly = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateReadOnly + }, + } + actionReadwrite = &commandAction{ + Action: func(cs *connectionState) { + *cs &^= stateReadOnly + }, + } + actionReset = &commandAction{ + Action: func(cs *connectionState) { + *cs = 0 + }, + } + actionWatch = &commandAction{ + Action: func(cs *connectionState) { + *cs |= stateWatch }, } activeConnActions = map[string]*commandAction{ - "WATCH": actionWatch, - "WATCh": actionWatch, - "WATcH": actionWatch, - "WATch": actionWatch, - "WAtCH": actionWatch, - "WAtCh": actionWatch, - "WAtcH": actionWatch, - "WAtch": actionWatch, - "WaTCH": actionWatch, - "WaTCh": actionWatch, - "WaTcH": actionWatch, - "WaTch": actionWatch, - "WatCH": actionWatch, - "WatCh": actionWatch, - "WatcH": actionWatch, - "Watch": actionWatch, - "wATCH": actionWatch, - "wATCh": actionWatch, - "wATcH": actionWatch, - "wATch": actionWatch, - "wAtCH": actionWatch, - "wAtCh": actionWatch, - "wAtcH": actionWatch, - "wAtch": actionWatch, - "waTCH": actionWatch, - "waTCh": actionWatch, - "waTcH": actionWatch, - "waTch": actionWatch, - "watCH": actionWatch, - "watCh": actionWatch, - "watcH": actionWatch, - "watch": actionWatch, - "UNWATCH": actionUnwatch, - "UNWATCh": actionUnwatch, - "UNWATcH": actionUnwatch, - "UNWATch": actionUnwatch, - "UNWAtCH": actionUnwatch, - "UNWAtCh": actionUnwatch, - "UNWAtcH": actionUnwatch, - "UNWAtch": actionUnwatch, - "UNWaTCH": actionUnwatch, - "UNWaTCh": actionUnwatch, - "UNWaTcH": actionUnwatch, - "UNWaTch": actionUnwatch, - "UNWatCH": actionUnwatch, - "UNWatCh": actionUnwatch, - "UNWatcH": actionUnwatch, - "UNWatch": actionUnwatch, - "UNwATCH": actionUnwatch, - "UNwATCh": actionUnwatch, - "UNwATcH": actionUnwatch, - "UNwATch": actionUnwatch, - "UNwAtCH": actionUnwatch, - "UNwAtCh": actionUnwatch, - "UNwAtcH": actionUnwatch, - "UNwAtch": actionUnwatch, - "UNwaTCH": actionUnwatch, - "UNwaTCh": actionUnwatch, - "UNwaTcH": actionUnwatch, - "UNwaTch": actionUnwatch, - "UNwatCH": actionUnwatch, - "UNwatCh": actionUnwatch, - "UNwatcH": actionUnwatch, - "UNwatch": actionUnwatch, - "UnWATCH": actionUnwatch, - "UnWATCh": actionUnwatch, - "UnWATcH": actionUnwatch, - "UnWATch": actionUnwatch, - "UnWAtCH": actionUnwatch, - "UnWAtCh": actionUnwatch, - "UnWAtcH": actionUnwatch, - "UnWAtch": actionUnwatch, - "UnWaTCH": actionUnwatch, - "UnWaTCh": actionUnwatch, - "UnWaTcH": actionUnwatch, - "UnWaTch": actionUnwatch, - "UnWatCH": actionUnwatch, - "UnWatCh": actionUnwatch, - "UnWatcH": actionUnwatch, - "UnWatch": actionUnwatch, - "UnwATCH": actionUnwatch, - "UnwATCh": actionUnwatch, - "UnwATcH": actionUnwatch, - "UnwATch": actionUnwatch, - "UnwAtCH": actionUnwatch, - "UnwAtCh": actionUnwatch, - "UnwAtcH": actionUnwatch, - "UnwAtch": actionUnwatch, - "UnwaTCH": actionUnwatch, - "UnwaTCh": actionUnwatch, - "UnwaTcH": actionUnwatch, - "UnwaTch": actionUnwatch, - "UnwatCH": actionUnwatch, - "UnwatCh": actionUnwatch, - "UnwatcH": actionUnwatch, - "Unwatch": actionUnwatch, - "uNWATCH": actionUnwatch, - "uNWATCh": actionUnwatch, - "uNWATcH": actionUnwatch, - "uNWATch": actionUnwatch, - "uNWAtCH": actionUnwatch, - "uNWAtCh": actionUnwatch, - "uNWAtcH": actionUnwatch, - "uNWAtch": actionUnwatch, - "uNWaTCH": actionUnwatch, - "uNWaTCh": actionUnwatch, - "uNWaTcH": actionUnwatch, - "uNWaTch": actionUnwatch, - "uNWatCH": actionUnwatch, - "uNWatCh": actionUnwatch, - "uNWatcH": actionUnwatch, - "uNWatch": actionUnwatch, - "uNwATCH": actionUnwatch, - "uNwATCh": actionUnwatch, - "uNwATcH": actionUnwatch, - "uNwATch": actionUnwatch, - "uNwAtCH": actionUnwatch, - "uNwAtCh": actionUnwatch, - "uNwAtcH": actionUnwatch, - "uNwAtch": actionUnwatch, - "uNwaTCH": actionUnwatch, - "uNwaTCh": actionUnwatch, - "uNwaTcH": actionUnwatch, - "uNwaTch": actionUnwatch, - "uNwatCH": actionUnwatch, - "uNwatCh": actionUnwatch, - "uNwatcH": actionUnwatch, - "uNwatch": actionUnwatch, - "unWATCH": actionUnwatch, - "unWATCh": actionUnwatch, - "unWATcH": actionUnwatch, - "unWATch": actionUnwatch, - "unWAtCH": actionUnwatch, - "unWAtCh": actionUnwatch, - "unWAtcH": actionUnwatch, - "unWAtch": actionUnwatch, - "unWaTCH": actionUnwatch, - "unWaTCh": actionUnwatch, - "unWaTcH": actionUnwatch, - "unWaTch": actionUnwatch, - "unWatCH": actionUnwatch, - "unWatCh": actionUnwatch, - "unWatcH": actionUnwatch, - "unWatch": actionUnwatch, - "unwATCH": actionUnwatch, - "unwATCh": actionUnwatch, - "unwATcH": actionUnwatch, - "unwATch": actionUnwatch, - "unwAtCH": actionUnwatch, - "unwAtCh": actionUnwatch, - "unwAtcH": actionUnwatch, - "unwAtch": actionUnwatch, - "unwaTCH": actionUnwatch, - "unwaTCh": actionUnwatch, - "unwaTcH": actionUnwatch, - "unwaTch": actionUnwatch, - "unwatCH": actionUnwatch, - "unwatCh": actionUnwatch, - "unwatcH": actionUnwatch, - "unwatch": actionUnwatch, - "MULTI": actionMulti, - "MULTi": actionMulti, - "MULtI": actionMulti, - "MULti": actionMulti, - "MUlTI": actionMulti, - "MUlTi": actionMulti, - "MUltI": actionMulti, - "MUlti": actionMulti, - "MuLTI": actionMulti, - "MuLTi": actionMulti, - "MuLtI": actionMulti, - "MuLti": actionMulti, - "MulTI": actionMulti, - "MulTi": actionMulti, - "MultI": actionMulti, - "Multi": actionMulti, - "mULTI": actionMulti, - "mULTi": actionMulti, - "mULtI": actionMulti, - "mULti": actionMulti, - "mUlTI": actionMulti, - "mUlTi": actionMulti, - "mUltI": actionMulti, - "mUlti": actionMulti, - "muLTI": actionMulti, - "muLTi": actionMulti, - "muLtI": actionMulti, - "muLti": actionMulti, - "mulTI": actionMulti, - "mulTi": actionMulti, - "multI": actionMulti, - "multi": actionMulti, - "EXEC": actionExec, - "EXEc": actionExec, - "EXeC": actionExec, - "EXec": actionExec, - "ExEC": actionExec, - "ExEc": actionExec, - "ExeC": actionExec, - "Exec": actionExec, - "eXEC": actionExec, - "eXEc": actionExec, - "eXeC": actionExec, - "eXec": actionExec, - "exEC": actionExec, - "exEc": actionExec, - "exeC": actionExec, - "exec": actionExec, + "CLIENT": actionClient, + "CLIENt": actionClient, + "CLIEnT": actionClient, + "CLIEnt": actionClient, + "CLIeNT": actionClient, + "CLIeNt": actionClient, + "CLIenT": actionClient, + "CLIent": actionClient, + "CLiENT": actionClient, + "CLiENt": actionClient, + "CLiEnT": actionClient, + "CLiEnt": actionClient, + "CLieNT": actionClient, + "CLieNt": actionClient, + "CLienT": actionClient, + "CLient": actionClient, + "ClIENT": actionClient, + "ClIENt": actionClient, + "ClIEnT": actionClient, + "ClIEnt": actionClient, + "ClIeNT": actionClient, + "ClIeNt": actionClient, + "ClIenT": actionClient, + "ClIent": actionClient, + "CliENT": actionClient, + "CliENt": actionClient, + "CliEnT": actionClient, + "CliEnt": actionClient, + "ClieNT": actionClient, + "ClieNt": actionClient, + "ClienT": actionClient, + "Client": actionClient, + "cLIENT": actionClient, + "cLIENt": actionClient, + "cLIEnT": actionClient, + "cLIEnt": actionClient, + "cLIeNT": actionClient, + "cLIeNt": actionClient, + "cLIenT": actionClient, + "cLIent": actionClient, + "cLiENT": actionClient, + "cLiENt": actionClient, + "cLiEnT": actionClient, + "cLiEnt": actionClient, + "cLieNT": actionClient, + "cLieNt": actionClient, + "cLienT": actionClient, + "cLient": actionClient, + "clIENT": actionClient, + "clIENt": actionClient, + "clIEnT": actionClient, + "clIEnt": actionClient, + "clIeNT": actionClient, + "clIeNt": actionClient, + "clIenT": actionClient, + "clIent": actionClient, + "cliENT": actionClient, + "cliENt": actionClient, + "cliEnT": actionClient, + "cliEnt": actionClient, + "clieNT": actionClient, + "clieNt": actionClient, + "clienT": actionClient, + "client": actionClient, "DISCARD": actionDiscard, "DISCARd": actionDiscard, "DISCArD": actionDiscard, @@ -465,6 +931,182 @@ var ( "discaRd": actionDiscard, "discarD": actionDiscard, "discard": actionDiscard, + "EXEC": actionExec, + "EXEc": actionExec, + "EXeC": actionExec, + "EXec": actionExec, + "ExEC": actionExec, + "ExEc": actionExec, + "ExeC": actionExec, + "Exec": actionExec, + "eXEC": actionExec, + "eXEc": actionExec, + "eXeC": actionExec, + "eXec": actionExec, + "exEC": actionExec, + "exEc": actionExec, + "exeC": actionExec, + "exec": actionExec, + "MONITOR": actionMonitor, + "MONITOr": actionMonitor, + "MONIToR": actionMonitor, + "MONITor": actionMonitor, + "MONItOR": actionMonitor, + "MONItOr": actionMonitor, + "MONItoR": actionMonitor, + "MONItor": actionMonitor, + "MONiTOR": actionMonitor, + "MONiTOr": actionMonitor, + "MONiToR": actionMonitor, + "MONiTor": actionMonitor, + "MONitOR": actionMonitor, + "MONitOr": actionMonitor, + "MONitoR": actionMonitor, + "MONitor": actionMonitor, + "MOnITOR": actionMonitor, + "MOnITOr": actionMonitor, + "MOnIToR": actionMonitor, + "MOnITor": actionMonitor, + "MOnItOR": actionMonitor, + "MOnItOr": actionMonitor, + "MOnItoR": actionMonitor, + "MOnItor": actionMonitor, + "MOniTOR": actionMonitor, + "MOniTOr": actionMonitor, + "MOniToR": actionMonitor, + "MOniTor": actionMonitor, + "MOnitOR": actionMonitor, + "MOnitOr": actionMonitor, + "MOnitoR": actionMonitor, + "MOnitor": actionMonitor, + "MoNITOR": actionMonitor, + "MoNITOr": actionMonitor, + "MoNIToR": actionMonitor, + "MoNITor": actionMonitor, + "MoNItOR": actionMonitor, + "MoNItOr": actionMonitor, + "MoNItoR": actionMonitor, + "MoNItor": actionMonitor, + "MoNiTOR": actionMonitor, + "MoNiTOr": actionMonitor, + "MoNiToR": actionMonitor, + "MoNiTor": actionMonitor, + "MoNitOR": actionMonitor, + "MoNitOr": actionMonitor, + "MoNitoR": actionMonitor, + "MoNitor": actionMonitor, + "MonITOR": actionMonitor, + "MonITOr": actionMonitor, + "MonIToR": actionMonitor, + "MonITor": actionMonitor, + "MonItOR": actionMonitor, + "MonItOr": actionMonitor, + "MonItoR": actionMonitor, + "MonItor": actionMonitor, + "MoniTOR": actionMonitor, + "MoniTOr": actionMonitor, + "MoniToR": actionMonitor, + "MoniTor": actionMonitor, + "MonitOR": actionMonitor, + "MonitOr": actionMonitor, + "MonitoR": actionMonitor, + "Monitor": actionMonitor, + "mONITOR": actionMonitor, + "mONITOr": actionMonitor, + "mONIToR": actionMonitor, + "mONITor": actionMonitor, + "mONItOR": actionMonitor, + "mONItOr": actionMonitor, + "mONItoR": actionMonitor, + "mONItor": actionMonitor, + "mONiTOR": actionMonitor, + "mONiTOr": actionMonitor, + "mONiToR": actionMonitor, + "mONiTor": actionMonitor, + "mONitOR": actionMonitor, + "mONitOr": actionMonitor, + "mONitoR": actionMonitor, + "mONitor": actionMonitor, + "mOnITOR": actionMonitor, + "mOnITOr": actionMonitor, + "mOnIToR": actionMonitor, + "mOnITor": actionMonitor, + "mOnItOR": actionMonitor, + "mOnItOr": actionMonitor, + "mOnItoR": actionMonitor, + "mOnItor": actionMonitor, + "mOniTOR": actionMonitor, + "mOniTOr": actionMonitor, + "mOniToR": actionMonitor, + "mOniTor": actionMonitor, + "mOnitOR": actionMonitor, + "mOnitOr": actionMonitor, + "mOnitoR": actionMonitor, + "mOnitor": actionMonitor, + "moNITOR": actionMonitor, + "moNITOr": actionMonitor, + "moNIToR": actionMonitor, + "moNITor": actionMonitor, + "moNItOR": actionMonitor, + "moNItOr": actionMonitor, + "moNItoR": actionMonitor, + "moNItor": actionMonitor, + "moNiTOR": actionMonitor, + "moNiTOr": actionMonitor, + "moNiToR": actionMonitor, + "moNiTor": actionMonitor, + "moNitOR": actionMonitor, + "moNitOr": actionMonitor, + "moNitoR": actionMonitor, + "moNitor": actionMonitor, + "monITOR": actionMonitor, + "monITOr": actionMonitor, + "monIToR": actionMonitor, + "monITor": actionMonitor, + "monItOR": actionMonitor, + "monItOr": actionMonitor, + "monItoR": actionMonitor, + "monItor": actionMonitor, + "moniTOR": actionMonitor, + "moniTOr": actionMonitor, + "moniToR": actionMonitor, + "moniTor": actionMonitor, + "monitOR": actionMonitor, + "monitOr": actionMonitor, + "monitoR": actionMonitor, + "monitor": actionMonitor, + "MULTI": actionMulti, + "MULTi": actionMulti, + "MULtI": actionMulti, + "MULti": actionMulti, + "MUlTI": actionMulti, + "MUlTi": actionMulti, + "MUltI": actionMulti, + "MUlti": actionMulti, + "MuLTI": actionMulti, + "MuLTi": actionMulti, + "MuLtI": actionMulti, + "MuLti": actionMulti, + "MulTI": actionMulti, + "MulTi": actionMulti, + "MultI": actionMulti, + "Multi": actionMulti, + "mULTI": actionMulti, + "mULTi": actionMulti, + "mULtI": actionMulti, + "mULti": actionMulti, + "mUlTI": actionMulti, + "mUlTi": actionMulti, + "mUltI": actionMulti, + "mUlti": actionMulti, + "muLTI": actionMulti, + "muLTi": actionMulti, + "muLtI": actionMulti, + "muLti": actionMulti, + "mulTI": actionMulti, + "mulTi": actionMulti, + "multI": actionMulti, + "multi": actionMulti, "PSUBSCRIBE": actionPsubscribe, "PSUBSCRIBe": actionPsubscribe, "PSUBSCRIbE": actionPsubscribe, @@ -1489,6 +2131,1030 @@ var ( "psubscriBe": actionPsubscribe, "psubscribE": actionPsubscribe, "psubscribe": actionPsubscribe, + "SSUBSCRIBE": actionSsubscribe, + "SSUBSCRIBe": actionSsubscribe, + "SSUBSCRIbE": actionSsubscribe, + "SSUBSCRIbe": actionSsubscribe, + "SSUBSCRiBE": actionSsubscribe, + "SSUBSCRiBe": actionSsubscribe, + "SSUBSCRibE": actionSsubscribe, + "SSUBSCRibe": actionSsubscribe, + "SSUBSCrIBE": actionSsubscribe, + "SSUBSCrIBe": actionSsubscribe, + "SSUBSCrIbE": actionSsubscribe, + "SSUBSCrIbe": actionSsubscribe, + "SSUBSCriBE": actionSsubscribe, + "SSUBSCriBe": actionSsubscribe, + "SSUBSCribE": actionSsubscribe, + "SSUBSCribe": actionSsubscribe, + "SSUBScRIBE": actionSsubscribe, + "SSUBScRIBe": actionSsubscribe, + "SSUBScRIbE": actionSsubscribe, + "SSUBScRIbe": actionSsubscribe, + "SSUBScRiBE": actionSsubscribe, + "SSUBScRiBe": actionSsubscribe, + "SSUBScRibE": actionSsubscribe, + "SSUBScRibe": actionSsubscribe, + "SSUBScrIBE": actionSsubscribe, + "SSUBScrIBe": actionSsubscribe, + "SSUBScrIbE": actionSsubscribe, + "SSUBScrIbe": actionSsubscribe, + "SSUBScriBE": actionSsubscribe, + "SSUBScriBe": actionSsubscribe, + "SSUBScribE": actionSsubscribe, + "SSUBScribe": actionSsubscribe, + "SSUBsCRIBE": actionSsubscribe, + "SSUBsCRIBe": actionSsubscribe, + "SSUBsCRIbE": actionSsubscribe, + "SSUBsCRIbe": actionSsubscribe, + "SSUBsCRiBE": actionSsubscribe, + "SSUBsCRiBe": actionSsubscribe, + "SSUBsCRibE": actionSsubscribe, + "SSUBsCRibe": actionSsubscribe, + "SSUBsCrIBE": actionSsubscribe, + "SSUBsCrIBe": actionSsubscribe, + "SSUBsCrIbE": actionSsubscribe, + "SSUBsCrIbe": actionSsubscribe, + "SSUBsCriBE": actionSsubscribe, + "SSUBsCriBe": actionSsubscribe, + "SSUBsCribE": actionSsubscribe, + "SSUBsCribe": actionSsubscribe, + "SSUBscRIBE": actionSsubscribe, + "SSUBscRIBe": actionSsubscribe, + "SSUBscRIbE": actionSsubscribe, + "SSUBscRIbe": actionSsubscribe, + "SSUBscRiBE": actionSsubscribe, + "SSUBscRiBe": actionSsubscribe, + "SSUBscRibE": actionSsubscribe, + "SSUBscRibe": actionSsubscribe, + "SSUBscrIBE": actionSsubscribe, + "SSUBscrIBe": actionSsubscribe, + "SSUBscrIbE": actionSsubscribe, + "SSUBscrIbe": actionSsubscribe, + "SSUBscriBE": actionSsubscribe, + "SSUBscriBe": actionSsubscribe, + "SSUBscribE": actionSsubscribe, + "SSUBscribe": actionSsubscribe, + "SSUbSCRIBE": actionSsubscribe, + "SSUbSCRIBe": actionSsubscribe, + "SSUbSCRIbE": actionSsubscribe, + "SSUbSCRIbe": actionSsubscribe, + "SSUbSCRiBE": actionSsubscribe, + "SSUbSCRiBe": actionSsubscribe, + "SSUbSCRibE": actionSsubscribe, + "SSUbSCRibe": actionSsubscribe, + "SSUbSCrIBE": actionSsubscribe, + "SSUbSCrIBe": actionSsubscribe, + "SSUbSCrIbE": actionSsubscribe, + "SSUbSCrIbe": actionSsubscribe, + "SSUbSCriBE": actionSsubscribe, + "SSUbSCriBe": actionSsubscribe, + "SSUbSCribE": actionSsubscribe, + "SSUbSCribe": actionSsubscribe, + "SSUbScRIBE": actionSsubscribe, + "SSUbScRIBe": actionSsubscribe, + "SSUbScRIbE": actionSsubscribe, + "SSUbScRIbe": actionSsubscribe, + "SSUbScRiBE": actionSsubscribe, + "SSUbScRiBe": actionSsubscribe, + "SSUbScRibE": actionSsubscribe, + "SSUbScRibe": actionSsubscribe, + "SSUbScrIBE": actionSsubscribe, + "SSUbScrIBe": actionSsubscribe, + "SSUbScrIbE": actionSsubscribe, + "SSUbScrIbe": actionSsubscribe, + "SSUbScriBE": actionSsubscribe, + "SSUbScriBe": actionSsubscribe, + "SSUbScribE": actionSsubscribe, + "SSUbScribe": actionSsubscribe, + "SSUbsCRIBE": actionSsubscribe, + "SSUbsCRIBe": actionSsubscribe, + "SSUbsCRIbE": actionSsubscribe, + "SSUbsCRIbe": actionSsubscribe, + "SSUbsCRiBE": actionSsubscribe, + "SSUbsCRiBe": actionSsubscribe, + "SSUbsCRibE": actionSsubscribe, + "SSUbsCRibe": actionSsubscribe, + "SSUbsCrIBE": actionSsubscribe, + "SSUbsCrIBe": actionSsubscribe, + "SSUbsCrIbE": actionSsubscribe, + "SSUbsCrIbe": actionSsubscribe, + "SSUbsCriBE": actionSsubscribe, + "SSUbsCriBe": actionSsubscribe, + "SSUbsCribE": actionSsubscribe, + "SSUbsCribe": actionSsubscribe, + "SSUbscRIBE": actionSsubscribe, + "SSUbscRIBe": actionSsubscribe, + "SSUbscRIbE": actionSsubscribe, + "SSUbscRIbe": actionSsubscribe, + "SSUbscRiBE": actionSsubscribe, + "SSUbscRiBe": actionSsubscribe, + "SSUbscRibE": actionSsubscribe, + "SSUbscRibe": actionSsubscribe, + "SSUbscrIBE": actionSsubscribe, + "SSUbscrIBe": actionSsubscribe, + "SSUbscrIbE": actionSsubscribe, + "SSUbscrIbe": actionSsubscribe, + "SSUbscriBE": actionSsubscribe, + "SSUbscriBe": actionSsubscribe, + "SSUbscribE": actionSsubscribe, + "SSUbscribe": actionSsubscribe, + "SSuBSCRIBE": actionSsubscribe, + "SSuBSCRIBe": actionSsubscribe, + "SSuBSCRIbE": actionSsubscribe, + "SSuBSCRIbe": actionSsubscribe, + "SSuBSCRiBE": actionSsubscribe, + "SSuBSCRiBe": actionSsubscribe, + "SSuBSCRibE": actionSsubscribe, + "SSuBSCRibe": actionSsubscribe, + "SSuBSCrIBE": actionSsubscribe, + "SSuBSCrIBe": actionSsubscribe, + "SSuBSCrIbE": actionSsubscribe, + "SSuBSCrIbe": actionSsubscribe, + "SSuBSCriBE": actionSsubscribe, + "SSuBSCriBe": actionSsubscribe, + "SSuBSCribE": actionSsubscribe, + "SSuBSCribe": actionSsubscribe, + "SSuBScRIBE": actionSsubscribe, + "SSuBScRIBe": actionSsubscribe, + "SSuBScRIbE": actionSsubscribe, + "SSuBScRIbe": actionSsubscribe, + "SSuBScRiBE": actionSsubscribe, + "SSuBScRiBe": actionSsubscribe, + "SSuBScRibE": actionSsubscribe, + "SSuBScRibe": actionSsubscribe, + "SSuBScrIBE": actionSsubscribe, + "SSuBScrIBe": actionSsubscribe, + "SSuBScrIbE": actionSsubscribe, + "SSuBScrIbe": actionSsubscribe, + "SSuBScriBE": actionSsubscribe, + "SSuBScriBe": actionSsubscribe, + "SSuBScribE": actionSsubscribe, + "SSuBScribe": actionSsubscribe, + "SSuBsCRIBE": actionSsubscribe, + "SSuBsCRIBe": actionSsubscribe, + "SSuBsCRIbE": actionSsubscribe, + "SSuBsCRIbe": actionSsubscribe, + "SSuBsCRiBE": actionSsubscribe, + "SSuBsCRiBe": actionSsubscribe, + "SSuBsCRibE": actionSsubscribe, + "SSuBsCRibe": actionSsubscribe, + "SSuBsCrIBE": actionSsubscribe, + "SSuBsCrIBe": actionSsubscribe, + "SSuBsCrIbE": actionSsubscribe, + "SSuBsCrIbe": actionSsubscribe, + "SSuBsCriBE": actionSsubscribe, + "SSuBsCriBe": actionSsubscribe, + "SSuBsCribE": actionSsubscribe, + "SSuBsCribe": actionSsubscribe, + "SSuBscRIBE": actionSsubscribe, + "SSuBscRIBe": actionSsubscribe, + "SSuBscRIbE": actionSsubscribe, + "SSuBscRIbe": actionSsubscribe, + "SSuBscRiBE": actionSsubscribe, + "SSuBscRiBe": actionSsubscribe, + "SSuBscRibE": actionSsubscribe, + "SSuBscRibe": actionSsubscribe, + "SSuBscrIBE": actionSsubscribe, + "SSuBscrIBe": actionSsubscribe, + "SSuBscrIbE": actionSsubscribe, + "SSuBscrIbe": actionSsubscribe, + "SSuBscriBE": actionSsubscribe, + "SSuBscriBe": actionSsubscribe, + "SSuBscribE": actionSsubscribe, + "SSuBscribe": actionSsubscribe, + "SSubSCRIBE": actionSsubscribe, + "SSubSCRIBe": actionSsubscribe, + "SSubSCRIbE": actionSsubscribe, + "SSubSCRIbe": actionSsubscribe, + "SSubSCRiBE": actionSsubscribe, + "SSubSCRiBe": actionSsubscribe, + "SSubSCRibE": actionSsubscribe, + "SSubSCRibe": actionSsubscribe, + "SSubSCrIBE": actionSsubscribe, + "SSubSCrIBe": actionSsubscribe, + "SSubSCrIbE": actionSsubscribe, + "SSubSCrIbe": actionSsubscribe, + "SSubSCriBE": actionSsubscribe, + "SSubSCriBe": actionSsubscribe, + "SSubSCribE": actionSsubscribe, + "SSubSCribe": actionSsubscribe, + "SSubScRIBE": actionSsubscribe, + "SSubScRIBe": actionSsubscribe, + "SSubScRIbE": actionSsubscribe, + "SSubScRIbe": actionSsubscribe, + "SSubScRiBE": actionSsubscribe, + "SSubScRiBe": actionSsubscribe, + "SSubScRibE": actionSsubscribe, + "SSubScRibe": actionSsubscribe, + "SSubScrIBE": actionSsubscribe, + "SSubScrIBe": actionSsubscribe, + "SSubScrIbE": actionSsubscribe, + "SSubScrIbe": actionSsubscribe, + "SSubScriBE": actionSsubscribe, + "SSubScriBe": actionSsubscribe, + "SSubScribE": actionSsubscribe, + "SSubScribe": actionSsubscribe, + "SSubsCRIBE": actionSsubscribe, + "SSubsCRIBe": actionSsubscribe, + "SSubsCRIbE": actionSsubscribe, + "SSubsCRIbe": actionSsubscribe, + "SSubsCRiBE": actionSsubscribe, + "SSubsCRiBe": actionSsubscribe, + "SSubsCRibE": actionSsubscribe, + "SSubsCRibe": actionSsubscribe, + "SSubsCrIBE": actionSsubscribe, + "SSubsCrIBe": actionSsubscribe, + "SSubsCrIbE": actionSsubscribe, + "SSubsCrIbe": actionSsubscribe, + "SSubsCriBE": actionSsubscribe, + "SSubsCriBe": actionSsubscribe, + "SSubsCribE": actionSsubscribe, + "SSubsCribe": actionSsubscribe, + "SSubscRIBE": actionSsubscribe, + "SSubscRIBe": actionSsubscribe, + "SSubscRIbE": actionSsubscribe, + "SSubscRIbe": actionSsubscribe, + "SSubscRiBE": actionSsubscribe, + "SSubscRiBe": actionSsubscribe, + "SSubscRibE": actionSsubscribe, + "SSubscRibe": actionSsubscribe, + "SSubscrIBE": actionSsubscribe, + "SSubscrIBe": actionSsubscribe, + "SSubscrIbE": actionSsubscribe, + "SSubscrIbe": actionSsubscribe, + "SSubscriBE": actionSsubscribe, + "SSubscriBe": actionSsubscribe, + "SSubscribE": actionSsubscribe, + "SSubscribe": actionSsubscribe, + "SsUBSCRIBE": actionSsubscribe, + "SsUBSCRIBe": actionSsubscribe, + "SsUBSCRIbE": actionSsubscribe, + "SsUBSCRIbe": actionSsubscribe, + "SsUBSCRiBE": actionSsubscribe, + "SsUBSCRiBe": actionSsubscribe, + "SsUBSCRibE": actionSsubscribe, + "SsUBSCRibe": actionSsubscribe, + "SsUBSCrIBE": actionSsubscribe, + "SsUBSCrIBe": actionSsubscribe, + "SsUBSCrIbE": actionSsubscribe, + "SsUBSCrIbe": actionSsubscribe, + "SsUBSCriBE": actionSsubscribe, + "SsUBSCriBe": actionSsubscribe, + "SsUBSCribE": actionSsubscribe, + "SsUBSCribe": actionSsubscribe, + "SsUBScRIBE": actionSsubscribe, + "SsUBScRIBe": actionSsubscribe, + "SsUBScRIbE": actionSsubscribe, + "SsUBScRIbe": actionSsubscribe, + "SsUBScRiBE": actionSsubscribe, + "SsUBScRiBe": actionSsubscribe, + "SsUBScRibE": actionSsubscribe, + "SsUBScRibe": actionSsubscribe, + "SsUBScrIBE": actionSsubscribe, + "SsUBScrIBe": actionSsubscribe, + "SsUBScrIbE": actionSsubscribe, + "SsUBScrIbe": actionSsubscribe, + "SsUBScriBE": actionSsubscribe, + "SsUBScriBe": actionSsubscribe, + "SsUBScribE": actionSsubscribe, + "SsUBScribe": actionSsubscribe, + "SsUBsCRIBE": actionSsubscribe, + "SsUBsCRIBe": actionSsubscribe, + "SsUBsCRIbE": actionSsubscribe, + "SsUBsCRIbe": actionSsubscribe, + "SsUBsCRiBE": actionSsubscribe, + "SsUBsCRiBe": actionSsubscribe, + "SsUBsCRibE": actionSsubscribe, + "SsUBsCRibe": actionSsubscribe, + "SsUBsCrIBE": actionSsubscribe, + "SsUBsCrIBe": actionSsubscribe, + "SsUBsCrIbE": actionSsubscribe, + "SsUBsCrIbe": actionSsubscribe, + "SsUBsCriBE": actionSsubscribe, + "SsUBsCriBe": actionSsubscribe, + "SsUBsCribE": actionSsubscribe, + "SsUBsCribe": actionSsubscribe, + "SsUBscRIBE": actionSsubscribe, + "SsUBscRIBe": actionSsubscribe, + "SsUBscRIbE": actionSsubscribe, + "SsUBscRIbe": actionSsubscribe, + "SsUBscRiBE": actionSsubscribe, + "SsUBscRiBe": actionSsubscribe, + "SsUBscRibE": actionSsubscribe, + "SsUBscRibe": actionSsubscribe, + "SsUBscrIBE": actionSsubscribe, + "SsUBscrIBe": actionSsubscribe, + "SsUBscrIbE": actionSsubscribe, + "SsUBscrIbe": actionSsubscribe, + "SsUBscriBE": actionSsubscribe, + "SsUBscriBe": actionSsubscribe, + "SsUBscribE": actionSsubscribe, + "SsUBscribe": actionSsubscribe, + "SsUbSCRIBE": actionSsubscribe, + "SsUbSCRIBe": actionSsubscribe, + "SsUbSCRIbE": actionSsubscribe, + "SsUbSCRIbe": actionSsubscribe, + "SsUbSCRiBE": actionSsubscribe, + "SsUbSCRiBe": actionSsubscribe, + "SsUbSCRibE": actionSsubscribe, + "SsUbSCRibe": actionSsubscribe, + "SsUbSCrIBE": actionSsubscribe, + "SsUbSCrIBe": actionSsubscribe, + "SsUbSCrIbE": actionSsubscribe, + "SsUbSCrIbe": actionSsubscribe, + "SsUbSCriBE": actionSsubscribe, + "SsUbSCriBe": actionSsubscribe, + "SsUbSCribE": actionSsubscribe, + "SsUbSCribe": actionSsubscribe, + "SsUbScRIBE": actionSsubscribe, + "SsUbScRIBe": actionSsubscribe, + "SsUbScRIbE": actionSsubscribe, + "SsUbScRIbe": actionSsubscribe, + "SsUbScRiBE": actionSsubscribe, + "SsUbScRiBe": actionSsubscribe, + "SsUbScRibE": actionSsubscribe, + "SsUbScRibe": actionSsubscribe, + "SsUbScrIBE": actionSsubscribe, + "SsUbScrIBe": actionSsubscribe, + "SsUbScrIbE": actionSsubscribe, + "SsUbScrIbe": actionSsubscribe, + "SsUbScriBE": actionSsubscribe, + "SsUbScriBe": actionSsubscribe, + "SsUbScribE": actionSsubscribe, + "SsUbScribe": actionSsubscribe, + "SsUbsCRIBE": actionSsubscribe, + "SsUbsCRIBe": actionSsubscribe, + "SsUbsCRIbE": actionSsubscribe, + "SsUbsCRIbe": actionSsubscribe, + "SsUbsCRiBE": actionSsubscribe, + "SsUbsCRiBe": actionSsubscribe, + "SsUbsCRibE": actionSsubscribe, + "SsUbsCRibe": actionSsubscribe, + "SsUbsCrIBE": actionSsubscribe, + "SsUbsCrIBe": actionSsubscribe, + "SsUbsCrIbE": actionSsubscribe, + "SsUbsCrIbe": actionSsubscribe, + "SsUbsCriBE": actionSsubscribe, + "SsUbsCriBe": actionSsubscribe, + "SsUbsCribE": actionSsubscribe, + "SsUbsCribe": actionSsubscribe, + "SsUbscRIBE": actionSsubscribe, + "SsUbscRIBe": actionSsubscribe, + "SsUbscRIbE": actionSsubscribe, + "SsUbscRIbe": actionSsubscribe, + "SsUbscRiBE": actionSsubscribe, + "SsUbscRiBe": actionSsubscribe, + "SsUbscRibE": actionSsubscribe, + "SsUbscRibe": actionSsubscribe, + "SsUbscrIBE": actionSsubscribe, + "SsUbscrIBe": actionSsubscribe, + "SsUbscrIbE": actionSsubscribe, + "SsUbscrIbe": actionSsubscribe, + "SsUbscriBE": actionSsubscribe, + "SsUbscriBe": actionSsubscribe, + "SsUbscribE": actionSsubscribe, + "SsUbscribe": actionSsubscribe, + "SsuBSCRIBE": actionSsubscribe, + "SsuBSCRIBe": actionSsubscribe, + "SsuBSCRIbE": actionSsubscribe, + "SsuBSCRIbe": actionSsubscribe, + "SsuBSCRiBE": actionSsubscribe, + "SsuBSCRiBe": actionSsubscribe, + "SsuBSCRibE": actionSsubscribe, + "SsuBSCRibe": actionSsubscribe, + "SsuBSCrIBE": actionSsubscribe, + "SsuBSCrIBe": actionSsubscribe, + "SsuBSCrIbE": actionSsubscribe, + "SsuBSCrIbe": actionSsubscribe, + "SsuBSCriBE": actionSsubscribe, + "SsuBSCriBe": actionSsubscribe, + "SsuBSCribE": actionSsubscribe, + "SsuBSCribe": actionSsubscribe, + "SsuBScRIBE": actionSsubscribe, + "SsuBScRIBe": actionSsubscribe, + "SsuBScRIbE": actionSsubscribe, + "SsuBScRIbe": actionSsubscribe, + "SsuBScRiBE": actionSsubscribe, + "SsuBScRiBe": actionSsubscribe, + "SsuBScRibE": actionSsubscribe, + "SsuBScRibe": actionSsubscribe, + "SsuBScrIBE": actionSsubscribe, + "SsuBScrIBe": actionSsubscribe, + "SsuBScrIbE": actionSsubscribe, + "SsuBScrIbe": actionSsubscribe, + "SsuBScriBE": actionSsubscribe, + "SsuBScriBe": actionSsubscribe, + "SsuBScribE": actionSsubscribe, + "SsuBScribe": actionSsubscribe, + "SsuBsCRIBE": actionSsubscribe, + "SsuBsCRIBe": actionSsubscribe, + "SsuBsCRIbE": actionSsubscribe, + "SsuBsCRIbe": actionSsubscribe, + "SsuBsCRiBE": actionSsubscribe, + "SsuBsCRiBe": actionSsubscribe, + "SsuBsCRibE": actionSsubscribe, + "SsuBsCRibe": actionSsubscribe, + "SsuBsCrIBE": actionSsubscribe, + "SsuBsCrIBe": actionSsubscribe, + "SsuBsCrIbE": actionSsubscribe, + "SsuBsCrIbe": actionSsubscribe, + "SsuBsCriBE": actionSsubscribe, + "SsuBsCriBe": actionSsubscribe, + "SsuBsCribE": actionSsubscribe, + "SsuBsCribe": actionSsubscribe, + "SsuBscRIBE": actionSsubscribe, + "SsuBscRIBe": actionSsubscribe, + "SsuBscRIbE": actionSsubscribe, + "SsuBscRIbe": actionSsubscribe, + "SsuBscRiBE": actionSsubscribe, + "SsuBscRiBe": actionSsubscribe, + "SsuBscRibE": actionSsubscribe, + "SsuBscRibe": actionSsubscribe, + "SsuBscrIBE": actionSsubscribe, + "SsuBscrIBe": actionSsubscribe, + "SsuBscrIbE": actionSsubscribe, + "SsuBscrIbe": actionSsubscribe, + "SsuBscriBE": actionSsubscribe, + "SsuBscriBe": actionSsubscribe, + "SsuBscribE": actionSsubscribe, + "SsuBscribe": actionSsubscribe, + "SsubSCRIBE": actionSsubscribe, + "SsubSCRIBe": actionSsubscribe, + "SsubSCRIbE": actionSsubscribe, + "SsubSCRIbe": actionSsubscribe, + "SsubSCRiBE": actionSsubscribe, + "SsubSCRiBe": actionSsubscribe, + "SsubSCRibE": actionSsubscribe, + "SsubSCRibe": actionSsubscribe, + "SsubSCrIBE": actionSsubscribe, + "SsubSCrIBe": actionSsubscribe, + "SsubSCrIbE": actionSsubscribe, + "SsubSCrIbe": actionSsubscribe, + "SsubSCriBE": actionSsubscribe, + "SsubSCriBe": actionSsubscribe, + "SsubSCribE": actionSsubscribe, + "SsubSCribe": actionSsubscribe, + "SsubScRIBE": actionSsubscribe, + "SsubScRIBe": actionSsubscribe, + "SsubScRIbE": actionSsubscribe, + "SsubScRIbe": actionSsubscribe, + "SsubScRiBE": actionSsubscribe, + "SsubScRiBe": actionSsubscribe, + "SsubScRibE": actionSsubscribe, + "SsubScRibe": actionSsubscribe, + "SsubScrIBE": actionSsubscribe, + "SsubScrIBe": actionSsubscribe, + "SsubScrIbE": actionSsubscribe, + "SsubScrIbe": actionSsubscribe, + "SsubScriBE": actionSsubscribe, + "SsubScriBe": actionSsubscribe, + "SsubScribE": actionSsubscribe, + "SsubScribe": actionSsubscribe, + "SsubsCRIBE": actionSsubscribe, + "SsubsCRIBe": actionSsubscribe, + "SsubsCRIbE": actionSsubscribe, + "SsubsCRIbe": actionSsubscribe, + "SsubsCRiBE": actionSsubscribe, + "SsubsCRiBe": actionSsubscribe, + "SsubsCRibE": actionSsubscribe, + "SsubsCRibe": actionSsubscribe, + "SsubsCrIBE": actionSsubscribe, + "SsubsCrIBe": actionSsubscribe, + "SsubsCrIbE": actionSsubscribe, + "SsubsCrIbe": actionSsubscribe, + "SsubsCriBE": actionSsubscribe, + "SsubsCriBe": actionSsubscribe, + "SsubsCribE": actionSsubscribe, + "SsubsCribe": actionSsubscribe, + "SsubscRIBE": actionSsubscribe, + "SsubscRIBe": actionSsubscribe, + "SsubscRIbE": actionSsubscribe, + "SsubscRIbe": actionSsubscribe, + "SsubscRiBE": actionSsubscribe, + "SsubscRiBe": actionSsubscribe, + "SsubscRibE": actionSsubscribe, + "SsubscRibe": actionSsubscribe, + "SsubscrIBE": actionSsubscribe, + "SsubscrIBe": actionSsubscribe, + "SsubscrIbE": actionSsubscribe, + "SsubscrIbe": actionSsubscribe, + "SsubscriBE": actionSsubscribe, + "SsubscriBe": actionSsubscribe, + "SsubscribE": actionSsubscribe, + "Ssubscribe": actionSsubscribe, + "sSUBSCRIBE": actionSsubscribe, + "sSUBSCRIBe": actionSsubscribe, + "sSUBSCRIbE": actionSsubscribe, + "sSUBSCRIbe": actionSsubscribe, + "sSUBSCRiBE": actionSsubscribe, + "sSUBSCRiBe": actionSsubscribe, + "sSUBSCRibE": actionSsubscribe, + "sSUBSCRibe": actionSsubscribe, + "sSUBSCrIBE": actionSsubscribe, + "sSUBSCrIBe": actionSsubscribe, + "sSUBSCrIbE": actionSsubscribe, + "sSUBSCrIbe": actionSsubscribe, + "sSUBSCriBE": actionSsubscribe, + "sSUBSCriBe": actionSsubscribe, + "sSUBSCribE": actionSsubscribe, + "sSUBSCribe": actionSsubscribe, + "sSUBScRIBE": actionSsubscribe, + "sSUBScRIBe": actionSsubscribe, + "sSUBScRIbE": actionSsubscribe, + "sSUBScRIbe": actionSsubscribe, + "sSUBScRiBE": actionSsubscribe, + "sSUBScRiBe": actionSsubscribe, + "sSUBScRibE": actionSsubscribe, + "sSUBScRibe": actionSsubscribe, + "sSUBScrIBE": actionSsubscribe, + "sSUBScrIBe": actionSsubscribe, + "sSUBScrIbE": actionSsubscribe, + "sSUBScrIbe": actionSsubscribe, + "sSUBScriBE": actionSsubscribe, + "sSUBScriBe": actionSsubscribe, + "sSUBScribE": actionSsubscribe, + "sSUBScribe": actionSsubscribe, + "sSUBsCRIBE": actionSsubscribe, + "sSUBsCRIBe": actionSsubscribe, + "sSUBsCRIbE": actionSsubscribe, + "sSUBsCRIbe": actionSsubscribe, + "sSUBsCRiBE": actionSsubscribe, + "sSUBsCRiBe": actionSsubscribe, + "sSUBsCRibE": actionSsubscribe, + "sSUBsCRibe": actionSsubscribe, + "sSUBsCrIBE": actionSsubscribe, + "sSUBsCrIBe": actionSsubscribe, + "sSUBsCrIbE": actionSsubscribe, + "sSUBsCrIbe": actionSsubscribe, + "sSUBsCriBE": actionSsubscribe, + "sSUBsCriBe": actionSsubscribe, + "sSUBsCribE": actionSsubscribe, + "sSUBsCribe": actionSsubscribe, + "sSUBscRIBE": actionSsubscribe, + "sSUBscRIBe": actionSsubscribe, + "sSUBscRIbE": actionSsubscribe, + "sSUBscRIbe": actionSsubscribe, + "sSUBscRiBE": actionSsubscribe, + "sSUBscRiBe": actionSsubscribe, + "sSUBscRibE": actionSsubscribe, + "sSUBscRibe": actionSsubscribe, + "sSUBscrIBE": actionSsubscribe, + "sSUBscrIBe": actionSsubscribe, + "sSUBscrIbE": actionSsubscribe, + "sSUBscrIbe": actionSsubscribe, + "sSUBscriBE": actionSsubscribe, + "sSUBscriBe": actionSsubscribe, + "sSUBscribE": actionSsubscribe, + "sSUBscribe": actionSsubscribe, + "sSUbSCRIBE": actionSsubscribe, + "sSUbSCRIBe": actionSsubscribe, + "sSUbSCRIbE": actionSsubscribe, + "sSUbSCRIbe": actionSsubscribe, + "sSUbSCRiBE": actionSsubscribe, + "sSUbSCRiBe": actionSsubscribe, + "sSUbSCRibE": actionSsubscribe, + "sSUbSCRibe": actionSsubscribe, + "sSUbSCrIBE": actionSsubscribe, + "sSUbSCrIBe": actionSsubscribe, + "sSUbSCrIbE": actionSsubscribe, + "sSUbSCrIbe": actionSsubscribe, + "sSUbSCriBE": actionSsubscribe, + "sSUbSCriBe": actionSsubscribe, + "sSUbSCribE": actionSsubscribe, + "sSUbSCribe": actionSsubscribe, + "sSUbScRIBE": actionSsubscribe, + "sSUbScRIBe": actionSsubscribe, + "sSUbScRIbE": actionSsubscribe, + "sSUbScRIbe": actionSsubscribe, + "sSUbScRiBE": actionSsubscribe, + "sSUbScRiBe": actionSsubscribe, + "sSUbScRibE": actionSsubscribe, + "sSUbScRibe": actionSsubscribe, + "sSUbScrIBE": actionSsubscribe, + "sSUbScrIBe": actionSsubscribe, + "sSUbScrIbE": actionSsubscribe, + "sSUbScrIbe": actionSsubscribe, + "sSUbScriBE": actionSsubscribe, + "sSUbScriBe": actionSsubscribe, + "sSUbScribE": actionSsubscribe, + "sSUbScribe": actionSsubscribe, + "sSUbsCRIBE": actionSsubscribe, + "sSUbsCRIBe": actionSsubscribe, + "sSUbsCRIbE": actionSsubscribe, + "sSUbsCRIbe": actionSsubscribe, + "sSUbsCRiBE": actionSsubscribe, + "sSUbsCRiBe": actionSsubscribe, + "sSUbsCRibE": actionSsubscribe, + "sSUbsCRibe": actionSsubscribe, + "sSUbsCrIBE": actionSsubscribe, + "sSUbsCrIBe": actionSsubscribe, + "sSUbsCrIbE": actionSsubscribe, + "sSUbsCrIbe": actionSsubscribe, + "sSUbsCriBE": actionSsubscribe, + "sSUbsCriBe": actionSsubscribe, + "sSUbsCribE": actionSsubscribe, + "sSUbsCribe": actionSsubscribe, + "sSUbscRIBE": actionSsubscribe, + "sSUbscRIBe": actionSsubscribe, + "sSUbscRIbE": actionSsubscribe, + "sSUbscRIbe": actionSsubscribe, + "sSUbscRiBE": actionSsubscribe, + "sSUbscRiBe": actionSsubscribe, + "sSUbscRibE": actionSsubscribe, + "sSUbscRibe": actionSsubscribe, + "sSUbscrIBE": actionSsubscribe, + "sSUbscrIBe": actionSsubscribe, + "sSUbscrIbE": actionSsubscribe, + "sSUbscrIbe": actionSsubscribe, + "sSUbscriBE": actionSsubscribe, + "sSUbscriBe": actionSsubscribe, + "sSUbscribE": actionSsubscribe, + "sSUbscribe": actionSsubscribe, + "sSuBSCRIBE": actionSsubscribe, + "sSuBSCRIBe": actionSsubscribe, + "sSuBSCRIbE": actionSsubscribe, + "sSuBSCRIbe": actionSsubscribe, + "sSuBSCRiBE": actionSsubscribe, + "sSuBSCRiBe": actionSsubscribe, + "sSuBSCRibE": actionSsubscribe, + "sSuBSCRibe": actionSsubscribe, + "sSuBSCrIBE": actionSsubscribe, + "sSuBSCrIBe": actionSsubscribe, + "sSuBSCrIbE": actionSsubscribe, + "sSuBSCrIbe": actionSsubscribe, + "sSuBSCriBE": actionSsubscribe, + "sSuBSCriBe": actionSsubscribe, + "sSuBSCribE": actionSsubscribe, + "sSuBSCribe": actionSsubscribe, + "sSuBScRIBE": actionSsubscribe, + "sSuBScRIBe": actionSsubscribe, + "sSuBScRIbE": actionSsubscribe, + "sSuBScRIbe": actionSsubscribe, + "sSuBScRiBE": actionSsubscribe, + "sSuBScRiBe": actionSsubscribe, + "sSuBScRibE": actionSsubscribe, + "sSuBScRibe": actionSsubscribe, + "sSuBScrIBE": actionSsubscribe, + "sSuBScrIBe": actionSsubscribe, + "sSuBScrIbE": actionSsubscribe, + "sSuBScrIbe": actionSsubscribe, + "sSuBScriBE": actionSsubscribe, + "sSuBScriBe": actionSsubscribe, + "sSuBScribE": actionSsubscribe, + "sSuBScribe": actionSsubscribe, + "sSuBsCRIBE": actionSsubscribe, + "sSuBsCRIBe": actionSsubscribe, + "sSuBsCRIbE": actionSsubscribe, + "sSuBsCRIbe": actionSsubscribe, + "sSuBsCRiBE": actionSsubscribe, + "sSuBsCRiBe": actionSsubscribe, + "sSuBsCRibE": actionSsubscribe, + "sSuBsCRibe": actionSsubscribe, + "sSuBsCrIBE": actionSsubscribe, + "sSuBsCrIBe": actionSsubscribe, + "sSuBsCrIbE": actionSsubscribe, + "sSuBsCrIbe": actionSsubscribe, + "sSuBsCriBE": actionSsubscribe, + "sSuBsCriBe": actionSsubscribe, + "sSuBsCribE": actionSsubscribe, + "sSuBsCribe": actionSsubscribe, + "sSuBscRIBE": actionSsubscribe, + "sSuBscRIBe": actionSsubscribe, + "sSuBscRIbE": actionSsubscribe, + "sSuBscRIbe": actionSsubscribe, + "sSuBscRiBE": actionSsubscribe, + "sSuBscRiBe": actionSsubscribe, + "sSuBscRibE": actionSsubscribe, + "sSuBscRibe": actionSsubscribe, + "sSuBscrIBE": actionSsubscribe, + "sSuBscrIBe": actionSsubscribe, + "sSuBscrIbE": actionSsubscribe, + "sSuBscrIbe": actionSsubscribe, + "sSuBscriBE": actionSsubscribe, + "sSuBscriBe": actionSsubscribe, + "sSuBscribE": actionSsubscribe, + "sSuBscribe": actionSsubscribe, + "sSubSCRIBE": actionSsubscribe, + "sSubSCRIBe": actionSsubscribe, + "sSubSCRIbE": actionSsubscribe, + "sSubSCRIbe": actionSsubscribe, + "sSubSCRiBE": actionSsubscribe, + "sSubSCRiBe": actionSsubscribe, + "sSubSCRibE": actionSsubscribe, + "sSubSCRibe": actionSsubscribe, + "sSubSCrIBE": actionSsubscribe, + "sSubSCrIBe": actionSsubscribe, + "sSubSCrIbE": actionSsubscribe, + "sSubSCrIbe": actionSsubscribe, + "sSubSCriBE": actionSsubscribe, + "sSubSCriBe": actionSsubscribe, + "sSubSCribE": actionSsubscribe, + "sSubSCribe": actionSsubscribe, + "sSubScRIBE": actionSsubscribe, + "sSubScRIBe": actionSsubscribe, + "sSubScRIbE": actionSsubscribe, + "sSubScRIbe": actionSsubscribe, + "sSubScRiBE": actionSsubscribe, + "sSubScRiBe": actionSsubscribe, + "sSubScRibE": actionSsubscribe, + "sSubScRibe": actionSsubscribe, + "sSubScrIBE": actionSsubscribe, + "sSubScrIBe": actionSsubscribe, + "sSubScrIbE": actionSsubscribe, + "sSubScrIbe": actionSsubscribe, + "sSubScriBE": actionSsubscribe, + "sSubScriBe": actionSsubscribe, + "sSubScribE": actionSsubscribe, + "sSubScribe": actionSsubscribe, + "sSubsCRIBE": actionSsubscribe, + "sSubsCRIBe": actionSsubscribe, + "sSubsCRIbE": actionSsubscribe, + "sSubsCRIbe": actionSsubscribe, + "sSubsCRiBE": actionSsubscribe, + "sSubsCRiBe": actionSsubscribe, + "sSubsCRibE": actionSsubscribe, + "sSubsCRibe": actionSsubscribe, + "sSubsCrIBE": actionSsubscribe, + "sSubsCrIBe": actionSsubscribe, + "sSubsCrIbE": actionSsubscribe, + "sSubsCrIbe": actionSsubscribe, + "sSubsCriBE": actionSsubscribe, + "sSubsCriBe": actionSsubscribe, + "sSubsCribE": actionSsubscribe, + "sSubsCribe": actionSsubscribe, + "sSubscRIBE": actionSsubscribe, + "sSubscRIBe": actionSsubscribe, + "sSubscRIbE": actionSsubscribe, + "sSubscRIbe": actionSsubscribe, + "sSubscRiBE": actionSsubscribe, + "sSubscRiBe": actionSsubscribe, + "sSubscRibE": actionSsubscribe, + "sSubscRibe": actionSsubscribe, + "sSubscrIBE": actionSsubscribe, + "sSubscrIBe": actionSsubscribe, + "sSubscrIbE": actionSsubscribe, + "sSubscrIbe": actionSsubscribe, + "sSubscriBE": actionSsubscribe, + "sSubscriBe": actionSsubscribe, + "sSubscribE": actionSsubscribe, + "sSubscribe": actionSsubscribe, + "ssUBSCRIBE": actionSsubscribe, + "ssUBSCRIBe": actionSsubscribe, + "ssUBSCRIbE": actionSsubscribe, + "ssUBSCRIbe": actionSsubscribe, + "ssUBSCRiBE": actionSsubscribe, + "ssUBSCRiBe": actionSsubscribe, + "ssUBSCRibE": actionSsubscribe, + "ssUBSCRibe": actionSsubscribe, + "ssUBSCrIBE": actionSsubscribe, + "ssUBSCrIBe": actionSsubscribe, + "ssUBSCrIbE": actionSsubscribe, + "ssUBSCrIbe": actionSsubscribe, + "ssUBSCriBE": actionSsubscribe, + "ssUBSCriBe": actionSsubscribe, + "ssUBSCribE": actionSsubscribe, + "ssUBSCribe": actionSsubscribe, + "ssUBScRIBE": actionSsubscribe, + "ssUBScRIBe": actionSsubscribe, + "ssUBScRIbE": actionSsubscribe, + "ssUBScRIbe": actionSsubscribe, + "ssUBScRiBE": actionSsubscribe, + "ssUBScRiBe": actionSsubscribe, + "ssUBScRibE": actionSsubscribe, + "ssUBScRibe": actionSsubscribe, + "ssUBScrIBE": actionSsubscribe, + "ssUBScrIBe": actionSsubscribe, + "ssUBScrIbE": actionSsubscribe, + "ssUBScrIbe": actionSsubscribe, + "ssUBScriBE": actionSsubscribe, + "ssUBScriBe": actionSsubscribe, + "ssUBScribE": actionSsubscribe, + "ssUBScribe": actionSsubscribe, + "ssUBsCRIBE": actionSsubscribe, + "ssUBsCRIBe": actionSsubscribe, + "ssUBsCRIbE": actionSsubscribe, + "ssUBsCRIbe": actionSsubscribe, + "ssUBsCRiBE": actionSsubscribe, + "ssUBsCRiBe": actionSsubscribe, + "ssUBsCRibE": actionSsubscribe, + "ssUBsCRibe": actionSsubscribe, + "ssUBsCrIBE": actionSsubscribe, + "ssUBsCrIBe": actionSsubscribe, + "ssUBsCrIbE": actionSsubscribe, + "ssUBsCrIbe": actionSsubscribe, + "ssUBsCriBE": actionSsubscribe, + "ssUBsCriBe": actionSsubscribe, + "ssUBsCribE": actionSsubscribe, + "ssUBsCribe": actionSsubscribe, + "ssUBscRIBE": actionSsubscribe, + "ssUBscRIBe": actionSsubscribe, + "ssUBscRIbE": actionSsubscribe, + "ssUBscRIbe": actionSsubscribe, + "ssUBscRiBE": actionSsubscribe, + "ssUBscRiBe": actionSsubscribe, + "ssUBscRibE": actionSsubscribe, + "ssUBscRibe": actionSsubscribe, + "ssUBscrIBE": actionSsubscribe, + "ssUBscrIBe": actionSsubscribe, + "ssUBscrIbE": actionSsubscribe, + "ssUBscrIbe": actionSsubscribe, + "ssUBscriBE": actionSsubscribe, + "ssUBscriBe": actionSsubscribe, + "ssUBscribE": actionSsubscribe, + "ssUBscribe": actionSsubscribe, + "ssUbSCRIBE": actionSsubscribe, + "ssUbSCRIBe": actionSsubscribe, + "ssUbSCRIbE": actionSsubscribe, + "ssUbSCRIbe": actionSsubscribe, + "ssUbSCRiBE": actionSsubscribe, + "ssUbSCRiBe": actionSsubscribe, + "ssUbSCRibE": actionSsubscribe, + "ssUbSCRibe": actionSsubscribe, + "ssUbSCrIBE": actionSsubscribe, + "ssUbSCrIBe": actionSsubscribe, + "ssUbSCrIbE": actionSsubscribe, + "ssUbSCrIbe": actionSsubscribe, + "ssUbSCriBE": actionSsubscribe, + "ssUbSCriBe": actionSsubscribe, + "ssUbSCribE": actionSsubscribe, + "ssUbSCribe": actionSsubscribe, + "ssUbScRIBE": actionSsubscribe, + "ssUbScRIBe": actionSsubscribe, + "ssUbScRIbE": actionSsubscribe, + "ssUbScRIbe": actionSsubscribe, + "ssUbScRiBE": actionSsubscribe, + "ssUbScRiBe": actionSsubscribe, + "ssUbScRibE": actionSsubscribe, + "ssUbScRibe": actionSsubscribe, + "ssUbScrIBE": actionSsubscribe, + "ssUbScrIBe": actionSsubscribe, + "ssUbScrIbE": actionSsubscribe, + "ssUbScrIbe": actionSsubscribe, + "ssUbScriBE": actionSsubscribe, + "ssUbScriBe": actionSsubscribe, + "ssUbScribE": actionSsubscribe, + "ssUbScribe": actionSsubscribe, + "ssUbsCRIBE": actionSsubscribe, + "ssUbsCRIBe": actionSsubscribe, + "ssUbsCRIbE": actionSsubscribe, + "ssUbsCRIbe": actionSsubscribe, + "ssUbsCRiBE": actionSsubscribe, + "ssUbsCRiBe": actionSsubscribe, + "ssUbsCRibE": actionSsubscribe, + "ssUbsCRibe": actionSsubscribe, + "ssUbsCrIBE": actionSsubscribe, + "ssUbsCrIBe": actionSsubscribe, + "ssUbsCrIbE": actionSsubscribe, + "ssUbsCrIbe": actionSsubscribe, + "ssUbsCriBE": actionSsubscribe, + "ssUbsCriBe": actionSsubscribe, + "ssUbsCribE": actionSsubscribe, + "ssUbsCribe": actionSsubscribe, + "ssUbscRIBE": actionSsubscribe, + "ssUbscRIBe": actionSsubscribe, + "ssUbscRIbE": actionSsubscribe, + "ssUbscRIbe": actionSsubscribe, + "ssUbscRiBE": actionSsubscribe, + "ssUbscRiBe": actionSsubscribe, + "ssUbscRibE": actionSsubscribe, + "ssUbscRibe": actionSsubscribe, + "ssUbscrIBE": actionSsubscribe, + "ssUbscrIBe": actionSsubscribe, + "ssUbscrIbE": actionSsubscribe, + "ssUbscrIbe": actionSsubscribe, + "ssUbscriBE": actionSsubscribe, + "ssUbscriBe": actionSsubscribe, + "ssUbscribE": actionSsubscribe, + "ssUbscribe": actionSsubscribe, + "ssuBSCRIBE": actionSsubscribe, + "ssuBSCRIBe": actionSsubscribe, + "ssuBSCRIbE": actionSsubscribe, + "ssuBSCRIbe": actionSsubscribe, + "ssuBSCRiBE": actionSsubscribe, + "ssuBSCRiBe": actionSsubscribe, + "ssuBSCRibE": actionSsubscribe, + "ssuBSCRibe": actionSsubscribe, + "ssuBSCrIBE": actionSsubscribe, + "ssuBSCrIBe": actionSsubscribe, + "ssuBSCrIbE": actionSsubscribe, + "ssuBSCrIbe": actionSsubscribe, + "ssuBSCriBE": actionSsubscribe, + "ssuBSCriBe": actionSsubscribe, + "ssuBSCribE": actionSsubscribe, + "ssuBSCribe": actionSsubscribe, + "ssuBScRIBE": actionSsubscribe, + "ssuBScRIBe": actionSsubscribe, + "ssuBScRIbE": actionSsubscribe, + "ssuBScRIbe": actionSsubscribe, + "ssuBScRiBE": actionSsubscribe, + "ssuBScRiBe": actionSsubscribe, + "ssuBScRibE": actionSsubscribe, + "ssuBScRibe": actionSsubscribe, + "ssuBScrIBE": actionSsubscribe, + "ssuBScrIBe": actionSsubscribe, + "ssuBScrIbE": actionSsubscribe, + "ssuBScrIbe": actionSsubscribe, + "ssuBScriBE": actionSsubscribe, + "ssuBScriBe": actionSsubscribe, + "ssuBScribE": actionSsubscribe, + "ssuBScribe": actionSsubscribe, + "ssuBsCRIBE": actionSsubscribe, + "ssuBsCRIBe": actionSsubscribe, + "ssuBsCRIbE": actionSsubscribe, + "ssuBsCRIbe": actionSsubscribe, + "ssuBsCRiBE": actionSsubscribe, + "ssuBsCRiBe": actionSsubscribe, + "ssuBsCRibE": actionSsubscribe, + "ssuBsCRibe": actionSsubscribe, + "ssuBsCrIBE": actionSsubscribe, + "ssuBsCrIBe": actionSsubscribe, + "ssuBsCrIbE": actionSsubscribe, + "ssuBsCrIbe": actionSsubscribe, + "ssuBsCriBE": actionSsubscribe, + "ssuBsCriBe": actionSsubscribe, + "ssuBsCribE": actionSsubscribe, + "ssuBsCribe": actionSsubscribe, + "ssuBscRIBE": actionSsubscribe, + "ssuBscRIBe": actionSsubscribe, + "ssuBscRIbE": actionSsubscribe, + "ssuBscRIbe": actionSsubscribe, + "ssuBscRiBE": actionSsubscribe, + "ssuBscRiBe": actionSsubscribe, + "ssuBscRibE": actionSsubscribe, + "ssuBscRibe": actionSsubscribe, + "ssuBscrIBE": actionSsubscribe, + "ssuBscrIBe": actionSsubscribe, + "ssuBscrIbE": actionSsubscribe, + "ssuBscrIbe": actionSsubscribe, + "ssuBscriBE": actionSsubscribe, + "ssuBscriBe": actionSsubscribe, + "ssuBscribE": actionSsubscribe, + "ssuBscribe": actionSsubscribe, + "ssubSCRIBE": actionSsubscribe, + "ssubSCRIBe": actionSsubscribe, + "ssubSCRIbE": actionSsubscribe, + "ssubSCRIbe": actionSsubscribe, + "ssubSCRiBE": actionSsubscribe, + "ssubSCRiBe": actionSsubscribe, + "ssubSCRibE": actionSsubscribe, + "ssubSCRibe": actionSsubscribe, + "ssubSCrIBE": actionSsubscribe, + "ssubSCrIBe": actionSsubscribe, + "ssubSCrIbE": actionSsubscribe, + "ssubSCrIbe": actionSsubscribe, + "ssubSCriBE": actionSsubscribe, + "ssubSCriBe": actionSsubscribe, + "ssubSCribE": actionSsubscribe, + "ssubSCribe": actionSsubscribe, + "ssubScRIBE": actionSsubscribe, + "ssubScRIBe": actionSsubscribe, + "ssubScRIbE": actionSsubscribe, + "ssubScRIbe": actionSsubscribe, + "ssubScRiBE": actionSsubscribe, + "ssubScRiBe": actionSsubscribe, + "ssubScRibE": actionSsubscribe, + "ssubScRibe": actionSsubscribe, + "ssubScrIBE": actionSsubscribe, + "ssubScrIBe": actionSsubscribe, + "ssubScrIbE": actionSsubscribe, + "ssubScrIbe": actionSsubscribe, + "ssubScriBE": actionSsubscribe, + "ssubScriBe": actionSsubscribe, + "ssubScribE": actionSsubscribe, + "ssubScribe": actionSsubscribe, + "ssubsCRIBE": actionSsubscribe, + "ssubsCRIBe": actionSsubscribe, + "ssubsCRIbE": actionSsubscribe, + "ssubsCRIbe": actionSsubscribe, + "ssubsCRiBE": actionSsubscribe, + "ssubsCRiBe": actionSsubscribe, + "ssubsCRibE": actionSsubscribe, + "ssubsCRibe": actionSsubscribe, + "ssubsCrIBE": actionSsubscribe, + "ssubsCrIBe": actionSsubscribe, + "ssubsCrIbE": actionSsubscribe, + "ssubsCrIbe": actionSsubscribe, + "ssubsCriBE": actionSsubscribe, + "ssubsCriBe": actionSsubscribe, + "ssubsCribE": actionSsubscribe, + "ssubsCribe": actionSsubscribe, + "ssubscRIBE": actionSsubscribe, + "ssubscRIBe": actionSsubscribe, + "ssubscRIbE": actionSsubscribe, + "ssubscRIbe": actionSsubscribe, + "ssubscRiBE": actionSsubscribe, + "ssubscRiBe": actionSsubscribe, + "ssubscRibE": actionSsubscribe, + "ssubscRibe": actionSsubscribe, + "ssubscrIBE": actionSsubscribe, + "ssubscrIBe": actionSsubscribe, + "ssubscrIbE": actionSsubscribe, + "ssubscrIbe": actionSsubscribe, + "ssubscriBE": actionSsubscribe, + "ssubscriBe": actionSsubscribe, + "ssubscribE": actionSsubscribe, + "ssubscribe": actionSsubscribe, "SUBSCRIBE": actionSubscribe, "SUBSCRIBe": actionSubscribe, "SUBSCRIbE": actionSubscribe, @@ -2001,198 +3667,966 @@ var ( "subscriBe": actionSubscribe, "subscribE": actionSubscribe, "subscribe": actionSubscribe, - "MONITOR": actionMonitor, - "MONITOr": actionMonitor, - "MONIToR": actionMonitor, - "MONITor": actionMonitor, - "MONItOR": actionMonitor, - "MONItOr": actionMonitor, - "MONItoR": actionMonitor, - "MONItor": actionMonitor, - "MONiTOR": actionMonitor, - "MONiTOr": actionMonitor, - "MONiToR": actionMonitor, - "MONiTor": actionMonitor, - "MONitOR": actionMonitor, - "MONitOr": actionMonitor, - "MONitoR": actionMonitor, - "MONitor": actionMonitor, - "MOnITOR": actionMonitor, - "MOnITOr": actionMonitor, - "MOnIToR": actionMonitor, - "MOnITor": actionMonitor, - "MOnItOR": actionMonitor, - "MOnItOr": actionMonitor, - "MOnItoR": actionMonitor, - "MOnItor": actionMonitor, - "MOniTOR": actionMonitor, - "MOniTOr": actionMonitor, - "MOniToR": actionMonitor, - "MOniTor": actionMonitor, - "MOnitOR": actionMonitor, - "MOnitOr": actionMonitor, - "MOnitoR": actionMonitor, - "MOnitor": actionMonitor, - "MoNITOR": actionMonitor, - "MoNITOr": actionMonitor, - "MoNIToR": actionMonitor, - "MoNITor": actionMonitor, - "MoNItOR": actionMonitor, - "MoNItOr": actionMonitor, - "MoNItoR": actionMonitor, - "MoNItor": actionMonitor, - "MoNiTOR": actionMonitor, - "MoNiTOr": actionMonitor, - "MoNiToR": actionMonitor, - "MoNiTor": actionMonitor, - "MoNitOR": actionMonitor, - "MoNitOr": actionMonitor, - "MoNitoR": actionMonitor, - "MoNitor": actionMonitor, - "MonITOR": actionMonitor, - "MonITOr": actionMonitor, - "MonIToR": actionMonitor, - "MonITor": actionMonitor, - "MonItOR": actionMonitor, - "MonItOr": actionMonitor, - "MonItoR": actionMonitor, - "MonItor": actionMonitor, - "MoniTOR": actionMonitor, - "MoniTOr": actionMonitor, - "MoniToR": actionMonitor, - "MoniTor": actionMonitor, - "MonitOR": actionMonitor, - "MonitOr": actionMonitor, - "MonitoR": actionMonitor, - "Monitor": actionMonitor, - "mONITOR": actionMonitor, - "mONITOr": actionMonitor, - "mONIToR": actionMonitor, - "mONITor": actionMonitor, - "mONItOR": actionMonitor, - "mONItOr": actionMonitor, - "mONItoR": actionMonitor, - "mONItor": actionMonitor, - "mONiTOR": actionMonitor, - "mONiTOr": actionMonitor, - "mONiToR": actionMonitor, - "mONiTor": actionMonitor, - "mONitOR": actionMonitor, - "mONitOr": actionMonitor, - "mONitoR": actionMonitor, - "mONitor": actionMonitor, - "mOnITOR": actionMonitor, - "mOnITOr": actionMonitor, - "mOnIToR": actionMonitor, - "mOnITor": actionMonitor, - "mOnItOR": actionMonitor, - "mOnItOr": actionMonitor, - "mOnItoR": actionMonitor, - "mOnItor": actionMonitor, - "mOniTOR": actionMonitor, - "mOniTOr": actionMonitor, - "mOniToR": actionMonitor, - "mOniTor": actionMonitor, - "mOnitOR": actionMonitor, - "mOnitOr": actionMonitor, - "mOnitoR": actionMonitor, - "mOnitor": actionMonitor, - "moNITOR": actionMonitor, - "moNITOr": actionMonitor, - "moNIToR": actionMonitor, - "moNITor": actionMonitor, - "moNItOR": actionMonitor, - "moNItOr": actionMonitor, - "moNItoR": actionMonitor, - "moNItor": actionMonitor, - "moNiTOR": actionMonitor, - "moNiTOr": actionMonitor, - "moNiToR": actionMonitor, - "moNiTor": actionMonitor, - "moNitOR": actionMonitor, - "moNitOr": actionMonitor, - "moNitoR": actionMonitor, - "moNitor": actionMonitor, - "monITOR": actionMonitor, - "monITOr": actionMonitor, - "monIToR": actionMonitor, - "monITor": actionMonitor, - "monItOR": actionMonitor, - "monItOr": actionMonitor, - "monItoR": actionMonitor, - "monItor": actionMonitor, - "moniTOR": actionMonitor, - "moniTOr": actionMonitor, - "moniToR": actionMonitor, - "moniTor": actionMonitor, - "monitOR": actionMonitor, - "monitOr": actionMonitor, - "monitoR": actionMonitor, - "monitor": actionMonitor, - "CLIENT": actionClient, - "CLIENt": actionClient, - "CLIEnT": actionClient, - "CLIEnt": actionClient, - "CLIeNT": actionClient, - "CLIeNt": actionClient, - "CLIenT": actionClient, - "CLIent": actionClient, - "CLiENT": actionClient, - "CLiENt": actionClient, - "CLiEnT": actionClient, - "CLiEnt": actionClient, - "CLieNT": actionClient, - "CLieNt": actionClient, - "CLienT": actionClient, - "CLient": actionClient, - "ClIENT": actionClient, - "ClIENt": actionClient, - "ClIEnT": actionClient, - "ClIEnt": actionClient, - "ClIeNT": actionClient, - "ClIeNt": actionClient, - "ClIenT": actionClient, - "ClIent": actionClient, - "CliENT": actionClient, - "CliENt": actionClient, - "CliEnT": actionClient, - "CliEnt": actionClient, - "ClieNT": actionClient, - "ClieNt": actionClient, - "ClienT": actionClient, - "Client": actionClient, - "cLIENT": actionClient, - "cLIENt": actionClient, - "cLIEnT": actionClient, - "cLIEnt": actionClient, - "cLIeNT": actionClient, - "cLIeNt": actionClient, - "cLIenT": actionClient, - "cLIent": actionClient, - "cLiENT": actionClient, - "cLiENt": actionClient, - "cLiEnT": actionClient, - "cLiEnt": actionClient, - "cLieNT": actionClient, - "cLieNt": actionClient, - "cLienT": actionClient, - "cLient": actionClient, - "clIENT": actionClient, - "clIENt": actionClient, - "clIEnT": actionClient, - "clIEnt": actionClient, - "clIeNT": actionClient, - "clIeNt": actionClient, - "clIenT": actionClient, - "clIent": actionClient, - "cliENT": actionClient, - "cliENt": actionClient, - "cliEnT": actionClient, - "cliEnt": actionClient, - "clieNT": actionClient, - "clieNt": actionClient, - "clienT": actionClient, - "client": actionClient, + "UNWATCH": actionUnwatch, + "UNWATCh": actionUnwatch, + "UNWATcH": actionUnwatch, + "UNWATch": actionUnwatch, + "UNWAtCH": actionUnwatch, + "UNWAtCh": actionUnwatch, + "UNWAtcH": actionUnwatch, + "UNWAtch": actionUnwatch, + "UNWaTCH": actionUnwatch, + "UNWaTCh": actionUnwatch, + "UNWaTcH": actionUnwatch, + "UNWaTch": actionUnwatch, + "UNWatCH": actionUnwatch, + "UNWatCh": actionUnwatch, + "UNWatcH": actionUnwatch, + "UNWatch": actionUnwatch, + "UNwATCH": actionUnwatch, + "UNwATCh": actionUnwatch, + "UNwATcH": actionUnwatch, + "UNwATch": actionUnwatch, + "UNwAtCH": actionUnwatch, + "UNwAtCh": actionUnwatch, + "UNwAtcH": actionUnwatch, + "UNwAtch": actionUnwatch, + "UNwaTCH": actionUnwatch, + "UNwaTCh": actionUnwatch, + "UNwaTcH": actionUnwatch, + "UNwaTch": actionUnwatch, + "UNwatCH": actionUnwatch, + "UNwatCh": actionUnwatch, + "UNwatcH": actionUnwatch, + "UNwatch": actionUnwatch, + "UnWATCH": actionUnwatch, + "UnWATCh": actionUnwatch, + "UnWATcH": actionUnwatch, + "UnWATch": actionUnwatch, + "UnWAtCH": actionUnwatch, + "UnWAtCh": actionUnwatch, + "UnWAtcH": actionUnwatch, + "UnWAtch": actionUnwatch, + "UnWaTCH": actionUnwatch, + "UnWaTCh": actionUnwatch, + "UnWaTcH": actionUnwatch, + "UnWaTch": actionUnwatch, + "UnWatCH": actionUnwatch, + "UnWatCh": actionUnwatch, + "UnWatcH": actionUnwatch, + "UnWatch": actionUnwatch, + "UnwATCH": actionUnwatch, + "UnwATCh": actionUnwatch, + "UnwATcH": actionUnwatch, + "UnwATch": actionUnwatch, + "UnwAtCH": actionUnwatch, + "UnwAtCh": actionUnwatch, + "UnwAtcH": actionUnwatch, + "UnwAtch": actionUnwatch, + "UnwaTCH": actionUnwatch, + "UnwaTCh": actionUnwatch, + "UnwaTcH": actionUnwatch, + "UnwaTch": actionUnwatch, + "UnwatCH": actionUnwatch, + "UnwatCh": actionUnwatch, + "UnwatcH": actionUnwatch, + "Unwatch": actionUnwatch, + "uNWATCH": actionUnwatch, + "uNWATCh": actionUnwatch, + "uNWATcH": actionUnwatch, + "uNWATch": actionUnwatch, + "uNWAtCH": actionUnwatch, + "uNWAtCh": actionUnwatch, + "uNWAtcH": actionUnwatch, + "uNWAtch": actionUnwatch, + "uNWaTCH": actionUnwatch, + "uNWaTCh": actionUnwatch, + "uNWaTcH": actionUnwatch, + "uNWaTch": actionUnwatch, + "uNWatCH": actionUnwatch, + "uNWatCh": actionUnwatch, + "uNWatcH": actionUnwatch, + "uNWatch": actionUnwatch, + "uNwATCH": actionUnwatch, + "uNwATCh": actionUnwatch, + "uNwATcH": actionUnwatch, + "uNwATch": actionUnwatch, + "uNwAtCH": actionUnwatch, + "uNwAtCh": actionUnwatch, + "uNwAtcH": actionUnwatch, + "uNwAtch": actionUnwatch, + "uNwaTCH": actionUnwatch, + "uNwaTCh": actionUnwatch, + "uNwaTcH": actionUnwatch, + "uNwaTch": actionUnwatch, + "uNwatCH": actionUnwatch, + "uNwatCh": actionUnwatch, + "uNwatcH": actionUnwatch, + "uNwatch": actionUnwatch, + "unWATCH": actionUnwatch, + "unWATCh": actionUnwatch, + "unWATcH": actionUnwatch, + "unWATch": actionUnwatch, + "unWAtCH": actionUnwatch, + "unWAtCh": actionUnwatch, + "unWAtcH": actionUnwatch, + "unWAtch": actionUnwatch, + "unWaTCH": actionUnwatch, + "unWaTCh": actionUnwatch, + "unWaTcH": actionUnwatch, + "unWaTch": actionUnwatch, + "unWatCH": actionUnwatch, + "unWatCh": actionUnwatch, + "unWatcH": actionUnwatch, + "unWatch": actionUnwatch, + "unwATCH": actionUnwatch, + "unwATCh": actionUnwatch, + "unwATcH": actionUnwatch, + "unwATch": actionUnwatch, + "unwAtCH": actionUnwatch, + "unwAtCh": actionUnwatch, + "unwAtcH": actionUnwatch, + "unwAtch": actionUnwatch, + "unwaTCH": actionUnwatch, + "unwaTCh": actionUnwatch, + "unwaTcH": actionUnwatch, + "unwaTch": actionUnwatch, + "unwatCH": actionUnwatch, + "unwatCh": actionUnwatch, + "unwatcH": actionUnwatch, + "unwatch": actionUnwatch, + "READONLY": actionReadonly, + "READONLy": actionReadonly, + "READONlY": actionReadonly, + "READONly": actionReadonly, + "READOnLY": actionReadonly, + "READOnLy": actionReadonly, + "READOnlY": actionReadonly, + "READOnly": actionReadonly, + "READoNLY": actionReadonly, + "READoNLy": actionReadonly, + "READoNlY": actionReadonly, + "READoNly": actionReadonly, + "READonLY": actionReadonly, + "READonLy": actionReadonly, + "READonlY": actionReadonly, + "READonly": actionReadonly, + "REAdONLY": actionReadonly, + "REAdONLy": actionReadonly, + "REAdONlY": actionReadonly, + "REAdONly": actionReadonly, + "REAdOnLY": actionReadonly, + "REAdOnLy": actionReadonly, + "REAdOnlY": actionReadonly, + "REAdOnly": actionReadonly, + "REAdoNLY": actionReadonly, + "REAdoNLy": actionReadonly, + "REAdoNlY": actionReadonly, + "REAdoNly": actionReadonly, + "REAdonLY": actionReadonly, + "REAdonLy": actionReadonly, + "REAdonlY": actionReadonly, + "REAdonly": actionReadonly, + "REaDONLY": actionReadonly, + "REaDONLy": actionReadonly, + "REaDONlY": actionReadonly, + "REaDONly": actionReadonly, + "REaDOnLY": actionReadonly, + "REaDOnLy": actionReadonly, + "REaDOnlY": actionReadonly, + "REaDOnly": actionReadonly, + "REaDoNLY": actionReadonly, + "REaDoNLy": actionReadonly, + "REaDoNlY": actionReadonly, + "REaDoNly": actionReadonly, + "REaDonLY": actionReadonly, + "REaDonLy": actionReadonly, + "REaDonlY": actionReadonly, + "REaDonly": actionReadonly, + "REadONLY": actionReadonly, + "REadONLy": actionReadonly, + "REadONlY": actionReadonly, + "REadONly": actionReadonly, + "REadOnLY": actionReadonly, + "REadOnLy": actionReadonly, + "REadOnlY": actionReadonly, + "REadOnly": actionReadonly, + "REadoNLY": actionReadonly, + "REadoNLy": actionReadonly, + "REadoNlY": actionReadonly, + "REadoNly": actionReadonly, + "REadonLY": actionReadonly, + "REadonLy": actionReadonly, + "REadonlY": actionReadonly, + "REadonly": actionReadonly, + "ReADONLY": actionReadonly, + "ReADONLy": actionReadonly, + "ReADONlY": actionReadonly, + "ReADONly": actionReadonly, + "ReADOnLY": actionReadonly, + "ReADOnLy": actionReadonly, + "ReADOnlY": actionReadonly, + "ReADOnly": actionReadonly, + "ReADoNLY": actionReadonly, + "ReADoNLy": actionReadonly, + "ReADoNlY": actionReadonly, + "ReADoNly": actionReadonly, + "ReADonLY": actionReadonly, + "ReADonLy": actionReadonly, + "ReADonlY": actionReadonly, + "ReADonly": actionReadonly, + "ReAdONLY": actionReadonly, + "ReAdONLy": actionReadonly, + "ReAdONlY": actionReadonly, + "ReAdONly": actionReadonly, + "ReAdOnLY": actionReadonly, + "ReAdOnLy": actionReadonly, + "ReAdOnlY": actionReadonly, + "ReAdOnly": actionReadonly, + "ReAdoNLY": actionReadonly, + "ReAdoNLy": actionReadonly, + "ReAdoNlY": actionReadonly, + "ReAdoNly": actionReadonly, + "ReAdonLY": actionReadonly, + "ReAdonLy": actionReadonly, + "ReAdonlY": actionReadonly, + "ReAdonly": actionReadonly, + "ReaDONLY": actionReadonly, + "ReaDONLy": actionReadonly, + "ReaDONlY": actionReadonly, + "ReaDONly": actionReadonly, + "ReaDOnLY": actionReadonly, + "ReaDOnLy": actionReadonly, + "ReaDOnlY": actionReadonly, + "ReaDOnly": actionReadonly, + "ReaDoNLY": actionReadonly, + "ReaDoNLy": actionReadonly, + "ReaDoNlY": actionReadonly, + "ReaDoNly": actionReadonly, + "ReaDonLY": actionReadonly, + "ReaDonLy": actionReadonly, + "ReaDonlY": actionReadonly, + "ReaDonly": actionReadonly, + "ReadONLY": actionReadonly, + "ReadONLy": actionReadonly, + "ReadONlY": actionReadonly, + "ReadONly": actionReadonly, + "ReadOnLY": actionReadonly, + "ReadOnLy": actionReadonly, + "ReadOnlY": actionReadonly, + "ReadOnly": actionReadonly, + "ReadoNLY": actionReadonly, + "ReadoNLy": actionReadonly, + "ReadoNlY": actionReadonly, + "ReadoNly": actionReadonly, + "ReadonLY": actionReadonly, + "ReadonLy": actionReadonly, + "ReadonlY": actionReadonly, + "Readonly": actionReadonly, + "rEADONLY": actionReadonly, + "rEADONLy": actionReadonly, + "rEADONlY": actionReadonly, + "rEADONly": actionReadonly, + "rEADOnLY": actionReadonly, + "rEADOnLy": actionReadonly, + "rEADOnlY": actionReadonly, + "rEADOnly": actionReadonly, + "rEADoNLY": actionReadonly, + "rEADoNLy": actionReadonly, + "rEADoNlY": actionReadonly, + "rEADoNly": actionReadonly, + "rEADonLY": actionReadonly, + "rEADonLy": actionReadonly, + "rEADonlY": actionReadonly, + "rEADonly": actionReadonly, + "rEAdONLY": actionReadonly, + "rEAdONLy": actionReadonly, + "rEAdONlY": actionReadonly, + "rEAdONly": actionReadonly, + "rEAdOnLY": actionReadonly, + "rEAdOnLy": actionReadonly, + "rEAdOnlY": actionReadonly, + "rEAdOnly": actionReadonly, + "rEAdoNLY": actionReadonly, + "rEAdoNLy": actionReadonly, + "rEAdoNlY": actionReadonly, + "rEAdoNly": actionReadonly, + "rEAdonLY": actionReadonly, + "rEAdonLy": actionReadonly, + "rEAdonlY": actionReadonly, + "rEAdonly": actionReadonly, + "rEaDONLY": actionReadonly, + "rEaDONLy": actionReadonly, + "rEaDONlY": actionReadonly, + "rEaDONly": actionReadonly, + "rEaDOnLY": actionReadonly, + "rEaDOnLy": actionReadonly, + "rEaDOnlY": actionReadonly, + "rEaDOnly": actionReadonly, + "rEaDoNLY": actionReadonly, + "rEaDoNLy": actionReadonly, + "rEaDoNlY": actionReadonly, + "rEaDoNly": actionReadonly, + "rEaDonLY": actionReadonly, + "rEaDonLy": actionReadonly, + "rEaDonlY": actionReadonly, + "rEaDonly": actionReadonly, + "rEadONLY": actionReadonly, + "rEadONLy": actionReadonly, + "rEadONlY": actionReadonly, + "rEadONly": actionReadonly, + "rEadOnLY": actionReadonly, + "rEadOnLy": actionReadonly, + "rEadOnlY": actionReadonly, + "rEadOnly": actionReadonly, + "rEadoNLY": actionReadonly, + "rEadoNLy": actionReadonly, + "rEadoNlY": actionReadonly, + "rEadoNly": actionReadonly, + "rEadonLY": actionReadonly, + "rEadonLy": actionReadonly, + "rEadonlY": actionReadonly, + "rEadonly": actionReadonly, + "reADONLY": actionReadonly, + "reADONLy": actionReadonly, + "reADONlY": actionReadonly, + "reADONly": actionReadonly, + "reADOnLY": actionReadonly, + "reADOnLy": actionReadonly, + "reADOnlY": actionReadonly, + "reADOnly": actionReadonly, + "reADoNLY": actionReadonly, + "reADoNLy": actionReadonly, + "reADoNlY": actionReadonly, + "reADoNly": actionReadonly, + "reADonLY": actionReadonly, + "reADonLy": actionReadonly, + "reADonlY": actionReadonly, + "reADonly": actionReadonly, + "reAdONLY": actionReadonly, + "reAdONLy": actionReadonly, + "reAdONlY": actionReadonly, + "reAdONly": actionReadonly, + "reAdOnLY": actionReadonly, + "reAdOnLy": actionReadonly, + "reAdOnlY": actionReadonly, + "reAdOnly": actionReadonly, + "reAdoNLY": actionReadonly, + "reAdoNLy": actionReadonly, + "reAdoNlY": actionReadonly, + "reAdoNly": actionReadonly, + "reAdonLY": actionReadonly, + "reAdonLy": actionReadonly, + "reAdonlY": actionReadonly, + "reAdonly": actionReadonly, + "reaDONLY": actionReadonly, + "reaDONLy": actionReadonly, + "reaDONlY": actionReadonly, + "reaDONly": actionReadonly, + "reaDOnLY": actionReadonly, + "reaDOnLy": actionReadonly, + "reaDOnlY": actionReadonly, + "reaDOnly": actionReadonly, + "reaDoNLY": actionReadonly, + "reaDoNLy": actionReadonly, + "reaDoNlY": actionReadonly, + "reaDoNly": actionReadonly, + "reaDonLY": actionReadonly, + "reaDonLy": actionReadonly, + "reaDonlY": actionReadonly, + "reaDonly": actionReadonly, + "readONLY": actionReadonly, + "readONLy": actionReadonly, + "readONlY": actionReadonly, + "readONly": actionReadonly, + "readOnLY": actionReadonly, + "readOnLy": actionReadonly, + "readOnlY": actionReadonly, + "readOnly": actionReadonly, + "readoNLY": actionReadonly, + "readoNLy": actionReadonly, + "readoNlY": actionReadonly, + "readoNly": actionReadonly, + "readonLY": actionReadonly, + "readonLy": actionReadonly, + "readonlY": actionReadonly, + "readonly": actionReadonly, + "READWRITE": actionReadwrite, + "READWRITe": actionReadwrite, + "READWRItE": actionReadwrite, + "READWRIte": actionReadwrite, + "READWRiTE": actionReadwrite, + "READWRiTe": actionReadwrite, + "READWRitE": actionReadwrite, + "READWRite": actionReadwrite, + "READWrITE": actionReadwrite, + "READWrITe": actionReadwrite, + "READWrItE": actionReadwrite, + "READWrIte": actionReadwrite, + "READWriTE": actionReadwrite, + "READWriTe": actionReadwrite, + "READWritE": actionReadwrite, + "READWrite": actionReadwrite, + "READwRITE": actionReadwrite, + "READwRITe": actionReadwrite, + "READwRItE": actionReadwrite, + "READwRIte": actionReadwrite, + "READwRiTE": actionReadwrite, + "READwRiTe": actionReadwrite, + "READwRitE": actionReadwrite, + "READwRite": actionReadwrite, + "READwrITE": actionReadwrite, + "READwrITe": actionReadwrite, + "READwrItE": actionReadwrite, + "READwrIte": actionReadwrite, + "READwriTE": actionReadwrite, + "READwriTe": actionReadwrite, + "READwritE": actionReadwrite, + "READwrite": actionReadwrite, + "REAdWRITE": actionReadwrite, + "REAdWRITe": actionReadwrite, + "REAdWRItE": actionReadwrite, + "REAdWRIte": actionReadwrite, + "REAdWRiTE": actionReadwrite, + "REAdWRiTe": actionReadwrite, + "REAdWRitE": actionReadwrite, + "REAdWRite": actionReadwrite, + "REAdWrITE": actionReadwrite, + "REAdWrITe": actionReadwrite, + "REAdWrItE": actionReadwrite, + "REAdWrIte": actionReadwrite, + "REAdWriTE": actionReadwrite, + "REAdWriTe": actionReadwrite, + "REAdWritE": actionReadwrite, + "REAdWrite": actionReadwrite, + "REAdwRITE": actionReadwrite, + "REAdwRITe": actionReadwrite, + "REAdwRItE": actionReadwrite, + "REAdwRIte": actionReadwrite, + "REAdwRiTE": actionReadwrite, + "REAdwRiTe": actionReadwrite, + "REAdwRitE": actionReadwrite, + "REAdwRite": actionReadwrite, + "REAdwrITE": actionReadwrite, + "REAdwrITe": actionReadwrite, + "REAdwrItE": actionReadwrite, + "REAdwrIte": actionReadwrite, + "REAdwriTE": actionReadwrite, + "REAdwriTe": actionReadwrite, + "REAdwritE": actionReadwrite, + "REAdwrite": actionReadwrite, + "REaDWRITE": actionReadwrite, + "REaDWRITe": actionReadwrite, + "REaDWRItE": actionReadwrite, + "REaDWRIte": actionReadwrite, + "REaDWRiTE": actionReadwrite, + "REaDWRiTe": actionReadwrite, + "REaDWRitE": actionReadwrite, + "REaDWRite": actionReadwrite, + "REaDWrITE": actionReadwrite, + "REaDWrITe": actionReadwrite, + "REaDWrItE": actionReadwrite, + "REaDWrIte": actionReadwrite, + "REaDWriTE": actionReadwrite, + "REaDWriTe": actionReadwrite, + "REaDWritE": actionReadwrite, + "REaDWrite": actionReadwrite, + "REaDwRITE": actionReadwrite, + "REaDwRITe": actionReadwrite, + "REaDwRItE": actionReadwrite, + "REaDwRIte": actionReadwrite, + "REaDwRiTE": actionReadwrite, + "REaDwRiTe": actionReadwrite, + "REaDwRitE": actionReadwrite, + "REaDwRite": actionReadwrite, + "REaDwrITE": actionReadwrite, + "REaDwrITe": actionReadwrite, + "REaDwrItE": actionReadwrite, + "REaDwrIte": actionReadwrite, + "REaDwriTE": actionReadwrite, + "REaDwriTe": actionReadwrite, + "REaDwritE": actionReadwrite, + "REaDwrite": actionReadwrite, + "REadWRITE": actionReadwrite, + "REadWRITe": actionReadwrite, + "REadWRItE": actionReadwrite, + "REadWRIte": actionReadwrite, + "REadWRiTE": actionReadwrite, + "REadWRiTe": actionReadwrite, + "REadWRitE": actionReadwrite, + "REadWRite": actionReadwrite, + "REadWrITE": actionReadwrite, + "REadWrITe": actionReadwrite, + "REadWrItE": actionReadwrite, + "REadWrIte": actionReadwrite, + "REadWriTE": actionReadwrite, + "REadWriTe": actionReadwrite, + "REadWritE": actionReadwrite, + "REadWrite": actionReadwrite, + "REadwRITE": actionReadwrite, + "REadwRITe": actionReadwrite, + "REadwRItE": actionReadwrite, + "REadwRIte": actionReadwrite, + "REadwRiTE": actionReadwrite, + "REadwRiTe": actionReadwrite, + "REadwRitE": actionReadwrite, + "REadwRite": actionReadwrite, + "REadwrITE": actionReadwrite, + "REadwrITe": actionReadwrite, + "REadwrItE": actionReadwrite, + "REadwrIte": actionReadwrite, + "REadwriTE": actionReadwrite, + "REadwriTe": actionReadwrite, + "REadwritE": actionReadwrite, + "REadwrite": actionReadwrite, + "ReADWRITE": actionReadwrite, + "ReADWRITe": actionReadwrite, + "ReADWRItE": actionReadwrite, + "ReADWRIte": actionReadwrite, + "ReADWRiTE": actionReadwrite, + "ReADWRiTe": actionReadwrite, + "ReADWRitE": actionReadwrite, + "ReADWRite": actionReadwrite, + "ReADWrITE": actionReadwrite, + "ReADWrITe": actionReadwrite, + "ReADWrItE": actionReadwrite, + "ReADWrIte": actionReadwrite, + "ReADWriTE": actionReadwrite, + "ReADWriTe": actionReadwrite, + "ReADWritE": actionReadwrite, + "ReADWrite": actionReadwrite, + "ReADwRITE": actionReadwrite, + "ReADwRITe": actionReadwrite, + "ReADwRItE": actionReadwrite, + "ReADwRIte": actionReadwrite, + "ReADwRiTE": actionReadwrite, + "ReADwRiTe": actionReadwrite, + "ReADwRitE": actionReadwrite, + "ReADwRite": actionReadwrite, + "ReADwrITE": actionReadwrite, + "ReADwrITe": actionReadwrite, + "ReADwrItE": actionReadwrite, + "ReADwrIte": actionReadwrite, + "ReADwriTE": actionReadwrite, + "ReADwriTe": actionReadwrite, + "ReADwritE": actionReadwrite, + "ReADwrite": actionReadwrite, + "ReAdWRITE": actionReadwrite, + "ReAdWRITe": actionReadwrite, + "ReAdWRItE": actionReadwrite, + "ReAdWRIte": actionReadwrite, + "ReAdWRiTE": actionReadwrite, + "ReAdWRiTe": actionReadwrite, + "ReAdWRitE": actionReadwrite, + "ReAdWRite": actionReadwrite, + "ReAdWrITE": actionReadwrite, + "ReAdWrITe": actionReadwrite, + "ReAdWrItE": actionReadwrite, + "ReAdWrIte": actionReadwrite, + "ReAdWriTE": actionReadwrite, + "ReAdWriTe": actionReadwrite, + "ReAdWritE": actionReadwrite, + "ReAdWrite": actionReadwrite, + "ReAdwRITE": actionReadwrite, + "ReAdwRITe": actionReadwrite, + "ReAdwRItE": actionReadwrite, + "ReAdwRIte": actionReadwrite, + "ReAdwRiTE": actionReadwrite, + "ReAdwRiTe": actionReadwrite, + "ReAdwRitE": actionReadwrite, + "ReAdwRite": actionReadwrite, + "ReAdwrITE": actionReadwrite, + "ReAdwrITe": actionReadwrite, + "ReAdwrItE": actionReadwrite, + "ReAdwrIte": actionReadwrite, + "ReAdwriTE": actionReadwrite, + "ReAdwriTe": actionReadwrite, + "ReAdwritE": actionReadwrite, + "ReAdwrite": actionReadwrite, + "ReaDWRITE": actionReadwrite, + "ReaDWRITe": actionReadwrite, + "ReaDWRItE": actionReadwrite, + "ReaDWRIte": actionReadwrite, + "ReaDWRiTE": actionReadwrite, + "ReaDWRiTe": actionReadwrite, + "ReaDWRitE": actionReadwrite, + "ReaDWRite": actionReadwrite, + "ReaDWrITE": actionReadwrite, + "ReaDWrITe": actionReadwrite, + "ReaDWrItE": actionReadwrite, + "ReaDWrIte": actionReadwrite, + "ReaDWriTE": actionReadwrite, + "ReaDWriTe": actionReadwrite, + "ReaDWritE": actionReadwrite, + "ReaDWrite": actionReadwrite, + "ReaDwRITE": actionReadwrite, + "ReaDwRITe": actionReadwrite, + "ReaDwRItE": actionReadwrite, + "ReaDwRIte": actionReadwrite, + "ReaDwRiTE": actionReadwrite, + "ReaDwRiTe": actionReadwrite, + "ReaDwRitE": actionReadwrite, + "ReaDwRite": actionReadwrite, + "ReaDwrITE": actionReadwrite, + "ReaDwrITe": actionReadwrite, + "ReaDwrItE": actionReadwrite, + "ReaDwrIte": actionReadwrite, + "ReaDwriTE": actionReadwrite, + "ReaDwriTe": actionReadwrite, + "ReaDwritE": actionReadwrite, + "ReaDwrite": actionReadwrite, + "ReadWRITE": actionReadwrite, + "ReadWRITe": actionReadwrite, + "ReadWRItE": actionReadwrite, + "ReadWRIte": actionReadwrite, + "ReadWRiTE": actionReadwrite, + "ReadWRiTe": actionReadwrite, + "ReadWRitE": actionReadwrite, + "ReadWRite": actionReadwrite, + "ReadWrITE": actionReadwrite, + "ReadWrITe": actionReadwrite, + "ReadWrItE": actionReadwrite, + "ReadWrIte": actionReadwrite, + "ReadWriTE": actionReadwrite, + "ReadWriTe": actionReadwrite, + "ReadWritE": actionReadwrite, + "ReadWrite": actionReadwrite, + "ReadwRITE": actionReadwrite, + "ReadwRITe": actionReadwrite, + "ReadwRItE": actionReadwrite, + "ReadwRIte": actionReadwrite, + "ReadwRiTE": actionReadwrite, + "ReadwRiTe": actionReadwrite, + "ReadwRitE": actionReadwrite, + "ReadwRite": actionReadwrite, + "ReadwrITE": actionReadwrite, + "ReadwrITe": actionReadwrite, + "ReadwrItE": actionReadwrite, + "ReadwrIte": actionReadwrite, + "ReadwriTE": actionReadwrite, + "ReadwriTe": actionReadwrite, + "ReadwritE": actionReadwrite, + "Readwrite": actionReadwrite, + "rEADWRITE": actionReadwrite, + "rEADWRITe": actionReadwrite, + "rEADWRItE": actionReadwrite, + "rEADWRIte": actionReadwrite, + "rEADWRiTE": actionReadwrite, + "rEADWRiTe": actionReadwrite, + "rEADWRitE": actionReadwrite, + "rEADWRite": actionReadwrite, + "rEADWrITE": actionReadwrite, + "rEADWrITe": actionReadwrite, + "rEADWrItE": actionReadwrite, + "rEADWrIte": actionReadwrite, + "rEADWriTE": actionReadwrite, + "rEADWriTe": actionReadwrite, + "rEADWritE": actionReadwrite, + "rEADWrite": actionReadwrite, + "rEADwRITE": actionReadwrite, + "rEADwRITe": actionReadwrite, + "rEADwRItE": actionReadwrite, + "rEADwRIte": actionReadwrite, + "rEADwRiTE": actionReadwrite, + "rEADwRiTe": actionReadwrite, + "rEADwRitE": actionReadwrite, + "rEADwRite": actionReadwrite, + "rEADwrITE": actionReadwrite, + "rEADwrITe": actionReadwrite, + "rEADwrItE": actionReadwrite, + "rEADwrIte": actionReadwrite, + "rEADwriTE": actionReadwrite, + "rEADwriTe": actionReadwrite, + "rEADwritE": actionReadwrite, + "rEADwrite": actionReadwrite, + "rEAdWRITE": actionReadwrite, + "rEAdWRITe": actionReadwrite, + "rEAdWRItE": actionReadwrite, + "rEAdWRIte": actionReadwrite, + "rEAdWRiTE": actionReadwrite, + "rEAdWRiTe": actionReadwrite, + "rEAdWRitE": actionReadwrite, + "rEAdWRite": actionReadwrite, + "rEAdWrITE": actionReadwrite, + "rEAdWrITe": actionReadwrite, + "rEAdWrItE": actionReadwrite, + "rEAdWrIte": actionReadwrite, + "rEAdWriTE": actionReadwrite, + "rEAdWriTe": actionReadwrite, + "rEAdWritE": actionReadwrite, + "rEAdWrite": actionReadwrite, + "rEAdwRITE": actionReadwrite, + "rEAdwRITe": actionReadwrite, + "rEAdwRItE": actionReadwrite, + "rEAdwRIte": actionReadwrite, + "rEAdwRiTE": actionReadwrite, + "rEAdwRiTe": actionReadwrite, + "rEAdwRitE": actionReadwrite, + "rEAdwRite": actionReadwrite, + "rEAdwrITE": actionReadwrite, + "rEAdwrITe": actionReadwrite, + "rEAdwrItE": actionReadwrite, + "rEAdwrIte": actionReadwrite, + "rEAdwriTE": actionReadwrite, + "rEAdwriTe": actionReadwrite, + "rEAdwritE": actionReadwrite, + "rEAdwrite": actionReadwrite, + "rEaDWRITE": actionReadwrite, + "rEaDWRITe": actionReadwrite, + "rEaDWRItE": actionReadwrite, + "rEaDWRIte": actionReadwrite, + "rEaDWRiTE": actionReadwrite, + "rEaDWRiTe": actionReadwrite, + "rEaDWRitE": actionReadwrite, + "rEaDWRite": actionReadwrite, + "rEaDWrITE": actionReadwrite, + "rEaDWrITe": actionReadwrite, + "rEaDWrItE": actionReadwrite, + "rEaDWrIte": actionReadwrite, + "rEaDWriTE": actionReadwrite, + "rEaDWriTe": actionReadwrite, + "rEaDWritE": actionReadwrite, + "rEaDWrite": actionReadwrite, + "rEaDwRITE": actionReadwrite, + "rEaDwRITe": actionReadwrite, + "rEaDwRItE": actionReadwrite, + "rEaDwRIte": actionReadwrite, + "rEaDwRiTE": actionReadwrite, + "rEaDwRiTe": actionReadwrite, + "rEaDwRitE": actionReadwrite, + "rEaDwRite": actionReadwrite, + "rEaDwrITE": actionReadwrite, + "rEaDwrITe": actionReadwrite, + "rEaDwrItE": actionReadwrite, + "rEaDwrIte": actionReadwrite, + "rEaDwriTE": actionReadwrite, + "rEaDwriTe": actionReadwrite, + "rEaDwritE": actionReadwrite, + "rEaDwrite": actionReadwrite, + "rEadWRITE": actionReadwrite, + "rEadWRITe": actionReadwrite, + "rEadWRItE": actionReadwrite, + "rEadWRIte": actionReadwrite, + "rEadWRiTE": actionReadwrite, + "rEadWRiTe": actionReadwrite, + "rEadWRitE": actionReadwrite, + "rEadWRite": actionReadwrite, + "rEadWrITE": actionReadwrite, + "rEadWrITe": actionReadwrite, + "rEadWrItE": actionReadwrite, + "rEadWrIte": actionReadwrite, + "rEadWriTE": actionReadwrite, + "rEadWriTe": actionReadwrite, + "rEadWritE": actionReadwrite, + "rEadWrite": actionReadwrite, + "rEadwRITE": actionReadwrite, + "rEadwRITe": actionReadwrite, + "rEadwRItE": actionReadwrite, + "rEadwRIte": actionReadwrite, + "rEadwRiTE": actionReadwrite, + "rEadwRiTe": actionReadwrite, + "rEadwRitE": actionReadwrite, + "rEadwRite": actionReadwrite, + "rEadwrITE": actionReadwrite, + "rEadwrITe": actionReadwrite, + "rEadwrItE": actionReadwrite, + "rEadwrIte": actionReadwrite, + "rEadwriTE": actionReadwrite, + "rEadwriTe": actionReadwrite, + "rEadwritE": actionReadwrite, + "rEadwrite": actionReadwrite, + "reADWRITE": actionReadwrite, + "reADWRITe": actionReadwrite, + "reADWRItE": actionReadwrite, + "reADWRIte": actionReadwrite, + "reADWRiTE": actionReadwrite, + "reADWRiTe": actionReadwrite, + "reADWRitE": actionReadwrite, + "reADWRite": actionReadwrite, + "reADWrITE": actionReadwrite, + "reADWrITe": actionReadwrite, + "reADWrItE": actionReadwrite, + "reADWrIte": actionReadwrite, + "reADWriTE": actionReadwrite, + "reADWriTe": actionReadwrite, + "reADWritE": actionReadwrite, + "reADWrite": actionReadwrite, + "reADwRITE": actionReadwrite, + "reADwRITe": actionReadwrite, + "reADwRItE": actionReadwrite, + "reADwRIte": actionReadwrite, + "reADwRiTE": actionReadwrite, + "reADwRiTe": actionReadwrite, + "reADwRitE": actionReadwrite, + "reADwRite": actionReadwrite, + "reADwrITE": actionReadwrite, + "reADwrITe": actionReadwrite, + "reADwrItE": actionReadwrite, + "reADwrIte": actionReadwrite, + "reADwriTE": actionReadwrite, + "reADwriTe": actionReadwrite, + "reADwritE": actionReadwrite, + "reADwrite": actionReadwrite, + "reAdWRITE": actionReadwrite, + "reAdWRITe": actionReadwrite, + "reAdWRItE": actionReadwrite, + "reAdWRIte": actionReadwrite, + "reAdWRiTE": actionReadwrite, + "reAdWRiTe": actionReadwrite, + "reAdWRitE": actionReadwrite, + "reAdWRite": actionReadwrite, + "reAdWrITE": actionReadwrite, + "reAdWrITe": actionReadwrite, + "reAdWrItE": actionReadwrite, + "reAdWrIte": actionReadwrite, + "reAdWriTE": actionReadwrite, + "reAdWriTe": actionReadwrite, + "reAdWritE": actionReadwrite, + "reAdWrite": actionReadwrite, + "reAdwRITE": actionReadwrite, + "reAdwRITe": actionReadwrite, + "reAdwRItE": actionReadwrite, + "reAdwRIte": actionReadwrite, + "reAdwRiTE": actionReadwrite, + "reAdwRiTe": actionReadwrite, + "reAdwRitE": actionReadwrite, + "reAdwRite": actionReadwrite, + "reAdwrITE": actionReadwrite, + "reAdwrITe": actionReadwrite, + "reAdwrItE": actionReadwrite, + "reAdwrIte": actionReadwrite, + "reAdwriTE": actionReadwrite, + "reAdwriTe": actionReadwrite, + "reAdwritE": actionReadwrite, + "reAdwrite": actionReadwrite, + "reaDWRITE": actionReadwrite, + "reaDWRITe": actionReadwrite, + "reaDWRItE": actionReadwrite, + "reaDWRIte": actionReadwrite, + "reaDWRiTE": actionReadwrite, + "reaDWRiTe": actionReadwrite, + "reaDWRitE": actionReadwrite, + "reaDWRite": actionReadwrite, + "reaDWrITE": actionReadwrite, + "reaDWrITe": actionReadwrite, + "reaDWrItE": actionReadwrite, + "reaDWrIte": actionReadwrite, + "reaDWriTE": actionReadwrite, + "reaDWriTe": actionReadwrite, + "reaDWritE": actionReadwrite, + "reaDWrite": actionReadwrite, + "reaDwRITE": actionReadwrite, + "reaDwRITe": actionReadwrite, + "reaDwRItE": actionReadwrite, + "reaDwRIte": actionReadwrite, + "reaDwRiTE": actionReadwrite, + "reaDwRiTe": actionReadwrite, + "reaDwRitE": actionReadwrite, + "reaDwRite": actionReadwrite, + "reaDwrITE": actionReadwrite, + "reaDwrITe": actionReadwrite, + "reaDwrItE": actionReadwrite, + "reaDwrIte": actionReadwrite, + "reaDwriTE": actionReadwrite, + "reaDwriTe": actionReadwrite, + "reaDwritE": actionReadwrite, + "reaDwrite": actionReadwrite, + "readWRITE": actionReadwrite, + "readWRITe": actionReadwrite, + "readWRItE": actionReadwrite, + "readWRIte": actionReadwrite, + "readWRiTE": actionReadwrite, + "readWRiTe": actionReadwrite, + "readWRitE": actionReadwrite, + "readWRite": actionReadwrite, + "readWrITE": actionReadwrite, + "readWrITe": actionReadwrite, + "readWrItE": actionReadwrite, + "readWrIte": actionReadwrite, + "readWriTE": actionReadwrite, + "readWriTe": actionReadwrite, + "readWritE": actionReadwrite, + "readWrite": actionReadwrite, + "readwRITE": actionReadwrite, + "readwRITe": actionReadwrite, + "readwRItE": actionReadwrite, + "readwRIte": actionReadwrite, + "readwRiTE": actionReadwrite, + "readwRiTe": actionReadwrite, + "readwRitE": actionReadwrite, + "readwRite": actionReadwrite, + "readwrITE": actionReadwrite, + "readwrITe": actionReadwrite, + "readwrItE": actionReadwrite, + "readwrIte": actionReadwrite, + "readwriTE": actionReadwrite, + "readwriTe": actionReadwrite, + "readwritE": actionReadwrite, + "readwrite": actionReadwrite, + "RESET": actionReset, + "RESEt": actionReset, + "RESeT": actionReset, + "RESet": actionReset, + "REsET": actionReset, + "REsEt": actionReset, + "REseT": actionReset, + "REset": actionReset, + "ReSET": actionReset, + "ReSEt": actionReset, + "ReSeT": actionReset, + "ReSet": actionReset, + "ResET": actionReset, + "ResEt": actionReset, + "ReseT": actionReset, + "Reset": actionReset, + "rESET": actionReset, + "rESEt": actionReset, + "rESeT": actionReset, + "rESet": actionReset, + "rEsET": actionReset, + "rEsEt": actionReset, + "rEseT": actionReset, + "rEset": actionReset, + "reSET": actionReset, + "reSEt": actionReset, + "reSeT": actionReset, + "reSet": actionReset, + "resET": actionReset, + "resEt": actionReset, + "reseT": actionReset, + "reset": actionReset, + "WATCH": actionWatch, + "WATCh": actionWatch, + "WATcH": actionWatch, + "WATch": actionWatch, + "WAtCH": actionWatch, + "WAtCh": actionWatch, + "WAtcH": actionWatch, + "WAtch": actionWatch, + "WaTCH": actionWatch, + "WaTCh": actionWatch, + "WaTcH": actionWatch, + "WaTch": actionWatch, + "WatCH": actionWatch, + "WatCh": actionWatch, + "WatcH": actionWatch, + "Watch": actionWatch, + "wATCH": actionWatch, + "wATCh": actionWatch, + "wATcH": actionWatch, + "wATch": actionWatch, + "wAtCH": actionWatch, + "wAtCh": actionWatch, + "wAtcH": actionWatch, + "wAtch": actionWatch, + "waTCH": actionWatch, + "waTCh": actionWatch, + "waTcH": actionWatch, + "waTch": actionWatch, + "watCH": actionWatch, + "watCh": actionWatch, + "watcH": actionWatch, + "watch": actionWatch, } connActions = map[string]*commandAction{ "CLIENT": actionClient, diff --git a/redis/command_action_gen.go b/redis/command_action_gen.go index 71075080..e3fa4b93 100644 --- a/redis/command_action_gen.go +++ b/redis/command_action_gen.go @@ -36,29 +36,54 @@ func newCommandInfo(name, action string) *commandInfo { var activeConnCommands = &commandInfo{ Variable: "activeConnActions", Next: []*commandInfo{ - newCommandInfo("watch", "*state |= stateWatch"), - newCommandInfo("unwatch", "*state &^= stateWatch"), - newCommandInfo("multi", "*state |= stateMulti"), - newCommandInfo("exec", "*state &^= stateWatch|stateMulti"), - newCommandInfo("discard", "*state &^= stateWatch|stateMulti"), - newCommandInfo("psubscribe", "*state |= stateSubscribe"), - newCommandInfo("subscribe", "*state |= stateSubscribe"), - newCommandInfo("monitor", "*state |= stateMonitor"), { Name: "client", Next: []*commandInfo{ + { + Name: "no-evict", + Next: []*commandInfo{ + newCommandInfo("on", "*cs |= stateClientNoEvict"), + newCommandInfo("off", "*cs &^= stateClientNoEvict"), + }, + }, + { + Name: "no-touch", + Next: []*commandInfo{ + newCommandInfo("on", "*cs |= stateClientNoTouch"), + newCommandInfo("off", "*cs &^= stateClientNoTouch"), + }, + }, { Name: "reply", Next: []*commandInfo{ - newCommandInfo("off", "*state |= stateClientReplyOff"), - newCommandInfo("on", "*state &^= stateClientReplyOff|stateClientReplySkip"), - newCommandInfo("skip", `if *state&stateClientReplyOff == 0 { - *state |= stateClientReplySkipNext + newCommandInfo("off", "*cs |= stateClientReplyOff"), + newCommandInfo("on", "*cs &^= stateClientReplyOff|stateClientReplySkipNext|stateClientReplySkip"), + newCommandInfo("skip", `if *cs&stateClientReplyOff == 0 { + *cs |= stateClientReplySkipNext }`), }, }, + { + Name: "tracking", + Next: []*commandInfo{ + newCommandInfo("on", "*cs |= stateClientTracking"), + newCommandInfo("off", "*cs &^= stateClientTracking"), + }, + }, }, }, + newCommandInfo("discard", "*cs &^= stateWatch|stateMulti"), + newCommandInfo("exec", "*cs &^= stateWatch|stateMulti"), + newCommandInfo("monitor", "*cs |= stateMonitor"), + newCommandInfo("multi", "*cs |= stateMulti"), + newCommandInfo("psubscribe", "*cs |= statePsubscribe"), + newCommandInfo("ssubscribe", "*cs |= stateSsubscribe"), + newCommandInfo("subscribe", "*cs |= stateSubscribe"), + newCommandInfo("unwatch", "*cs &^= stateWatch"), + newCommandInfo("readonly", "*cs |= stateReadOnly"), + newCommandInfo("readwrite", "*cs &^= stateReadOnly"), + newCommandInfo("reset", "*cs = 0"), + newCommandInfo("watch", "*cs |= stateWatch"), }, } @@ -113,7 +138,7 @@ var ( {{- end -}} {{- if .Action}} {{.Variable}} = &commandAction{ - Action: func(state *connectionState) { + Action: func(cs *connectionState) { {{.Action}} }, } @@ -146,7 +171,7 @@ func processCommands(parent string, commands []*commandInfo) { for _, ci := range commands { prefix := parent if ci.Variable == "" { - ci.Variable = parent + strings.Title(ci.Name) + ci.Variable = parent + strings.ReplaceAll(strings.Title(ci.Name), "-", "") prefix = ci.Variable } if ci.Next != nil { diff --git a/redis/conn.go b/redis/conn.go index 57380b97..ab12211e 100644 --- a/redis/conn.go +++ b/redis/conn.go @@ -32,6 +32,7 @@ import ( var ( _ ConnWithTimeout = (*conn)(nil) + _ ConnWithContext = (*conn)(nil) ) // conn is the low-level implementation of Conn @@ -683,7 +684,7 @@ func (c *conn) readReply() (interface{}, error) { } func (c *conn) stateUpdate(cmd string, args ...interface{}) { - c.state.update(connActions, cmd, args...) + c.state.update(connActions, true, cmd, args...) } func (c *conn) Send(cmd string, args ...interface{}) error { diff --git a/redis/connection_state.go b/redis/connection_state.go index 35c45ccf..88004723 100644 --- a/redis/connection_state.go +++ b/redis/connection_state.go @@ -1,4 +1,4 @@ -// Copyright 2014 Gary Burd +// Copyright 2024 Steven Hartland // // Licensed under the Apache License, Version 2.0 (the "License"): you may // not use this file except in compliance with the License. You may obtain @@ -14,36 +14,51 @@ package redis -// connectionState represents a connection state. -type connectionState uint8 +// connectionState represents the state of a connection. +type connectionState uint16 +// Connection states flags. +// If you make a change to this you also need to update: +// * Command action generation in command_action_gen.go +// * TestPoolCloseCleanup +// * activeConn.reset() const ( - stateWatch connectionState = 1 << iota - stateMulti - stateSubscribe - stateMonitor - stateClientReplyOff - stateClientReplySkipNext - stateClientReplySkip + stateClientNoEvict connectionState = 1 << iota // Not evictable. + stateClientNoTouch // LRU/LFU stats touch disabled. + stateClientReplyOff // Connection replies aren't being sent. + stateClientReplySkip // Replies aren't expected for this cmd. + stateClientReplySkipNext // Set stateClientReplySkip for next cmd. + stateClientTracking // Key tracking is enabled. + stateMonitor // Monitoring server commands. + stateMulti // Processing a transaction. + statePsubscribe // Potentially subscribed to a pattern. + stateReadOnly // Read only mode. + stateSsubscribe // Potentially subscribed to a shard channel. + stateSubscribe // Potentially subscribed to a channel. + stateWatch // Watching one or more key. ) // commandAction represents an action to be taken when processing a command. type commandAction struct { - Action func(*connectionState) + // Action specifies the action to be taken. + Action func(cs *connectionState) // Next specifies sub actions for given arguments. Next map[string]*commandAction } // update updates the connection state based on the command and arguments if needed. -func (cs *connectionState) update(info map[string]*commandAction, first string, args ...interface{}) { - *cs &^= stateClientReplySkip - if *cs&stateClientReplySkipNext != 0 { - *cs |= stateClientReplySkip - *cs &^= stateClientReplySkipNext +func (cs *connectionState) update(info map[string]*commandAction, first bool, arg0 string, args ...interface{}) { + if first { + if *cs&stateClientReplySkipNext != 0 { + *cs &^= stateClientReplySkipNext + *cs |= stateClientReplySkip + } else { + *cs &^= stateClientReplySkip + } } - ci, ok := info[first] + ci, ok := info[arg0] if !ok { // No match. return @@ -60,12 +75,12 @@ func (cs *connectionState) update(info map[string]*commandAction, first string, return } - first, ok = args[0].(string) + arg0, ok = args[0].(string) if !ok { // No match due type miss-match. return } // Check the next argument. - cs.update(ci.Next, first, args[1:]...) + cs.update(ci.Next, false, arg0, args[1:]...) } diff --git a/redis/connection_state_test.go b/redis/connection_state_test.go index f3a60d01..84c6cdf2 100644 --- a/redis/connection_state_test.go +++ b/redis/connection_state_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -type lookupTest struct { +type stateUpdateTest struct { state connectionState expected connectionState commandName string @@ -16,7 +16,7 @@ type lookupTest struct { info map[string]*commandAction } -func buildLookupTests(tests map[string]lookupTest, root, infos map[string]*commandAction, args ...string) { +func buildStateUpdateTests(tests map[string]stateUpdateTest, root, infos map[string]*commandAction, args ...string) { for cmd, ci := range infos { if cmd != strings.ToLower(cmd) { // Skip non lower case commands as we only need to test one case per action. @@ -25,11 +25,11 @@ func buildLookupTests(tests map[string]lookupTest, root, infos map[string]*comma cmdArgs := append(args, cmd) if ci.Next != nil { - buildLookupTests(tests, root, ci.Next, cmdArgs...) + buildStateUpdateTests(tests, root, ci.Next, cmdArgs...) continue } - t := lookupTest{ + t := stateUpdateTest{ commandName: cmdArgs[0], args: make([]interface{}, len(cmdArgs)-1), info: root, @@ -54,13 +54,13 @@ func buildLookupTests(tests map[string]lookupTest, root, infos map[string]*comma } func TestConnectionStateUpdate(t *testing.T) { - tests := make(map[string]lookupTest) - buildLookupTests(tests, activeConnActions, activeConnActions) - buildLookupTests(tests, connActions, connActions) + tests := make(map[string]stateUpdateTest) + buildStateUpdateTests(tests, activeConnActions, activeConnActions) + buildStateUpdateTests(tests, connActions, connActions) for name, tc := range tests { t.Run(name, func(t *testing.T) { - tc.state.update(tc.info, tc.commandName, tc.args...) + tc.state.update(tc.info, true, tc.commandName, tc.args...) require.Equal(t, tc.expected, tc.state) }) } @@ -70,7 +70,7 @@ func benchmarkStateUpdate(b *testing.B, names ...string) { var state connectionState for i := 0; i < b.N; i++ { for _, cmd := range names { - state.update(activeConnActions, cmd) + state.update(activeConnActions, true, cmd) } } } @@ -193,3 +193,176 @@ func TestClientReply(t *testing.T) { t.Run(name, tc) } } + +// setAllFlags sets all flags in the state. +func setAllFlags(state *connectionState, infos map[string]*commandAction) { + for _, ci := range infos { + if ci.Next != nil { + setAllFlags(state, ci.Next) + } + + if ci.Action != nil { + var check connectionState + ci.Action(&check) + if check != 0 { + *state |= check + } + } + } +} + +// isUnsupported returns true if err is an unknown or disabled command error, false otherwise. +func isUnsupported(err error) bool { + if err != nil { + errStr := strings.ToLower(err.Error()) + if strings.HasPrefix(errStr, "err unknown command") || + strings.HasPrefix(errStr, "err unknown subcommand") || + strings.HasPrefix(errStr, "err this instance has cluster support disabled") { + return true + } + } + + return false +} + +// checkSupported checks if a command is supported and if it is, it +// sends it on c otherwise it removes flags from the expected state. +func checkSupported(t *testing.T, p *Pool, c Conn, expected *connectionState, flags connectionState, cmd string, args ...interface{}) { + t.Helper() + + c2 := p.Get() + defer c2.Close() //nolint: errcheck + + _, err := c2.Do(cmd, args...) + if isUnsupported(err) { + *expected &^= flags + c2.(*activeConn).state &^= flags + return + } + + require.NoError(t, err) + require.NoError(t, c.Send(cmd, args...)) +} + +type closeTest struct { + expected connectionState + commandName string + args []interface{} +} + +// buildCloseTests builds a map of close tests for the given command infos. +func buildCloseTests(tests map[string]closeTest, root, infos map[string]*commandAction, args ...string) { + for cmd, ci := range infos { + if cmd != strings.ToLower(cmd) { + // Skip non lower case commands as we only need to test one case per action. + continue + } + + if cmd == "monitor" { + // MONITOR is tested separately. + continue + } + + cmdArgs := append(args, cmd) + if ci.Next != nil { + buildCloseTests(tests, root, ci.Next, cmdArgs...) + continue + } + + var state connectionState + ci.Action(&state) + if state == 0 { + // Action is a Clear so not needed. + continue + } + + // Action is a Set. + t := closeTest{ + commandName: cmdArgs[0], + args: make([]interface{}, len(cmdArgs)-1), + expected: state, + } + for i, arg := range cmdArgs[1:] { + t.args[i] = arg + } + switch t.commandName { + case "watch", "psubscribe", "subscribe", "ssubscribe": + t.args = append(t.args, "key") + } + + tests[strings.Join(cmdArgs, "-")] = t + } +} + +func TestPoolCloseCleanup(t *testing.T) { + p := &Pool{ + Dial: func() (Conn, error) { + return DialDefaultServer() + }, + } + defer p.Close() + + var expected connectionState + setAllFlags(&expected, activeConnActions) + for _, val := range []string{"off", "skip"} { + t.Run("all-client-reply-"+val, func(t *testing.T) { + c := p.Get() + // Apply all state changing commands. + checkSupported(t, p, c, &expected, stateClientNoEvict, "CLIENT", "NO-EVICT", "ON") + checkSupported(t, p, c, &expected, stateClientNoTouch, "CLIENT", "NO-TOUCH", "ON") + // CLIENT REPLY OFF and CLIENT REPLY SKIP / SKIP NEXT are mutually exclusive. + switch val { + case "off": + checkSupported(t, p, c, &expected, stateClientReplyOff, "CLIENT", "REPLY", "OFF") + checkSupported(t, p, c, &expected, 0, "CLIENT", "REPLY", "SKIP") // Should be ignored. + // CLIENT REPLY SKIP / SKIP NEXT was never set. + expected &^= stateClientReplySkip | stateClientReplySkipNext + case "skip": + checkSupported(t, p, c, &expected, stateClientReplySkip|stateClientReplySkipNext, "CLIENT", "REPLY", "SKIP") + // CLIENT REPLY SKIP / SKIP NEXT should be unset by the next command and CLIENT REPLY OFF was never set. + expected &^= stateClientReplyOff | stateClientReplySkip | stateClientReplySkipNext + } + checkSupported(t, p, c, &expected, stateClientTracking, "CLIENT", "TRACKING", "ON") + require.Zero(t, c.(*activeConn).state&(stateClientReplySkipNext)) // Skip next should have been cleared. + // MONITOR isn't tested as it can't be cleared during close without using RESET + // which isn't possible to use as we can't ensure that the dialled settings such + // as selected database and AUTH are restored. + expected &^= stateMonitor + checkSupported(t, p, c, &expected, stateWatch, "WATCH", "key") // Out of order as WATCH isn't allowed in side a subscriptions. + require.Zero(t, c.(*activeConn).state&(stateClientReplySkip)) // Skip should should have cleared. + checkSupported(t, p, c, &expected, stateMulti, "MULTI") // Out of order as MULTI isn't allowed in side a subscriptions. + checkSupported(t, p, c, &expected, statePsubscribe, "PSUBSCRIBE", "x") + checkSupported(t, p, c, &expected, stateReadOnly, "READONLY") + checkSupported(t, p, c, &expected, stateSsubscribe, "SSUBSCRIBE", "x") + checkSupported(t, p, c, &expected, stateSubscribe, "SUBSCRIBE", "x") + require.Equal(t, expected, c.(*activeConn).state) + require.NoError(t, c.Close()) + require.Zero(t, c.(*activeConn).state) + }) + } + + tests := make(map[string]closeTest) + buildCloseTests(tests, activeConnActions, activeConnActions) + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + c := p.Get() + _, err := c.Do(tc.commandName, tc.args...) + if isUnsupported(err) { + t.Skipf("Command %q not supported", tc.commandName) + } + require.NoError(t, err) + + require.Equal(t, tc.expected, c.(*activeConn).state) + require.NoError(t, c.Close()) + require.Zero(t, c.(*activeConn).state) + }) + } + + t.Run("monitor", func(t *testing.T) { + c := p.Get() + _, err := c.Do("MONITOR") + require.NoError(t, err) + require.ErrorIs(t, c.Close(), errMonitorEnabled) + }) +} diff --git a/redis/pool.go b/redis/pool.go index 113ce76e..07f6436d 100644 --- a/redis/pool.go +++ b/redis/pool.go @@ -20,6 +20,7 @@ import ( "crypto/rand" "crypto/sha1" "errors" + "fmt" "io" "strconv" "sync" @@ -29,6 +30,10 @@ import ( var ( _ ConnWithTimeout = (*activeConn)(nil) _ ConnWithTimeout = (*errorConn)(nil) + _ ConnWithContext = (*activeConn)(nil) + _ ConnWithContext = (*errorConn)(nil) + + errMonitorEnabled = errors.New("redigo: monitor enabled") ) var nowFunc = time.Now // for testing @@ -450,68 +455,141 @@ func initSentinel() { } func (ac *activeConn) stateUpdate(cmd string, args ...interface{}) { - ac.state.update(activeConnActions, cmd, args...) + ac.state.update(activeConnActions, true, cmd, args...) } -func (ac *activeConn) firstError(errs ...error) error { - for _, err := range errs[:len(errs)-1] { - if err != nil { - return err +func (ac *activeConn) Close() error { + pc := ac.pc + if pc == nil { + return nil // Already closed. + } + + defer func() { + ac.pc = nil + }() + + if ac.state != 0 { + // Reset the connection state. + if err := ac.reset(pc.c); err != nil { + // Force close the connection. + ac.p.put(pc, true) //nolint: errcheck + return fmt.Errorf("reset: %w", err) } } - return errs[len(errs)-1] + + // Return the connection to the pool. + return ac.p.put(pc, pc.c.Err() != nil) } -func (ac *activeConn) Close() (err error) { - pc := ac.pc - if pc == nil { - return nil +// reset resets the connection to a clean state. +func (ac *activeConn) reset(conn Conn) error { + if ac.state&stateMonitor != 0 { + // RESET is the only way to clear MONITOR and that resets + // all state including authentication and DB. + // Since we can't detect if AUTH or SELECT commands were + // issued during dial, we have to force close the connection. + return errMonitorEnabled + } + + // DISCARD first to ensure subsequent commands are processed. + if ac.state&stateMulti != 0 { + if err := conn.Send("DISCARD"); err != nil { + return fmt.Errorf("discard: %w", err) + } + + // DISCARD resets WATCH and MULTI. + ac.state &^= stateWatch | stateMulti } - ac.pc = nil - // Return the connection to a clean state if possible. - if ac.state&(stateClientReplyOff|stateClientReplySkip) != 0 { - err = pc.c.Send("CLIENT", "REPLY", "ON") + if ac.state&stateClientNoEvict != 0 { + if err := conn.Send("CLIENT", "NO-EVICT", "OFF"); err != nil { + return fmt.Errorf("client no-evict off: %w", err) + } + ac.state &^= stateClientNoEvict } - if ac.state&stateMulti != 0 { - err = ac.firstError(err, pc.c.Send("DISCARD")) - } else if ac.state&stateWatch != 0 { - err = ac.firstError(err, pc.c.Send("UNWATCH")) + if ac.state&stateClientNoTouch != 0 { + if err := conn.Send("CLIENT", "NO-TOUCH", "OFF"); err != nil { + return fmt.Errorf("client no-touch off: %w", err) + } + ac.state &^= stateClientNoTouch + } + + if ac.state&(stateClientReplyOff|stateClientReplySkipNext|stateClientReplySkip) != 0 { + if err := conn.Send("CLIENT", "REPLY", "ON"); err != nil { + return fmt.Errorf("client reply on: %w", err) + } + ac.state &^= stateClientReplyOff | stateClientReplySkipNext | stateClientReplySkip + } + + if ac.state&stateClientTracking != 0 { + if err := conn.Send("CLIENT", "TRACKING", "OFF"); err != nil { + return fmt.Errorf("client tracking off: %w", err) + } + ac.state &^= stateClientTracking + } + + if ac.state&statePsubscribe != 0 { + if err := conn.Send("PUNSUBSCRIBE"); err != nil { + return fmt.Errorf("punsubscribe: %w", err) + } + } + + if ac.state&stateReadOnly != 0 { + if err := conn.Send("READWRITE"); err != nil { + return fmt.Errorf("readwrite: %w", err) + } + ac.state &^= stateReadOnly + } + + if ac.state&stateSsubscribe != 0 { + if err := conn.Send("SUNSUBSCRIBE"); err != nil { + return fmt.Errorf("sunsubscribe: %w", err) + } } if ac.state&stateSubscribe != 0 { - err = ac.firstError(err, - pc.c.Send("UNSUBSCRIBE"), - pc.c.Send("PUNSUBSCRIBE"), - ) + if err := conn.Send("UNSUBSCRIBE"); err != nil { + return fmt.Errorf("unsubscribe: %w", err) + } + } + + if ac.state&stateWatch != 0 { + if err := conn.Send("UNWATCH"); err != nil { + return fmt.Errorf("unwatch: %w", err) + } + ac.state &^= stateWatch + } + + if ac.state&(stateSubscribe|statePsubscribe|stateSsubscribe) != 0 { + // Drain subscribed messages. // To detect the end of the message stream, ask the server to echo // a sentinel value and read until we see that value. sentinelOnce.Do(initSentinel) - err = ac.firstError(err, - pc.c.Send("ECHO", sentinel), - pc.c.Flush(), - ) + if err := conn.Send("ECHO", sentinel); err != nil { + return fmt.Errorf("echo sentinel: %w", err) + } + + if err := conn.Flush(); err != nil { + return fmt.Errorf("flush: %w", err) + } + for { - p, err2 := pc.c.Receive() - if err2 != nil { - err = ac.firstError(err, err2) - break + p, err := conn.Receive() + if err != nil { + return fmt.Errorf("receive: %w", err) } + if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) { - ac.state &^= stateSubscribe - break + ac.state &^= stateSubscribe | statePsubscribe | stateSsubscribe + return nil // End of message stream. } } } // Ensure any pending reads have completed. - _, err2 := pc.c.Do("") - return ac.firstError( - err, - err2, - ac.p.put(pc, ac.state != 0 || pc.c.Err() != nil), - ) + _, err := conn.Do("") + return err } func (ac *activeConn) Err() error { diff --git a/redis/pool_test.go b/redis/pool_test.go index b8572370..6fb1be18 100644 --- a/redis/pool_test.go +++ b/redis/pool_test.go @@ -484,7 +484,7 @@ func TestPoolPubSubCleanup(t *testing.T) { require.NoError(t, c.Send("SUBSCRIBE", "x")) c.Close() - want := []string{"SUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"} + want := []string{"SUBSCRIBE", "UNSUBSCRIBE", "ECHO"} if !reflect.DeepEqual(d.commands, want) { t.Errorf("got commands %v, want %v", d.commands, want) } @@ -494,7 +494,7 @@ func TestPoolPubSubCleanup(t *testing.T) { require.NoError(t, c.Send("PSUBSCRIBE", "x*")) c.Close() - want = []string{"PSUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"} + want = []string{"PSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"} if !reflect.DeepEqual(d.commands, want) { t.Errorf("got commands %v, want %v", d.commands, want) }