Action Engine
Loading...
Searching...
No Matches
pop.lua.h
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ACTIONENGINE_REDIS_CHUNK_STORE_OPS_POP_LUA_H_
16#define ACTIONENGINE_REDIS_CHUNK_STORE_OPS_POP_LUA_H_
17
18#include <string_view>
19
20#include "actionengine/redis/chunk_store_ops/unindent.h"
21
22namespace act::redis {
23
24const std::array<std::string, 3> kPopScriptKeys = {"{}:s", "{}:seq_to_id",
25 "{}:offset_to_seq"};
26
27constexpr std::string_view kPopScriptCode = R"(
28 -- pop.lua
29 -- KEYS[1]: <id>:s
30 -- KEYS[2]: <id>:seq_to_id
31 -- KEYS[3]: <id>:offset_to_seq
32 -- ARGV[1]: seq_to_pop
33
34 local seq_to_pop = ARGV[1]
35
36 local stream_key = KEYS[1]
37 local seq_to_id_key = KEYS[2]
38 local offset_to_seq_key = KEYS[3]
39
40 -- 1. Find the element's stream ID. If it doesn't exist, return nil.
41 local id_in_stream = redis.call('HGET', seq_to_id_key, seq_to_pop)
42 if not id_in_stream then
43 return nil
44 end
45
46 -- 2. Get the element's data before deleting.
47 local stream_reply = redis.call('XRANGE', stream_key, id_in_stream, id_in_stream, 'COUNT', 1)
48 if #stream_reply == 0 then
49 redis.call('HDEL', seq_to_id_key, seq_to_pop) -- Cleanup dangling ref
50 return nil
51 end
52
53 local fields = stream_reply[1][2]
54 local data_to_return = nil
55 for i = 1, #fields, 2 do
56 if fields[i] == 'data' then
57 data_to_return = fields[i+1]
58 break
59 end
60 end
61
62 -- 3. Perform the deletions. There is no shifting.
63 redis.call('XDEL', stream_key, id_in_stream)
64 redis.call('HDEL', seq_to_id_key, seq_to_pop)
65 redis.call('ZREM', offset_to_seq_key, seq_to_pop) -- This leaves a gap in offsets.
66
67 -- 4. Return the retrieved data.
68 return data_to_return
69)"_unindent;
70
71} // namespace act::redis
72
73#endif // ACTIONENGINE_REDIS_CHUNK_STORE_OPS_POP_LUA_H_