@@ -1999,18 +1999,18 @@ redis_xread_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
19991999 return -1 ;
20002000}
20012001
2002- /* This helper function does that actual XCLAIM response handling, which can be used by both
2003- * Redis and RedisCluster. Note that XCLAIM is somewhat unique in that its reply type depends
2004- * on whether or not it was called with the JUSTID option */
2005- PHP_REDIS_API int
2006- redis_read_xclaim_response (RedisSock * redis_sock , int count , zval * rv ) {
2002+ /* A helper method to read X[AUTO]CLAIM messages into an array. */
2003+ static int
2004+ redis_read_xclaim_ids (RedisSock * redis_sock , int count , zval * rv ) {
20072005 zval z_msg ;
20082006 REDIS_REPLY_TYPE type ;
20092007 char * id = NULL ;
20102008 int i , fields , idlen ;
20112009 long li ;
20122010
20132011 for (i = 0 ; i < count ; i ++ ) {
2012+ id = NULL ;
2013+
20142014 /* Consume inner reply type */
20152015 if (redis_read_reply_type (redis_sock , & type , & li ) < 0 ||
20162016 (type != TYPE_BULK && type != TYPE_MULTIBULK ) ||
@@ -2043,29 +2043,88 @@ redis_read_xclaim_response(RedisSock *redis_sock, int count, zval *rv) {
20432043 return 0 ;
20442044}
20452045
2046+ /* Read an X[AUTO]CLAIM reply having already consumed the reply-type byte. */
2047+ PHP_REDIS_API int
2048+ redis_read_xclaim_reply (RedisSock * redis_sock , int count , int is_xautoclaim , zval * rv ) {
2049+ REDIS_REPLY_TYPE type ;
2050+ zval z_msgs = {0 };
2051+ char * id = NULL ;
2052+ long id_len = 0 ;
2053+ int messages ;
2054+
2055+ ZEND_ASSERT (!is_xautoclaim || count == 3 );
2056+
2057+ ZVAL_UNDEF (rv );
2058+
2059+ /* If this is XAUTOCLAIM consume the BULK ID and then the actual number of IDs.
2060+ * Otherwise, our 'count' argument is the number of IDs. */
2061+ if (is_xautoclaim ) {
2062+ if (redis_read_reply_type (redis_sock , & type , & id_len ) < 0 || type != TYPE_BULK )
2063+ goto failure ;
2064+ if ((id = redis_sock_read_bulk_reply (redis_sock , id_len )) == NULL )
2065+ goto failure ;
2066+ if (read_mbulk_header (redis_sock , & messages ) < 0 )
2067+ goto failure ;
2068+ } else {
2069+ messages = count ;
2070+ }
2071+
2072+ array_init (& z_msgs );
2073+
2074+ if (redis_read_xclaim_ids (redis_sock , messages , & z_msgs ) < 0 )
2075+ goto failure ;
2076+
2077+ /* If XAUTOCLAIM we now need to consume the final array of message IDs */
2078+ if (is_xautoclaim ) {
2079+ zval z_deleted = {0 };
2080+
2081+ if (redis_sock_read_multibulk_reply_zval (redis_sock , & z_deleted ) == NULL )
2082+ goto failure ;
2083+
2084+ array_init (rv );
2085+
2086+ // Package up ID, message, and deleted messages in our reply
2087+ add_next_index_stringl (rv , id , id_len );
2088+ add_next_index_zval (rv , & z_msgs );
2089+ add_next_index_zval (rv , & z_deleted );
2090+
2091+ efree (id );
2092+ } else {
2093+ // We just want the messages
2094+ ZVAL_COPY_VALUE (rv , & z_msgs );
2095+ }
2096+
2097+ return 0 ;
2098+
2099+ failure :
2100+ zval_dtor (& z_msgs );
2101+ zval_dtor (rv );
2102+ if (id ) efree (id );
2103+
2104+ return -1 ;
2105+ }
2106+
20462107PHP_REDIS_API int
20472108redis_xclaim_reply (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
20482109 zval * z_tab , void * ctx )
20492110{
2050- zval z_ret ;
2051- int messages ;
2111+ zval z_ret = { 0 } ;
2112+ int count ;
20522113
2053- /* All XCLAIM responses start multibulk */
2054- if (read_mbulk_header (redis_sock , & messages ) < 0 )
2055- goto failure ;
2114+ ZEND_ASSERT (ctx == NULL || ctx == PHPREDIS_CTX_PTR );
20562115
2057- array_init (& z_ret );
2116+ if (read_mbulk_header (redis_sock , & count ) < 0 )
2117+ goto failure ;
20582118
2059- if (redis_read_xclaim_response (redis_sock , messages , & z_ret ) < 0 ) {
2060- zval_dtor (& z_ret );
2119+ if (redis_read_xclaim_reply (redis_sock , count , ctx == PHPREDIS_CTX_PTR , & z_ret ) < 0 )
20612120 goto failure ;
2062- }
20632121
20642122 if (IS_ATOMIC (redis_sock )) {
20652123 RETVAL_ZVAL (& z_ret , 0 , 1 );
20662124 } else {
20672125 add_next_index_zval (z_tab , & z_ret );
20682126 }
2127+
20692128 return 0 ;
20702129
20712130failure :
0 commit comments