XINFO CONSUMERS * XINFO GROUPS * XINFO STREAM [FULL [COUNT ]] * XINFO HELP. */
| 3488 | * XINFO STREAM <key> [FULL [COUNT <count>]] |
| 3489 | * XINFO HELP. */ |
| 3490 | void xinfoCommand(client *c) { |
| 3491 | stream *s = NULL; |
| 3492 | char *opt; |
| 3493 | robj *key; |
| 3494 | |
| 3495 | /* HELP is special. Handle it ASAP. */ |
| 3496 | if (!strcasecmp(szFromObj(c->argv[1]),"HELP")) { |
| 3497 | const char *help[] = { |
| 3498 | "CONSUMERS <key> <groupname>", |
| 3499 | " Show consumers of <groupname>.", |
| 3500 | "GROUPS <key>", |
| 3501 | " Show the stream consumer groups.", |
| 3502 | "STREAM <key> [FULL [COUNT <count>]", |
| 3503 | " Show information about the stream.", |
| 3504 | NULL |
| 3505 | }; |
| 3506 | addReplyHelp(c, help); |
| 3507 | return; |
| 3508 | } else if (c->argc < 3) { |
| 3509 | addReplySubcommandSyntaxError(c); |
| 3510 | return; |
| 3511 | } |
| 3512 | |
| 3513 | /* With the exception of HELP handled before any other sub commands, all |
| 3514 | * the ones are in the form of "<subcommand> <key>". */ |
| 3515 | opt = szFromObj(c->argv[1]); |
| 3516 | key = c->argv[2]; |
| 3517 | |
| 3518 | /* Lookup the key now, this is common for all the subcommands but HELP. */ |
| 3519 | robj_roptr o = lookupKeyReadOrReply(c,key,shared.nokeyerr); |
| 3520 | if (o == nullptr || checkType(c,o,OBJ_STREAM)) return; |
| 3521 | s = (stream*)ptrFromObj(o); |
| 3522 | |
| 3523 | /* Dispatch the different subcommands. */ |
| 3524 | if (!strcasecmp(opt,"CONSUMERS") && c->argc == 4) { |
| 3525 | /* XINFO CONSUMERS <key> <group>. */ |
| 3526 | streamCG *cg = streamLookupCG(s,szFromObj(c->argv[3])); |
| 3527 | if (cg == NULL) { |
| 3528 | addReplyErrorFormat(c, "-NOGROUP No such consumer group '%s' " |
| 3529 | "for key name '%s'", |
| 3530 | (char*)ptrFromObj(c->argv[3]), (char*)ptrFromObj(key)); |
| 3531 | return; |
| 3532 | } |
| 3533 | |
| 3534 | addReplyArrayLen(c,raxSize(cg->consumers)); |
| 3535 | raxIterator ri; |
| 3536 | raxStart(&ri,cg->consumers); |
| 3537 | raxSeek(&ri,"^",NULL,0); |
| 3538 | mstime_t now = mstime(); |
| 3539 | while(raxNext(&ri)) { |
| 3540 | streamConsumer *consumer = (streamConsumer*)ri.data; |
| 3541 | mstime_t idle = now - consumer->seen_time; |
| 3542 | if (idle < 0) idle = 0; |
| 3543 | |
| 3544 | addReplyMapLen(c,3); |
| 3545 | addReplyBulkCString(c,"name"); |
| 3546 | addReplyBulkCBuffer(c,consumer->name,sdslen(consumer->name)); |
| 3547 | addReplyBulkCString(c,"pending"); |
nothing calls this directly
no test coverage detected