diff --git a/src/networking.c b/src/networking.c index ef1210b99..4f72e144a 100644 --- a/src/networking.c +++ b/src/networking.c @@ -2384,9 +2384,10 @@ void clientCommand(client *c) { "REPLY (on|off|skip) -- Control the replies sent to the current connection.", "SETNAME -- Assign the name to the current connection.", "UNBLOCK [TIMEOUT|ERROR] -- Unblock the specified blocked client.", -"TRACKING (on|off) [REDIRECT ] [BCAST] [PREFIX first] [PREFIX second] [OPTIN] [OPTOUT]... -- Enable client keys tracking for client side caching.", +"TRACKING (on|off) [REDIRECT ] [BCAST] [PREFIX first] [PREFIX second] [OPTIN] [OPTOUT] [NOLOOP]... -- Enable client keys tracking for client side caching.", "CACHING (yes|no) -- Enable/Disable tracking of the keys for next command in OPTIN/OPTOUT mode.", "GETREDIR -- Return the client ID we are redirecting to when tracking is enabled.", +"TRACKINGINFO -- Return information about current client's tracking status.", NULL }; addReplyHelp(c, help); @@ -2753,6 +2754,67 @@ NULL } else { addReplyLongLong(c,-1); } + } else if (!strcasecmp(c->argv[1]->ptr,"trackinginfo") && c->argc == 2) { + addReplyMapLen(c,3); + + /* Flags */ + addReplyBulkCString(c,"flags"); + void *arraylen_ptr = addReplyDeferredLen(c); + int numflags = 0; + addReplyBulkCString(c,c->flags & CLIENT_TRACKING ? "on" : "off"); + numflags++; + if (c->flags & CLIENT_TRACKING_BCAST) { + addReplyBulkCString(c,"bcast"); + numflags++; + } + if (c->flags & CLIENT_TRACKING_OPTIN) { + addReplyBulkCString(c,"optin"); + numflags++; + if (c->flags & CLIENT_TRACKING_CACHING) { + addReplyBulkCString(c,"caching-yes"); + numflags++; + } + } + if (c->flags & CLIENT_TRACKING_OPTOUT) { + addReplyBulkCString(c,"optout"); + numflags++; + if (c->flags & CLIENT_TRACKING_CACHING) { + addReplyBulkCString(c,"caching-no"); + numflags++; + } + } + if (c->flags & CLIENT_TRACKING_NOLOOP) { + addReplyBulkCString(c,"noloop"); + numflags++; + } + if (c->flags & CLIENT_TRACKING_BROKEN_REDIR) { + addReplyBulkCString(c,"broken_redirect"); + numflags++; + } + setDeferredSetLen(c,arraylen_ptr,numflags); + + /* Redirect */ + addReplyBulkCString(c,"redirect"); + if (c->flags & CLIENT_TRACKING) { + addReplyLongLong(c,c->client_tracking_redirection); + } else { + addReplyLongLong(c,-1); + } + + /* Prefixes */ + addReplyBulkCString(c,"prefixes"); + if (c->client_tracking_prefixes) { + addReplyArrayLen(c,raxSize(c->client_tracking_prefixes)); + raxIterator ri; + raxStart(&ri,c->client_tracking_prefixes); + raxSeek(&ri,"^",NULL,0); + while(raxNext(&ri)) { + addReplyBulkCBuffer(c,ri.key,ri.key_len); + } + raxStop(&ri); + } else { + addReplyArrayLen(c,0); + } } else { addReplyErrorFormat(c, "Unknown subcommand or wrong number of arguments for '%s'. Try CLIENT HELP", (char*)c->argv[1]->ptr); } diff --git a/tests/unit/tracking.tcl b/tests/unit/tracking.tcl index fc2800791..555c4e75e 100644 --- a/tests/unit/tracking.tcl +++ b/tests/unit/tracking.tcl @@ -398,6 +398,85 @@ start_server {tags {"tracking"}} { assert {$total_prefixes == 1} } + test {CLIENT TRACKINGINFO provides reasonable results when tracking off} { + r CLIENT TRACKING off + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {off} $flags + set redirect [dict get $res redirect] + assert_equal {-1} $redirect + set prefixes [dict get $res prefixes] + assert_equal {} $prefixes + } + + test {CLIENT TRACKINGINFO provides reasonable results when tracking on} { + r CLIENT TRACKING on + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on} $flags + set redirect [dict get $res redirect] + assert_equal {0} $redirect + set prefixes [dict get $res prefixes] + assert_equal {} $prefixes + } + + test {CLIENT TRACKINGINFO provides reasonable results when tracking on with options} { + r CLIENT TRACKING on REDIRECT $redir_id noloop + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on noloop} $flags + set redirect [dict get $res redirect] + assert_equal $redir_id $redirect + set prefixes [dict get $res prefixes] + assert_equal {} $prefixes + } + + test {CLIENT TRACKINGINFO provides reasonable results when tracking optin} { + r CLIENT TRACKING off + r CLIENT TRACKING on optin + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on optin} $flags + set redirect [dict get $res redirect] + assert_equal {0} $redirect + set prefixes [dict get $res prefixes] + assert_equal {} $prefixes + + r CLIENT CACHING yes + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on optin caching-yes} $flags + } + + test {CLIENT TRACKINGINFO provides reasonable results when tracking optout} { + r CLIENT TRACKING off + r CLIENT TRACKING on optout + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on optout} $flags + set redirect [dict get $res redirect] + assert_equal {0} $redirect + set prefixes [dict get $res prefixes] + assert_equal {} $prefixes + + r CLIENT CACHING no + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on optout caching-no} $flags + } + + test {CLIENT TRACKINGINFO provides reasonable results when tracking bcast mode} { + r CLIENT TRACKING off + r CLIENT TRACKING on BCAST PREFIX foo PREFIX bar + set res [r client trackinginfo] + set flags [dict get $res flags] + assert_equal {on bcast} $flags + set redirect [dict get $res redirect] + assert_equal {0} $redirect + set prefixes [lsort [dict get $res prefixes]] + assert_equal {bar foo} $prefixes + } + $rd_redirection close $rd close }