Skip to content

Commit 394a210

Browse files
a1div0vakhov
authored andcommitted
feat: allow running without user-defined stored procedures
(cherry picked from commit 0cff997f74b36a909dbc06badf3dad264e38f819)
1 parent 05faba5 commit 394a210

19 files changed

+950
-722
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
### Added
1111

12+
- Added the ability to run without a user Lua-code.
13+
1214
### Changed
1315

1416
### Fixed

README.md

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ Table below may help you to choose a proper module for your requirements:
3131
| expirationd | Medium (sec) | Yes | Yes | synchronous (fiber with condition) |
3232
| moonwalker | NA | No | Yes | asynchronous (using crontab etc) |
3333

34-
### Prerequisites
34+
## Prerequisites
3535

3636
* Tarantool 1.10+ (`tarantool` package, see [documentation](https://www.tarantool.io/en/download/)).
3737

38-
### Installation
38+
## Installation
3939

4040
You can:
4141

@@ -51,7 +51,7 @@ You can:
5151
luarocks install --local --server=https://rocks.tarantool.org expirationd
5252
```
5353

54-
### Documentation
54+
## Documentation
5555

5656
See API documentation in https://tarantool.github.io/expirationd/
5757

@@ -63,10 +63,43 @@ regular spaces. One can force running task on replica with option `force` in
6363
`start()` module function. The option force let a user control where to start
6464
task processing and where don't.
6565

66-
### Examples
66+
## Default deletion function
67+
68+
Although the expirationd module is quite flexible in its configuration, it includes a
69+
default deletion function. This function is activated if a custom expiration determination
70+
function, `is_expired`, is not specified. The default function deletes all rows that:
71+
* Are older than a specified threshold, defined in `options.args.lifetime_in_seconds`, type - number
72+
* Belong to the specified space
73+
* By checking a specified field, defined in `options.args.time_create_field`, type - string
74+
75+
The specified field can be of several types. The function for determining the current time
76+
depends on the column type. See the table:
77+
78+
| time_create_field type | now |
79+
|------------------------|----------------|
80+
| number | clock.time() |
81+
| integer | clock.time() |
82+
| unsigned | clock.time() |
83+
| datetime | datetime.now() |
84+
85+
## Examples
6786

6887
Simple version:
6988

89+
```lua
90+
expirationd = require("expirationd")
91+
92+
expirationd.start("clean_all", box.space.myspace.id, nil, {
93+
args = {
94+
lifetime_in_seconds = 86400,
95+
time_create_field = 'dt',
96+
},
97+
tuples_per_iteration = 50,
98+
full_scan_time = 3600
99+
})
100+
```
101+
102+
Simple version with user logic:
70103
```lua
71104
box.cfg{}
72105
space = box.space.old

cartridge/roles/expirationd.lua

Lines changed: 10 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
local expirationd = require("expirationd")
2-
local role_name = "expirationd"
3-
local started = require("cartridge.vars").new(role_name)
2+
local expirationd_roles_config = require("expirationd.roles.config")
43

4+
local role_name = "expirationd"
55
local issue_map = {}
66

7-
function _G.expirationd_enable_issue(task_name, message, ...)
7+
function _G.expirationd_enable_issue(task_name, message)
88
issue_map[task_name] = {
99
level = 'warning',
1010
topic = 'expirationd',
11-
message = ('EXPIRATIOND, task name "%s": ' .. message):format(task_name, ...),
11+
message = message,
1212
}
1313
end
1414

@@ -25,224 +25,25 @@ local function get_issues()
2525
return res
2626
end
2727

28-
local function get_param(param_name, value, types)
29-
local types_map = {
30-
b = {type = "boolean", err = "a boolean"},
31-
n = {type = "number", err = "a number"},
32-
s = {type = "string", err = "a string"},
33-
f = {type = "string", err = "a string"},
34-
t = {type = "table", err = "a table"},
35-
any = {err = "any type"},
36-
}
37-
38-
local found = false
39-
for _, t in ipairs(types) do
40-
local type_opts = types_map[t]
41-
if type_opts == nil then
42-
error(role_name .. ": unsupported type option")
43-
end
44-
if not type_opts.type or type(value) == type_opts.type then
45-
if type_opts.transform then
46-
local tmp = type_opts.transform(value)
47-
if tmp then
48-
value = tmp
49-
found = true
50-
break
51-
end
52-
else
53-
found = true
54-
break
55-
end
56-
end
57-
end
58-
59-
if not found then
60-
local err = role_name .. ": " .. param_name .. " must be "
61-
for i, t in ipairs(types) do
62-
err = err .. types_map[t].err
63-
if i ~= #types then
64-
err = err .. " or "
65-
end
66-
end
67-
return false, err
68-
end
69-
return true, value
70-
end
71-
72-
local function get_task_options(opts)
73-
local opts_map = {
74-
args = {"any"},
75-
atomic_iteration = {"b"},
76-
force = {"b"},
77-
force_allow_functional_index = {"b"},
78-
full_scan_delay = {"n"},
79-
full_scan_time = {"n"},
80-
index = {"n", "s"},
81-
iterate_with = {"f"},
82-
iteration_delay = {"n"},
83-
iterator_type = {"n", "s"},
84-
on_full_scan_complete = {"f"},
85-
on_full_scan_error = {"f"},
86-
on_full_scan_start = {"f"},
87-
on_full_scan_success = {"f"},
88-
process_expired_tuple = {"f"},
89-
process_while = {"f"},
90-
start_key = {"f", "t"},
91-
tuples_per_iteration = {"n"},
92-
vinyl_assumed_space_len_factor = {"n"},
93-
vinyl_assumed_space_len = {"n"},
94-
}
95-
if opts == nil then
96-
return
97-
end
98-
99-
for opt, val in pairs(opts) do
100-
if type(opt) ~= "string" then
101-
error(role_name .. ": an option must be a string")
102-
end
103-
if opts_map[opt] == nil then
104-
error(role_name .. ": unsupported option '" .. opt .. "'")
105-
end
106-
local ok, res = get_param("options." .. opt, val, opts_map[opt])
107-
if not ok then
108-
error(res)
109-
end
110-
opts[opt] = res
111-
end
112-
113-
return opts
114-
end
115-
116-
local function get_task_config(task_conf)
117-
-- setmetatable resets __newindex write protection on a copy
118-
local conf = setmetatable(table.deepcopy(task_conf), {})
119-
local params_map = {
120-
space = {required = true, types = {"n", "s"}},
121-
is_expired = {required = true, types = {"f"}},
122-
is_master_only = {required = false, types = {"b"}},
123-
options = {required = false, types = {"t"}},
124-
}
125-
for k, _ in pairs(conf) do
126-
if type(k) ~= "string" then
127-
error(role_name .. ": param must be a string")
128-
end
129-
if params_map[k] == nil then
130-
error(role_name .. ": unsupported param " .. k)
131-
end
132-
end
133-
134-
for param, opts in pairs(params_map) do
135-
if opts.required and conf[param] == nil then
136-
error(role_name .. ": " .. param .. " is required")
137-
end
138-
if conf[param] ~= nil then
139-
local ok, res = get_param(param, conf[param], opts.types)
140-
if not ok then
141-
error(res)
142-
end
143-
conf[param] = res
144-
end
145-
end
146-
147-
conf.options = get_task_options(conf.options)
148-
return conf
149-
end
150-
151-
local function get_cfg(cfg)
152-
local conf = setmetatable(table.deepcopy(cfg), {})
153-
local params_map = {
154-
metrics = {"b"},
155-
}
156-
157-
for k, _ in pairs(conf) do
158-
if type(k) ~= "string" then
159-
error(role_name .. ": config option must be a string")
160-
end
161-
if params_map[k] == nil then
162-
error(role_name .. ": unsupported config option " .. k)
163-
end
164-
end
165-
166-
for param, types in pairs(params_map) do
167-
if conf[param] ~= nil then
168-
local ok, res = get_param(param, conf[param], types)
169-
if not ok then
170-
error(res)
171-
end
172-
end
173-
end
174-
175-
return conf
176-
end
177-
17828
local function init()
17929

18030
end
18131

18232
local function validate_config(conf_new)
18333
local conf = conf_new[role_name] or {}
184-
185-
for task_name, task_conf in pairs(conf) do
186-
local ok, res = get_param("task name", task_name, {"s"})
187-
if not ok then
188-
error(res)
189-
end
190-
local ok, res = get_param("task params", task_conf, {"t"})
191-
if not ok then
192-
error(res)
193-
end
194-
local ok, ret = pcall(get_task_config, task_conf)
195-
if not ok then
196-
if task_name == "cfg" then
197-
get_cfg(task_conf)
198-
else
199-
error(ret)
200-
end
201-
end
34+
local ok, res = pcall(expirationd_roles_config.validate_config, conf)
35+
if not ok then
36+
error(role_name .. ": " .. res)
20237
end
20338

20439
return true
20540
end
20641

20742
local function apply_config(conf_new, opts)
20843
local conf = conf_new[role_name] or {}
209-
210-
-- finishes tasks from an old configuration
211-
for i=#started,1,-1 do
212-
local task_name = started[i]
213-
local ok, _ = pcall(expirationd.task, task_name)
214-
if ok then
215-
if conf[task_name] then
216-
expirationd.task(task_name):stop()
217-
else
218-
expirationd.task(task_name):kill()
219-
end
220-
end
221-
table.remove(started, i)
222-
end
223-
224-
if conf["cfg"] ~= nil then
225-
local ok = pcall(get_task_config, conf["cfg"])
226-
if not ok then
227-
local cfg = get_cfg(conf["cfg"])
228-
expirationd.cfg(cfg)
229-
conf["cfg"] = nil
230-
end
231-
end
232-
233-
for task_name, task_conf in pairs(conf) do
234-
task_conf = get_task_config(task_conf)
235-
236-
local skip = task_conf.is_master_only and not opts.is_master
237-
if not skip then
238-
local task = expirationd.start(task_name, task_conf.space,
239-
task_conf.is_expired,
240-
task_conf.options)
241-
if task == nil then
242-
error(role_name .. ": unable to start task " .. task_name)
243-
end
244-
table.insert(started, task_name)
245-
end
44+
local ok, res = pcall(expirationd_roles_config.apply_config, conf, opts)
45+
if not ok then
46+
error(role_name .. ": " .. res)
24647
end
24748
end
24849

expirationd-scm-1.rockspec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ dependencies = {
1717
build = {
1818
type = "builtin",
1919
modules = {
20+
["cartridge.roles.expirationd"] = "cartridge/roles/expirationd.lua",
21+
22+
["expirationd.roles.config"] = "expirationd/roles/config.lua",
23+
["expirationd.strategy.lifetime_all"] = "expirationd/strategy/lifetime_all.lua",
2024
["expirationd"] = "expirationd/init.lua",
2125
["expirationd.version"] = "expirationd/version.lua",
22-
["cartridge.roles.expirationd"] = "cartridge/roles/expirationd.lua",
26+
2327
["roles.expirationd"] = "roles/expirationd.lua"
2428
}
2529
}

0 commit comments

Comments
 (0)