Add RM_ReplyWithErrorFormat that can support format (#11923)

* Add RM_ReplyWithErrorFormat that can support format

Reply with the error create from a printf format and arguments.

If the error code is already passed in the string 'fmt', the error
code provided is used, otherwise the string "-ERR " for the generic
error code is automatically added.

The usage is, for example:
    RedisModule_ReplyWithErrorFormat(ctx, "An error: %s", "foo");
    RedisModule_ReplyWithErrorFormat(ctx, "-WRONGTYPE Wrong Type: %s", "foo");

The function always returns REDISMODULE_OK.
This commit is contained in:
Binbin 2023-04-12 15:11:29 +08:00 committed by GitHub
parent 997fa41e99
commit bfec2d700b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 2 deletions

View File

@ -2996,6 +2996,32 @@ int RM_ReplyWithError(RedisModuleCtx *ctx, const char *err) {
return REDISMODULE_OK;
}
/* Reply with the error create from a printf format and arguments.
*
* If the error code is already passed in the string 'fmt', the error
* code provided is used, otherwise the string "-ERR " for the generic
* error code is automatically added.
*
* The usage is, for example:
*
* RedisModule_ReplyWithErrorFormat(ctx, "An error: %s", "foo");
*
* RedisModule_ReplyWithErrorFormat(ctx, "-WRONGTYPE Wrong Type: %s", "foo");
*
* The function always returns REDISMODULE_OK.
*/
int RM_ReplyWithErrorFormat(RedisModuleCtx *ctx, const char *fmt, ...) {
client *c = moduleGetReplyClient(ctx);
if (c == NULL) return REDISMODULE_OK;
va_list ap;
va_start(ap, fmt);
addReplyErrorFormatInternal(c, 0, fmt, ap);
va_end(ap);
return REDISMODULE_OK;
}
/* Reply with a simple string (`+... \r\n` in RESP protocol). This replies
* are suitable only when sending a small non-binary string with small
* overhead, like "OK" or similar replies.
@ -13438,6 +13464,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(WrongArity);
REGISTER_API(ReplyWithLongLong);
REGISTER_API(ReplyWithError);
REGISTER_API(ReplyWithErrorFormat);
REGISTER_API(ReplyWithSimpleString);
REGISTER_API(ReplyWithArray);
REGISTER_API(ReplyWithMap);

View File

@ -620,9 +620,9 @@ void addReplyErrorSdsSafe(client *c, sds err) {
addReplyErrorSdsEx(c, err, 0);
}
/* Internal function used by addReplyErrorFormat and addReplyErrorFormatEx.
/* Internal function used by addReplyErrorFormat, addReplyErrorFormatEx and RM_ReplyWithErrorFormat.
* Refer to afterErrorReply for more information about the flags. */
static void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, va_list ap) {
void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, va_list ap) {
va_list cpy;
va_copy(cpy,ap);
sds s = sdscatvprintf(sdsempty(),fmt,cpy);

View File

@ -1014,6 +1014,7 @@ REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringPrintf)(RedisModul
REDISMODULE_API void (*RedisModule_FreeString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR;
REDISMODULE_API const char * (*RedisModule_StringPtrLen)(const RedisModuleString *str, size_t *len) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithError)(RedisModuleCtx *ctx, const char *err) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithErrorFormat)(RedisModuleCtx *ctx, const char *fmt, ...) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithSimpleString)(RedisModuleCtx *ctx, const char *msg) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithArray)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithMap)(RedisModuleCtx *ctx, long len) REDISMODULE_ATTR;
@ -1332,6 +1333,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(WrongArity);
REDISMODULE_GET_API(ReplyWithLongLong);
REDISMODULE_GET_API(ReplyWithError);
REDISMODULE_GET_API(ReplyWithErrorFormat);
REDISMODULE_GET_API(ReplyWithSimpleString);
REDISMODULE_GET_API(ReplyWithArray);
REDISMODULE_GET_API(ReplyWithMap);

View File

@ -2553,6 +2553,7 @@ void setDeferredReplyBulkSds(client *c, void *node, sds s);
void addReplyErrorObject(client *c, robj *err);
void addReplyOrErrorObject(client *c, robj *reply);
void afterErrorReply(client *c, const char *s, size_t len, int flags);
void addReplyErrorFormatInternal(client *c, int flags, const char *fmt, va_list ap);
void addReplyErrorSdsEx(client *c, sds err, int flags);
void addReplyErrorSds(client *c, sds err);
void addReplyErrorSdsSafe(client *c, sds err);

View File

@ -156,6 +156,14 @@ int rw_error(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
return RedisModule_ReplyWithError(ctx, "An error");
}
int rw_error_format(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 3) return RedisModule_WrongArity(ctx);
return RedisModule_ReplyWithErrorFormat(ctx,
RedisModule_StringPtrLen(argv[1], NULL),
RedisModule_StringPtrLen(argv[2], NULL));
}
int rw_verbatim(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc != 2) return RedisModule_WrongArity(ctx);
@ -197,6 +205,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"rw.error",rw_error,"",0,0,0) != REDISMODULE_OK)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"rw.error_format",rw_error_format,"",0,0,0) != REDISMODULE_OK)
return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"rw.verbatim",rw_verbatim,"",0,0,0) != REDISMODULE_OK)
return REDISMODULE_ERR;

View File

@ -126,6 +126,17 @@ start_server {tags {"modules"}} {
assert_match "An error" $e
}
test "RESP$proto: RM_ReplyWithErrorFormat: error format reply" {
catch {r rw.error_format "An error: %s" foo} e
assert_match "ERR An error: foo" $e
catch {r rw.error_format "-ERR An error: %s" foo2} e
assert_match "ERR An error: foo2" $e
catch {r rw.error_format "-WRONGTYPE A type error: %s" foo3} e
assert_match "WRONGTYPE A type error: foo3" $e
}
r hello 2
}