mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Redis: Handle other errors from requests, fix KEY_EXISTS for put operations
This commit is contained in:
parent
3d7fcfb428
commit
855c530b64
4 changed files with 67 additions and 44 deletions
|
@ -60,7 +60,7 @@ void redisZADD(redisAsyncContext* ctx, void* reply, void* privdata) {
|
|||
auto t = Tracer("generic");
|
||||
auto backend = static_cast<zeek::storage::backend::redis::Redis*>(ctx->data);
|
||||
|
||||
// We don't care about the reply from the ZADD, m1ostly because blocking to poll
|
||||
// We don't care about the reply from the ZADD, mostly because blocking to poll
|
||||
// for it adds a bunch of complication to DoPut() with having to handle the
|
||||
// reply from SET first.
|
||||
backend->HandleGeneric(nullptr);
|
||||
|
@ -415,9 +415,12 @@ void Redis::HandlePutResult(redisReply* reply, ResultCallback* callback) {
|
|||
if ( ! connected )
|
||||
res = {ReturnCode::NOT_CONNECTED};
|
||||
else if ( ! reply )
|
||||
res = {ReturnCode::OPERATION_FAILED, "Async put operation returned null reply"};
|
||||
else if ( reply && reply->type == REDIS_REPLY_ERROR )
|
||||
res = {ReturnCode::OPERATION_FAILED, util::fmt("Async put operation failed: %s", reply->str)};
|
||||
res = {ReturnCode::OPERATION_FAILED, "put operation returned null reply"};
|
||||
else if ( reply->type == REDIS_REPLY_NIL )
|
||||
// For a SET operation, a NIL reply indicates a conflict with the NX flag.
|
||||
res = {ReturnCode::KEY_EXISTS};
|
||||
else if ( reply->type == REDIS_REPLY_ERROR )
|
||||
res = ParseReplyError("put", reply->str);
|
||||
|
||||
freeReplyObject(reply);
|
||||
CompleteCallback(callback, res);
|
||||
|
@ -429,8 +432,19 @@ void Redis::HandleGetResult(redisReply* reply, ResultCallback* callback) {
|
|||
OperationResult res;
|
||||
if ( ! connected )
|
||||
res = {ReturnCode::NOT_CONNECTED};
|
||||
if ( ! reply )
|
||||
res = {ReturnCode::OPERATION_FAILED, "get operation returned null reply"};
|
||||
else if ( reply->type == REDIS_REPLY_NIL )
|
||||
res = {ReturnCode::KEY_NOT_FOUND};
|
||||
else if ( reply->type == REDIS_REPLY_ERROR )
|
||||
res = ParseReplyError("get", reply->str);
|
||||
else {
|
||||
auto val = zeek::detail::ValFromJSON(reply->str, val_type, Func::nil);
|
||||
if ( std::holds_alternative<ValPtr>(val) )
|
||||
res = {ReturnCode::SUCCESS, "", std::get<ValPtr>(val)};
|
||||
else
|
||||
res = ParseGetReply(reply);
|
||||
res = {ReturnCode::OPERATION_FAILED, std::get<std::string>(val)};
|
||||
}
|
||||
|
||||
freeReplyObject(reply);
|
||||
CompleteCallback(callback, res);
|
||||
|
@ -444,9 +458,9 @@ void Redis::HandleEraseResult(redisReply* reply, ResultCallback* callback) {
|
|||
if ( ! connected )
|
||||
res = {ReturnCode::NOT_CONNECTED};
|
||||
else if ( ! reply )
|
||||
res = {ReturnCode::OPERATION_FAILED, "Async erase operation returned null reply"};
|
||||
else if ( reply && reply->type == REDIS_REPLY_ERROR )
|
||||
res = {ReturnCode::OPERATION_FAILED, util::fmt("Async erase operation failed: %s", reply->str)};
|
||||
res = {ReturnCode::OPERATION_FAILED, "erase operation returned null reply"};
|
||||
else if ( reply->type == REDIS_REPLY_ERROR )
|
||||
res = ParseReplyError("erase", reply->str);
|
||||
|
||||
freeReplyObject(reply);
|
||||
CompleteCallback(callback, res);
|
||||
|
@ -505,22 +519,14 @@ void Redis::ProcessFd(int fd, int flags) {
|
|||
redisAsyncHandleWrite(async_ctx);
|
||||
}
|
||||
|
||||
OperationResult Redis::ParseGetReply(redisReply* reply) const {
|
||||
OperationResult res;
|
||||
|
||||
if ( ! reply )
|
||||
res = {ReturnCode::OPERATION_FAILED, "GET returned null reply"};
|
||||
else if ( ! reply->str )
|
||||
res = {ReturnCode::KEY_NOT_FOUND};
|
||||
else {
|
||||
auto val = zeek::detail::ValFromJSON(reply->str, val_type, Func::nil);
|
||||
if ( std::holds_alternative<ValPtr>(val) )
|
||||
res = {ReturnCode::SUCCESS, "", std::get<ValPtr>(val)};
|
||||
OperationResult Redis::ParseReplyError(std::string_view op_str, std::string_view reply_err_str) const {
|
||||
if ( async_ctx->err == REDIS_ERR_TIMEOUT )
|
||||
return {ReturnCode::TIMEOUT};
|
||||
else if ( async_ctx->err == REDIS_ERR_IO )
|
||||
return {ReturnCode::OPERATION_FAILED, util::fmt("%s operation IO error: %s", op_str.data(), strerror(errno))};
|
||||
else
|
||||
res = {ReturnCode::OPERATION_FAILED, std::get<std::string>(val)};
|
||||
}
|
||||
|
||||
return res;
|
||||
return {ReturnCode::OPERATION_FAILED,
|
||||
util::fmt("%s operation failed: %s", op_str.data(), reply_err_str.data())};
|
||||
}
|
||||
|
||||
void Redis::DoPoll() {
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
void DoExpire(double current_network_time) override;
|
||||
void DoPoll() override;
|
||||
|
||||
OperationResult ParseGetReply(redisReply* reply) const;
|
||||
OperationResult ParseReplyError(std::string_view op_str, std::string_view reply_err_str) const;
|
||||
|
||||
redisAsyncContext* async_ctx = nullptr;
|
||||
|
||||
|
|
|
@ -3,8 +3,11 @@ open_result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=<opaque of
|
|||
put result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=<uninitialized>]
|
||||
get result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=value1234]
|
||||
get result same as inserted, T
|
||||
overwrite put result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=<uninitialized>]
|
||||
get result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=value5678]
|
||||
get result same as inserted, T
|
||||
put result, [code=Storage::KEY_EXISTS, error_str=<uninitialized>, value=<uninitialized>]
|
||||
get result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=value1234]
|
||||
get result same as originally inserted, T
|
||||
put result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=<uninitialized>]
|
||||
get result, [code=Storage::SUCCESS, error_str=<uninitialized>, value=value2345]
|
||||
get result same as overwritten, T
|
||||
Storage::backend_opened, Storage::REDIS, [redis=[server_host=127.0.0.1, server_port=xxxx/tcp, server_unix_socket=<uninitialized>, key_prefix=testing]]
|
||||
Storage::backend_lost, Storage::REDIS, [redis=[server_host=127.0.0.1, server_port=xxxx/tcp, server_unix_socket=<uninitialized>, key_prefix=testing]], Client disconnected
|
||||
|
|
|
@ -29,28 +29,42 @@ event zeek_init()
|
|||
|
||||
local key = "key1234";
|
||||
local value = "value1234";
|
||||
local value2 = "value2345";
|
||||
|
||||
local open_res = Storage::Sync::open_backend(Storage::REDIS, opts, string, string);
|
||||
print "open_result", open_res;
|
||||
local res = Storage::Sync::open_backend(Storage::REDIS, opts, string, string);
|
||||
print "open_result", res;
|
||||
|
||||
local b = open_res$value;
|
||||
local b = res$value;
|
||||
|
||||
local res = Storage::Sync::put(b, [ $key=key, $value=value ]);
|
||||
# Put a first value. This should return Storage::SUCCESS.
|
||||
res = Storage::Sync::put(b, [$key=key, $value=value]);
|
||||
print "put result", res;
|
||||
|
||||
local res2 = Storage::Sync::get(b, key);
|
||||
print "get result", res2;
|
||||
if ( res2$code == Storage::SUCCESS && res2?$value )
|
||||
print "get result same as inserted", value == ( res2$value as string );
|
||||
# Get the first value, validate that it's what we inserted.
|
||||
res = Storage::Sync::get(b, key);
|
||||
print "get result", res;
|
||||
if ( res$code == Storage::SUCCESS && res?$value )
|
||||
print "get result same as inserted", value == (res$value as string);
|
||||
|
||||
local value2 = "value5678";
|
||||
# This will return a Storage::KEY_EXISTS since we don't want overwriting.
|
||||
res = Storage::Sync::put(b, [$key=key, $value=value2, $overwrite=F]);
|
||||
print "put result", res;
|
||||
|
||||
# Verify that the overwrite didn't actually happen.
|
||||
res = Storage::Sync::get(b, key);
|
||||
print "get result", res;
|
||||
if ( res$code == Storage::SUCCESS && res?$value )
|
||||
print "get result same as originally inserted", value == (res$value as string);
|
||||
|
||||
# This will return a Storage::SUCESSS since we're asking for an overwrite.
|
||||
res = Storage::Sync::put(b, [$key=key, $value=value2, $overwrite=T]);
|
||||
print "overwrite put result", res;
|
||||
print "put result", res;
|
||||
|
||||
res2 = Storage::Sync::get(b, key);
|
||||
print "get result", res2;
|
||||
if ( res2$code == Storage::SUCCESS && res2?$value )
|
||||
print "get result same as inserted", value2 == ( res2$value as string );
|
||||
# Verify that the overwrite happened.
|
||||
res = Storage::Sync::get(b, key);
|
||||
print "get result", res;
|
||||
if ( res$code == Storage::SUCCESS && res?$value )
|
||||
print "get result same as overwritten", value2 == (res$value as string);
|
||||
|
||||
Storage::Sync::close_backend(b);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue