Add reply_schema to command json files (internal for now) (#10273)
Work in progress towards implementing a reply schema as part of COMMAND DOCS, see #9845
Since ironing the details of the reply schema of each and every command can take a long time, we
would like to merge this PR when the infrastructure is ready, and let this mature in the unstable branch.
Meanwhile the changes of this PR are internal, they are part of the repo, but do not affect the produced build.
### Background
In #9656 we add a lot of information about Redis commands, but we are missing information about the replies
### Motivation
1. Documentation. This is the primary goal.
2. It should be possible, based on the output of COMMAND, to be able to generate client code in typed
languages. In order to do that, we need Redis to tell us, in detail, what each reply looks like.
3. We would like to build a fuzzer that verifies the reply structure (for now we use the existing
testsuite, see the "Testing" section)
### Schema
The idea is to supply some sort of schema for the various replies of each command.
The schema will describe the conceptual structure of the reply (for generated clients), as defined in RESP3.
Note that the reply structure itself may change, depending on the arguments (e.g. `XINFO STREAM`, with
and without the `FULL` modifier)
We decided to use the standard json-schema (see https://json-schema.org/) as the reply-schema.
Example for `BZPOPMIN`:
```
"reply_schema": {
"oneOf": [
{
"description": "Timeout reached and no elements were popped.",
"type": "null"
},
{
"description": "The keyname, popped member, and its score.",
"type": "array",
"minItems": 3,
"maxItems": 3,
"items": [
{
"description": "Keyname",
"type": "string"
},
{
"description": "Member",
"type": "string"
},
{
"description": "Score",
"type": "number"
}
]
}
]
}
```
#### Notes
1. It is ok that some commands' reply structure depends on the arguments and it's the caller's responsibility
to know which is the relevant one. this comes after looking at other request-reply systems like OpenAPI,
where the reply schema can also be oneOf and the caller is responsible to know which schema is the relevant one.
2. The reply schemas will describe RESP3 replies only. even though RESP3 is structured, we want to use reply
schema for documentation (and possibly to create a fuzzer that validates the replies)
3. For documentation, the description field will include an explanation of the scenario in which the reply is sent,
including any relation to arguments. for example, for `ZRANGE`'s two schemas we will need to state that one
is with `WITHSCORES` and the other is without.
4. For documentation, there will be another optional field "notes" in which we will add a short description of
the representation in RESP2, in case it's not trivial (RESP3's `ZRANGE`'s nested array vs. RESP2's flat
array, for example)
Given the above:
1. We can generate the "return" section of all commands in [redis-doc](https://redis.io/commands/)
(given that "description" and "notes" are comprehensive enough)
2. We can generate a client in a strongly typed language (but the return type could be a conceptual
`union` and the caller needs to know which schema is relevant). see the section below for RESP2 support.
3. We can create a fuzzer for RESP3.
### Limitations (because we are using the standard json-schema)
The problem is that Redis' replies are more diverse than what the json format allows. This means that,
when we convert the reply to a json (in order to validate the schema against it), we lose information (see
the "Testing" section below).
The other option would have been to extend the standard json-schema (and json format) to include stuff
like sets, bulk-strings, error-string, etc. but that would mean also extending the schema-validator - and that
seemed like too much work, so we decided to compromise.
Examples:
1. We cannot tell the difference between an "array" and a "set"
2. We cannot tell the difference between simple-string and bulk-string
3. we cannot verify true uniqueness of items in commands like ZRANGE: json-schema doesn't cover the
case of two identical members with different scores (e.g. `[["m1",6],["m1",7]]`) because `uniqueItems`
compares (member,score) tuples and not just the member name.
### Testing
This commit includes some changes inside Redis in order to verify the schemas (existing and future ones)
are indeed correct (i.e. describe the actual response of Redis).
To do that, we added a debugging feature to Redis that causes it to produce a log of all the commands
it executed and their replies.
For that, Redis needs to be compiled with `-DLOG_REQ_RES` and run with
`--reg-res-logfile <file> --client-default-resp 3` (the testsuite already does that if you run it with
`--log-req-res --force-resp3`)
You should run the testsuite with the above args (and `--dont-clean`) in order to make Redis generate
`.reqres` files (same dir as the `stdout` files) which contain request-response pairs.
These files are later on processed by `./utils/req-res-log-validator.py` which does:
1. Goes over req-res files, generated by redis-servers, spawned by the testsuite (see logreqres.c)
2. For each request-response pair, it validates the response against the request's reply_schema
(obtained from the extended COMMAND DOCS)
5. In order to get good coverage of the Redis commands, and all their different replies, we chose to use
the existing redis test suite, rather than attempt to write a fuzzer.
#### Notes about RESP2
1. We will not be able to use the testing tool to verify RESP2 replies (we are ok with that, it's time to
accept RESP3 as the future RESP)
2. Since the majority of the test suite is using RESP2, and we want the server to reply with RESP3
so that we can validate it, we will need to know how to convert the actual reply to the one expected.
- number and boolean are always strings in RESP2 so the conversion is easy
- objects (maps) are always a flat array in RESP2
- others (nested array in RESP3's `ZRANGE` and others) will need some special per-command
handling (so the client will not be totally auto-generated)
Example for ZRANGE:
```
"reply_schema": {
"anyOf": [
{
"description": "A list of member elements",
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
},
{
"description": "Members and their scores. Returned in case `WITHSCORES` was used.",
"notes": "In RESP2 this is returned as a flat array",
"type": "array",
"uniqueItems": true,
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": [
{
"description": "Member",
"type": "string"
},
{
"description": "Score",
"type": "number"
}
]
}
}
]
}
```
### Other changes
1. Some tests that behave differently depending on the RESP are now being tested for both RESP,
regardless of the special log-req-res mode ("Pub/Sub PING" for example)
2. Update the history field of CLIENT LIST
3. Added basic tests for commands that were not covered at all by the testsuite
### TODO
- [x] (maybe a different PR) add a "condition" field to anyOf/oneOf schemas that refers to args. e.g.
when `SET` return NULL, the condition is `arguments.get||arguments.condition`, for `OK` the condition
is `!arguments.get`, and for `string` the condition is `arguments.get` - https://github.com/redis/redis/issues/11896
- [x] (maybe a different PR) also run `runtest-cluster` in the req-res logging mode
- [x] add the new tests to GH actions (i.e. compile with `-DLOG_REQ_RES`, run the tests, and run the validator)
- [x] (maybe a different PR) figure out a way to warn about (sub)schemas that are uncovered by the output
of the tests - https://github.com/redis/redis/issues/11897
- [x] (probably a separate PR) add all missing schemas
- [x] check why "SDOWN is triggered by misconfigured instance replying with errors" fails with --log-req-res
- [x] move the response transformers to their own file (run both regular, cluster, and sentinel tests - need to
fight with the tcl including mechanism a bit)
- [x] issue: module API - https://github.com/redis/redis/issues/11898
- [x] (probably a separate PR): improve schemas: add `required` to `object`s - https://github.com/redis/redis/issues/11899
Co-authored-by: Ozan Tezcan <ozantezcan@gmail.com>
Co-authored-by: Hanna Fadida <hanna.fadida@redislabs.com>
Co-authored-by: Oran Agra <oran@redislabs.com>
Co-authored-by: Shaya Potter <shaya@redislabs.com>
2023-03-11 03:14:16 -05:00
|
|
|
# This unit has the potential to create huge .reqres files, causing log-req-res-validator.py to run for a very long time...
|
|
|
|
# Since this unit doesn't do anything worth validating, reply_schema-wise, we decided to skip it
|
Attempt to solve MacOS CI issues in GH Actions (#12013)
The MacOS CI in github actions often hangs without any logs. GH argues that
it's due to resource utilization, either running out of disk space, memory, or CPU
starvation, and thus the runner is terminated.
This PR contains multiple attempts to resolve this:
1. introducing pause_process instead of SIGSTOP, which waits for the process
to stop before resuming the test, possibly resolving race conditions in some tests,
this was a suspect since there was one test that could result in an infinite loop in that
case, in practice this didn't help, but still a good idea to keep.
2. disable the `save` config in many tests that don't need it, specifically ones that use
heavy writes and could create large files.
3. change the `populate` proc to use short pipeline rather than an infinite one.
4. use `--clients 1` in the macos CI so that we don't risk running multiple resource
demanding tests in parallel.
5. enable `--verbose` to be repeated to elevate verbosity and print more info to stdout
when a test or a server starts.
2023-04-12 02:19:21 -04:00
|
|
|
start_server {tags {"aofrw external:skip logreqres:skip"} overrides {save {}}} {
|
2014-07-10 05:24:59 -04:00
|
|
|
# Enable the AOF
|
|
|
|
r config set appendonly yes
|
|
|
|
r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite.
|
|
|
|
waitForBgrewriteaof r
|
2012-04-07 07:22:04 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
foreach rdbpre {yes no} {
|
|
|
|
r config set aof-use-rdb-preamble $rdbpre
|
|
|
|
test "AOF rewrite during write load: RDB preamble=$rdbpre" {
|
|
|
|
# Start a write load for 10 seconds
|
|
|
|
set master [srv 0 client]
|
|
|
|
set master_host [srv 0 host]
|
|
|
|
set master_port [srv 0 port]
|
|
|
|
set load_handle0 [start_write_load $master_host $master_port 10]
|
|
|
|
set load_handle1 [start_write_load $master_host $master_port 10]
|
|
|
|
set load_handle2 [start_write_load $master_host $master_port 10]
|
|
|
|
set load_handle3 [start_write_load $master_host $master_port 10]
|
|
|
|
set load_handle4 [start_write_load $master_host $master_port 10]
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Make sure the instance is really receiving data
|
|
|
|
wait_for_condition 50 100 {
|
|
|
|
[r dbsize] > 0
|
|
|
|
} else {
|
|
|
|
fail "No write load detected."
|
|
|
|
}
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# After 3 seconds, start a rewrite, while the write load is still
|
|
|
|
# active.
|
|
|
|
after 3000
|
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Let it run a bit more so that we'll append some data to the new
|
|
|
|
# AOF.
|
|
|
|
after 1000
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Stop the processes generating the load if they are still active
|
|
|
|
stop_write_load $load_handle0
|
|
|
|
stop_write_load $load_handle1
|
|
|
|
stop_write_load $load_handle2
|
|
|
|
stop_write_load $load_handle3
|
|
|
|
stop_write_load $load_handle4
|
2014-07-10 05:24:59 -04:00
|
|
|
|
stabilize tests that involved with load handlers (#8967)
When test stop 'load handler' by killing the process that generating the load,
some commands that already in the input buffer, still might be processed by the server.
This may cause some instability in tests, that count on that no more commands
processed after we stop the `load handler'
In this commit, new proc 'wait_load_handlers_disconnected' added, to verify that no more
cammands from any 'load handler' prossesed, by checking that the clients who
genreate the load is disconnceted.
Also, replacing check of dbsize with wait_for_ofs_sync before comparing debug digest, as
it would fail in case the last key the workload wrote was an overridden key (not a new one).
Affected tests
Race fix:
- failover command to specific replica works
- Connect multiple replicas at the same time (issue #141), master diskless=$mdl, replica diskless=$sdl
- AOF rewrite during write load: RDB preamble=$rdbpre
Cleanup and speedup:
- Test replication with blocking lists and sorted sets operations
- Test replication with parallel clients writing in different DBs
- Test replication partial resync: $descr (diskless: $mdl, $sdl, reconnect: $reconnect
2021-05-20 08:29:43 -04:00
|
|
|
# Make sure no more commands processed, before taking debug digest
|
|
|
|
wait_load_handlers_disconnected
|
2014-07-10 10:42:43 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Get the data set digest
|
2021-12-19 10:41:51 -05:00
|
|
|
set d1 [debug_digest]
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Load the AOF
|
|
|
|
r debug loadaof
|
2021-12-19 10:41:51 -05:00
|
|
|
set d2 [debug_digest]
|
2014-07-10 05:24:59 -04:00
|
|
|
|
2016-08-24 09:39:39 -04:00
|
|
|
# Make sure they are the same
|
|
|
|
assert {$d1 eq $d2}
|
|
|
|
}
|
2014-07-10 05:24:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-09 08:13:24 -04:00
|
|
|
start_server {tags {"aofrw external:skip"} overrides {aof-use-rdb-preamble no}} {
|
2012-04-07 07:22:04 -04:00
|
|
|
test {Turning off AOF kills the background writing child if any} {
|
|
|
|
r config set appendonly yes
|
|
|
|
waitForBgrewriteaof r
|
2022-01-04 06:37:47 -05:00
|
|
|
|
|
|
|
# start a slow AOFRW
|
2022-01-13 05:38:41 -05:00
|
|
|
r set k v
|
2022-01-04 06:37:47 -05:00
|
|
|
r config set rdb-key-save-delay 10000000
|
2012-04-07 07:22:04 -04:00
|
|
|
r bgrewriteaof
|
2022-01-04 06:37:47 -05:00
|
|
|
|
|
|
|
# disable AOF and wait for the child to be killed
|
2012-04-07 07:22:04 -04:00
|
|
|
r config set appendonly no
|
2012-05-02 05:40:46 -04:00
|
|
|
wait_for_condition 50 100 {
|
2017-02-22 07:08:21 -05:00
|
|
|
[string match {*Killing*AOF*child*} [exec tail -5 < [srv 0 stdout]]]
|
2012-05-02 05:40:46 -04:00
|
|
|
} else {
|
|
|
|
fail "Can't find 'Killing AOF child' into recent logs"
|
|
|
|
}
|
2022-01-19 14:21:42 -05:00
|
|
|
r config set rdb-key-save-delay 0
|
2012-05-02 05:40:46 -04:00
|
|
|
}
|
2012-04-07 07:22:04 -04:00
|
|
|
|
2011-12-12 09:34:00 -05:00
|
|
|
foreach d {string int} {
|
Add listpack encoding for list (#11303)
Improve memory efficiency of list keys
## Description of the feature
The new listpack encoding uses the old `list-max-listpack-size` config
to perform the conversion, which we can think it of as a node inside a
quicklist, but without 80 bytes overhead (internal fragmentation included)
of quicklist and quicklistNode structs.
For example, a list key with 5 items of 10 chars each, now takes 128 bytes
instead of 208 it used to take.
## Conversion rules
* Convert listpack to quicklist
When the listpack length or size reaches the `list-max-listpack-size` limit,
it will be converted to a quicklist.
* Convert quicklist to listpack
When a quicklist has only one node, and its length or size is reduced to half
of the `list-max-listpack-size` limit, it will be converted to a listpack.
This is done to avoid frequent conversions when we add or remove at the bounding size or length.
## Interface changes
1. add list entry param to listTypeSetIteratorDirection
When list encoding is listpack, `listTypeIterator->lpi` points to the next entry of current entry,
so when changing the direction, we need to use the current node (listTypeEntry->p) to
update `listTypeIterator->lpi` to the next node in the reverse direction.
## Benchmark
### Listpack VS Quicklist with one node
* LPUSH - roughly 0.3% improvement
* LRANGE - roughly 13% improvement
### Both are quicklist
* LRANGE - roughly 3% improvement
* LRANGE without pipeline - roughly 3% improvement
From the benchmark, as we can see from the results
1. When list is quicklist encoding, LRANGE improves performance by <5%.
2. When list is listpack encoding, LRANGE improves performance by ~13%,
the main enhancement is brought by `addListListpackRangeReply()`.
## Memory usage
1M lists(key:0~key:1000000) with 5 items of 10 chars ("hellohello") each.
shows memory usage down by 35.49%, from 214MB to 138MB.
## Note
1. Add conversion callback to support doing some work before conversion
Since the quicklist iterator decompresses the current node when it is released, we can
no longer decompress the quicklist after we convert the list.
2022-11-16 13:29:46 -05:00
|
|
|
foreach e {listpack quicklist} {
|
2011-12-12 09:34:00 -05:00
|
|
|
test "AOF rewrite of list with $e encoding, $d data" {
|
|
|
|
r flushall
|
Add listpack encoding for list (#11303)
Improve memory efficiency of list keys
## Description of the feature
The new listpack encoding uses the old `list-max-listpack-size` config
to perform the conversion, which we can think it of as a node inside a
quicklist, but without 80 bytes overhead (internal fragmentation included)
of quicklist and quicklistNode structs.
For example, a list key with 5 items of 10 chars each, now takes 128 bytes
instead of 208 it used to take.
## Conversion rules
* Convert listpack to quicklist
When the listpack length or size reaches the `list-max-listpack-size` limit,
it will be converted to a quicklist.
* Convert quicklist to listpack
When a quicklist has only one node, and its length or size is reduced to half
of the `list-max-listpack-size` limit, it will be converted to a listpack.
This is done to avoid frequent conversions when we add or remove at the bounding size or length.
## Interface changes
1. add list entry param to listTypeSetIteratorDirection
When list encoding is listpack, `listTypeIterator->lpi` points to the next entry of current entry,
so when changing the direction, we need to use the current node (listTypeEntry->p) to
update `listTypeIterator->lpi` to the next node in the reverse direction.
## Benchmark
### Listpack VS Quicklist with one node
* LPUSH - roughly 0.3% improvement
* LRANGE - roughly 13% improvement
### Both are quicklist
* LRANGE - roughly 3% improvement
* LRANGE without pipeline - roughly 3% improvement
From the benchmark, as we can see from the results
1. When list is quicklist encoding, LRANGE improves performance by <5%.
2. When list is listpack encoding, LRANGE improves performance by ~13%,
the main enhancement is brought by `addListListpackRangeReply()`.
## Memory usage
1M lists(key:0~key:1000000) with 5 items of 10 chars ("hellohello") each.
shows memory usage down by 35.49%, from 214MB to 138MB.
## Note
1. Add conversion callback to support doing some work before conversion
Since the quicklist iterator decompresses the current node when it is released, we can
no longer decompress the quicklist after we convert the list.
2022-11-16 13:29:46 -05:00
|
|
|
if {$e eq {listpack}} {
|
|
|
|
r config set list-max-listpack-size -2
|
|
|
|
set len 10
|
|
|
|
} else {
|
|
|
|
r config set list-max-listpack-size 10
|
|
|
|
set len 1000
|
|
|
|
}
|
2011-12-12 09:34:00 -05:00
|
|
|
for {set j 0} {$j < $len} {incr j} {
|
|
|
|
if {$d eq {string}} {
|
|
|
|
set data [randstring 0 16 alpha]
|
|
|
|
} else {
|
|
|
|
set data [randomInt 4000000000]
|
|
|
|
}
|
|
|
|
r lpush key $data
|
|
|
|
}
|
|
|
|
assert_equal [r object encoding key] $e
|
2021-12-19 10:41:51 -05:00
|
|
|
set d1 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
|
|
|
r debug loadaof
|
2021-12-19 10:41:51 -05:00
|
|
|
set d2 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
if {$d1 ne $d2} {
|
|
|
|
error "assertion:$d1 is not equal to $d2"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach d {string int} {
|
|
|
|
foreach e {intset hashtable} {
|
|
|
|
test "AOF rewrite of set with $e encoding, $d data" {
|
|
|
|
r flushall
|
|
|
|
if {$e eq {intset}} {set len 10} else {set len 1000}
|
|
|
|
for {set j 0} {$j < $len} {incr j} {
|
|
|
|
if {$d eq {string}} {
|
|
|
|
set data [randstring 0 16 alpha]
|
|
|
|
} else {
|
|
|
|
set data [randomInt 4000000000]
|
|
|
|
}
|
|
|
|
r sadd key $data
|
|
|
|
}
|
|
|
|
if {$d ne {string}} {
|
|
|
|
assert_equal [r object encoding key] $e
|
|
|
|
}
|
2021-12-19 10:41:51 -05:00
|
|
|
set d1 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
|
|
|
r debug loadaof
|
2021-12-19 10:41:51 -05:00
|
|
|
set d2 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
if {$d1 ne $d2} {
|
|
|
|
error "assertion:$d1 is not equal to $d2"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach d {string int} {
|
2021-08-10 02:18:49 -04:00
|
|
|
foreach e {listpack hashtable} {
|
2011-12-12 09:34:00 -05:00
|
|
|
test "AOF rewrite of hash with $e encoding, $d data" {
|
|
|
|
r flushall
|
2021-08-10 02:18:49 -04:00
|
|
|
if {$e eq {listpack}} {set len 10} else {set len 1000}
|
2011-12-12 09:34:00 -05:00
|
|
|
for {set j 0} {$j < $len} {incr j} {
|
|
|
|
if {$d eq {string}} {
|
|
|
|
set data [randstring 0 16 alpha]
|
|
|
|
} else {
|
|
|
|
set data [randomInt 4000000000]
|
|
|
|
}
|
|
|
|
r hset key $data $data
|
|
|
|
}
|
|
|
|
assert_equal [r object encoding key] $e
|
2021-12-19 10:41:51 -05:00
|
|
|
set d1 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
|
|
|
r debug loadaof
|
2021-12-19 10:41:51 -05:00
|
|
|
set d2 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
if {$d1 ne $d2} {
|
|
|
|
error "assertion:$d1 is not equal to $d2"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach d {string int} {
|
2021-09-09 11:18:53 -04:00
|
|
|
foreach e {listpack skiplist} {
|
2011-12-12 09:34:00 -05:00
|
|
|
test "AOF rewrite of zset with $e encoding, $d data" {
|
|
|
|
r flushall
|
2021-09-09 11:18:53 -04:00
|
|
|
if {$e eq {listpack}} {set len 10} else {set len 1000}
|
2011-12-12 09:34:00 -05:00
|
|
|
for {set j 0} {$j < $len} {incr j} {
|
|
|
|
if {$d eq {string}} {
|
|
|
|
set data [randstring 0 16 alpha]
|
|
|
|
} else {
|
|
|
|
set data [randomInt 4000000000]
|
|
|
|
}
|
|
|
|
r zadd key [expr rand()] $data
|
|
|
|
}
|
|
|
|
assert_equal [r object encoding key] $e
|
2021-12-19 10:41:51 -05:00
|
|
|
set d1 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
|
|
|
r debug loadaof
|
2021-12-19 10:41:51 -05:00
|
|
|
set d2 [debug_digest]
|
2011-12-12 09:34:00 -05:00
|
|
|
if {$d1 ne $d2} {
|
|
|
|
error "assertion:$d1 is not equal to $d2"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-04-06 17:52:53 -04:00
|
|
|
|
2022-01-19 14:21:42 -05:00
|
|
|
test "AOF rewrite functions" {
|
|
|
|
r flushall
|
2022-04-05 03:27:24 -04:00
|
|
|
r FUNCTION LOAD {#!lua name=test
|
2022-01-19 14:21:42 -05:00
|
|
|
redis.register_function('test', function() return 1 end)
|
|
|
|
}
|
|
|
|
r bgrewriteaof
|
|
|
|
waitForBgrewriteaof r
|
|
|
|
r function flush
|
|
|
|
r debug loadaof
|
|
|
|
assert_equal [r fcall test 0] 1
|
|
|
|
r FUNCTION LIST
|
2022-04-05 03:27:24 -04:00
|
|
|
} {{library_name test engine LUA functions {{name test description {} flags {}}}}}
|
2022-01-19 14:21:42 -05:00
|
|
|
|
2012-04-06 17:52:53 -04:00
|
|
|
test {BGREWRITEAOF is delayed if BGSAVE is in progress} {
|
2021-12-27 08:18:17 -05:00
|
|
|
r flushall
|
|
|
|
r set k v
|
|
|
|
r config set rdb-key-save-delay 10000000
|
2012-04-06 17:52:53 -04:00
|
|
|
r bgsave
|
2021-12-27 08:18:17 -05:00
|
|
|
assert_match {*scheduled*} [r bgrewriteaof]
|
|
|
|
assert_equal [s aof_rewrite_scheduled] 1
|
|
|
|
r config set rdb-key-save-delay 0
|
|
|
|
catch {exec kill -9 [get_child_pid 0]}
|
|
|
|
while {[s aof_rewrite_scheduled] eq 1} {
|
2012-04-06 17:52:53 -04:00
|
|
|
after 100
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
test {BGREWRITEAOF is refused if already in progress} {
|
2021-12-27 08:18:17 -05:00
|
|
|
r config set aof-use-rdb-preamble yes
|
|
|
|
r config set rdb-key-save-delay 10000000
|
2012-04-06 17:52:53 -04:00
|
|
|
catch {
|
|
|
|
r bgrewriteaof
|
|
|
|
r bgrewriteaof
|
|
|
|
} e
|
|
|
|
assert_match {*ERR*already*} $e
|
2021-12-27 08:18:17 -05:00
|
|
|
r config set rdb-key-save-delay 0
|
|
|
|
catch {exec kill -9 [get_child_pid 0]}
|
2012-04-06 17:52:53 -04:00
|
|
|
}
|
2011-12-12 09:34:00 -05:00
|
|
|
}
|