Skip to content

Commit 9954618

Browse files
authored
Merge branch 'master' into ligurio/gh-166-sharding-keys
2 parents 187c7e5 + 8ef4099 commit 9954618

File tree

5 files changed

+191
-0
lines changed

5 files changed

+191
-0
lines changed

CHANGELOG.md

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

88
## [Unreleased]
99

10+
### Added
11+
12+
* `crud.len()` function to calculate the number of tuples
13+
in the space for memtx engine and calculate the maximum
14+
approximate number of tuples in the space for vinyl engine.
15+
1016
## [0.8.0] - 02-07-21
1117

1218
### Fixed

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,54 @@ crud.truncate('customers', {timeout = 2})
487487
...
488488
```
489489

490+
### Len
491+
492+
```lua
493+
-- Calculates the number of tuples in the space for memtx engine
494+
-- Calculates the maximum approximate number of tuples in the space for vinyl engine
495+
local result, err = crud.len(space_name, opts)
496+
```
497+
498+
where:
499+
500+
* `space_name` (`string|number`) - name of the space as well
501+
as numerical id of the space
502+
* `opts`:
503+
* `timeout` (`?number`) - `vshard.call` timeout (in seconds)
504+
505+
Returns number or nil with error.
506+
507+
**Example:**
508+
509+
Using `memtx`:
510+
511+
```lua
512+
#crud.select('customers')
513+
---
514+
- 5
515+
...
516+
crud.len('customers', {timeout = 2})
517+
---
518+
- 5
519+
...
520+
```
521+
522+
Using `vinyl`:
523+
524+
```lua
525+
crud.len('customers')
526+
---
527+
- 0
528+
...
529+
crud.delete('customers', 1)
530+
---
531+
...
532+
crud.len('customers')
533+
---
534+
- 1
535+
...
536+
```
537+
490538
## Cartridge roles
491539

492540
`cartridge.roles.crud-storage` is a Tarantool Cartridge role that depends on the

crud.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ local upsert = require('crud.upsert')
1010
local delete = require('crud.delete')
1111
local select = require('crud.select')
1212
local truncate = require('crud.truncate')
13+
local len = require('crud.len')
1314
local borders = require('crud.borders')
1415
local utils = require('crud.common.utils')
1516

@@ -70,6 +71,10 @@ crud.unflatten_rows = utils.unflatten_rows
7071
-- @function truncate
7172
crud.truncate = truncate.call
7273

74+
-- @refer len.call
75+
-- @function len
76+
crud.len = len.call
77+
7378
-- @refer borders.min
7479
-- @function min
7580
crud.min = borders.min
@@ -106,6 +111,7 @@ function crud.init_storage()
106111
delete.init()
107112
select.init()
108113
truncate.init()
114+
len.init()
109115
borders.init()
110116
end
111117

crud/len.lua

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
local checks = require('checks')
2+
local errors = require('errors')
3+
local vshard = require('vshard')
4+
5+
local utils = require('crud.common.utils')
6+
local dev_checks = require('crud.common.dev_checks')
7+
8+
local LenError = errors.new_class('LenError', {capture_stack = false})
9+
10+
local len = {}
11+
12+
local LEN_FUNC_NAME = '_crud.len_on_storage'
13+
14+
local function len_on_storage(space_name)
15+
dev_checks('string|number')
16+
17+
return box.space[space_name]:len()
18+
end
19+
20+
function len.init()
21+
_G._crud.len_on_storage = len_on_storage
22+
end
23+
24+
--- Calculates the number of tuples in the space for memtx engine
25+
--- Calculates the maximum approximate number of tuples in the space for vinyl engine
26+
--
27+
-- @function call
28+
--
29+
-- @param string|number space_name
30+
-- A space name as well as numerical id
31+
--
32+
-- @tparam ?number opts.timeout
33+
-- Function call timeout
34+
--
35+
-- @return[1] number
36+
-- @treturn[2] nil
37+
-- @treturn[2] table Error description
38+
--
39+
function len.call(space_name, opts)
40+
checks('string|number', {
41+
timeout = '?number',
42+
})
43+
44+
opts = opts or {}
45+
46+
local space = utils.get_space(space_name, vshard.router.routeall())
47+
if space == nil then
48+
return nil, LenError:new("Space %q doesn't exist", space_name)
49+
end
50+
51+
local results, err = vshard.router.map_callrw(LEN_FUNC_NAME, {space_name}, opts)
52+
53+
if err ~= nil then
54+
return nil, LenError:new("Failed to call len on storage-side: %s", err)
55+
end
56+
57+
local total_len = 0
58+
for _, replicaset_results in pairs(results) do
59+
if replicaset_results[1] ~= nil then
60+
total_len = total_len + replicaset_results[1]
61+
end
62+
end
63+
64+
return total_len
65+
end
66+
67+
return len

test/integration/len_test.lua

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
local fio = require('fio')
2+
3+
local t = require('luatest')
4+
5+
local helpers = require('test.helper')
6+
7+
local pgroup = helpers.pgroup.new('len', {
8+
engine = {'memtx'},
9+
})
10+
11+
pgroup:set_before_all(function(g)
12+
g.cluster = helpers.Cluster:new({
13+
datadir = fio.tempdir(),
14+
server_command = helpers.entrypoint('srv_select'),
15+
use_vshard = true,
16+
replicasets = helpers.get_test_replicasets(),
17+
env = {
18+
['ENGINE'] = g.params.engine,
19+
},
20+
})
21+
22+
g.cluster:start()
23+
end)
24+
25+
pgroup:set_after_all(function(g) helpers.stop_cluster(g.cluster) end)
26+
27+
pgroup:set_before_each(function(g)
28+
helpers.truncate_space_on_cluster(g.cluster, 'customers')
29+
end)
30+
31+
pgroup:add('test_len_non_existent_space', function(g)
32+
local result, err = g.cluster.main_server.net_box:call('crud.len', {'non_existent_space'})
33+
34+
t.assert_equals(result, nil)
35+
t.assert_str_contains(err.err, "Space \"non_existent_space\" doesn't exist")
36+
end)
37+
38+
pgroup:add('test_len', function(g)
39+
local customers = {}
40+
local expected_len = 100
41+
42+
-- let's insert a large number of tuples in a simple loop that gives
43+
-- really high probability that there is at least one tuple on each storage
44+
for i = 1, expected_len do
45+
table.insert(customers, {
46+
id = i, name = tostring(i), last_name = tostring(i),
47+
age = i, city = tostring(i),
48+
})
49+
end
50+
51+
helpers.insert_objects(g, 'customers', customers)
52+
53+
local result, err = g.cluster.main_server.net_box:call('crud.len', {'customers'})
54+
55+
t.assert_equals(err, nil)
56+
t.assert_equals(result, expected_len)
57+
end)
58+
59+
pgroup:add('test_len_empty_space', function(g)
60+
local result, err = g.cluster.main_server.net_box:call('crud.len', {'customers'})
61+
62+
t.assert_equals(err, nil)
63+
t.assert_equals(result, 0)
64+
end)

0 commit comments

Comments
 (0)