TTL Purge REST API#
The TTL purging program runs inside every rdrs2 node that has the REST
API enabled. It scans the TTL tables and deletes the rows that have
expired, see TTL Service. The REST endpoints described
here report what the purge worker of one rdrs2 node is doing, and
change its settings.
Base URL and scope#
All endpoints are below
where 4406 is the default REST.ServerPort of rdrs2. Use https when
TLS is enabled for the REST server (Security.TLS.EnableTLS). The
ttl-purge endpoints exist only under API version 0.1.0, see API
Versions.
-
Every
rdrs2node has its own purge worker, its own settings and its own metrics. A request returns the values of the node that answers it. To see the whole cluster, query everyrdrs2node. -
Metrics are kept in memory. They start from zero when
rdrs2starts. -
Settings changed with
PUT /configare not stored. Whenrdrs2restarts, it takesenabledandactive_windowfromTTLPurge.EnableandTTLPurge.ActiveWindowin its configuration file, and the other settings from their defaults. -
The GET endpoints do not check API keys.
PUT /configrequires a valid API key in theX-API-KEYheader whenSecurity.APIKey.UseHopsworksAPIKeysistrue, which is the default. Any valid API key is accepted. -
The TTL purge metrics are not part of the Prometheus endpoint
/metrics.
Endpoints#
| Request | Returns |
|---|---|
GET /0.1.0/ttl-purge |
Configuration, status and metrics in one object |
GET /0.1.0/ttl-purge/config |
Current configuration |
PUT /0.1.0/ttl-purge/config |
Changes the configuration |
GET /0.1.0/ttl-purge/status |
What the purge worker is doing now |
GET /0.1.0/ttl-purge/metrics |
Counters for all TTL tables |
GET /0.1.0/ttl-purge/tables |
Counters per TTL table, one page at a time |
GET /0.1.0/ttl-purge/tables/{db}/{table} |
Counters for one TTL table |
All responses are JSON objects.
Configuration#
GET /0.1.0/ttl-purge/config returns the configuration of the purge
worker:
{"enabled":true,"min_batch_size":5,"max_batch_size":50,"sleep_interval_ms":1500,
"reconcile_interval_sec":30,"active_window":""}
-
enabled: whether this node purges. Whenfalse, the worker stops before the next table and reports the statedisabled. The value at startup isTTLPurge.Enable. -
min_batch_sizeandmax_batch_size: the limits for the number of rows the worker deletes from a table in one batch. The worker adapts the batch size of each table: when a batch deleted as many rows as the batch size in less than one second, the next batch is 5 rows larger, otherwise 5 rows smaller. The defaults are 5 and 50. -
sleep_interval_ms: the pause between two rounds. The actual pause is chosen at random within one third of this value, so that severalrdrs2nodes do not run in step. When the batch size of any table has reachedmax_batch_size, the next round starts without a pause. The default is 1500. -
reconcile_interval_sec: how often the worker lists all tables to find TTL tables that were created or dropped without a schema event, for example byndb_restoreinto a running cluster or by an NDB API application. 0 turns this off. The default is 30. -
active_window: the daily active window of this node, as"HH:MM-HH:MM"in UTC, or""for none. A valid window inmysql.ttl_purge_ctrltakes precedence over it, see TTL Service. The value at startup isTTLPurge.ActiveWindow.
Changing the configuration#
PUT /0.1.0/ttl-purge/config takes a JSON object with the fields to
change. Fields that are left out keep their current values, and unknown
fields are ignored.
curl -X PUT -H "X-API-KEY: <api-key>" -H "Content-Type: application/json" \
-d '{"enabled": false}' \
http://<rdrs-host>:4406/0.1.0/ttl-purge/config
curl -X PUT -H "X-API-KEY: <api-key>" -H "Content-Type: application/json" \
-d '{"active_window": "03:00-05:00", "max_batch_size": 100}' \
http://<rdrs-host>:4406/0.1.0/ttl-purge/config
# Remove the window of this node
curl -X PUT -H "X-API-KEY: <api-key>" -H "Content-Type: application/json" \
-d '{"active_window": ""}' \
http://<rdrs-host>:4406/0.1.0/ttl-purge/config
The response contains the configuration that is now in effect:
{"message":"Configuration updated","config":{"enabled":true,"min_batch_size":5,
"max_batch_size":100,"sleep_interval_ms":1500,"reconcile_interval_sec":30,
"active_window":"03:00-05:00"}}
The values are checked as follows:
-
active_windowmust be a string of exactly the form"HH:MM-HH:MM", with hours from 00 to 23, minutes from 00 to 59, and a start that differs from the end, or the empty string. The window wraps past midnight when the start is later than the end, for example"22:00-02:00". Any other value is rejected with 400 and the erroractive_window must be a string "HH:MM-HH:MM" (UTC) or empty, and none of the fields in the request are changed. -
A value of the wrong JSON type for
enabledor one of the numeric fields is ignored. -
min_batch_sizebelow 1 is set to 1, andmax_batch_sizebelowmin_batch_sizeis set tomin_batch_size.sleep_interval_msbelow 100 is set to 100.reconcile_interval_secabove 86400 is set to 86400.
An empty body is rejected with 400 and the error
Request body is empty, and a body that is not a JSON object with 400
and Invalid JSON or Failed to parse JSON.
The worker reads the configuration at the start of every round. A change
of enabled to false is also checked before every table, so the
worker stops within one batch.
Status#
GET /0.1.0/ttl-purge/status shows what the purge worker is doing:
{"state":"running","schema_watcher_running":true,"purge_worker_running":true,
"current_table":"mydb/events","current_partition":3,
"active_window":"03:00-05:00","active_window_source":"ttl_purge_ctrl"}
-
stateis one of:-
stopped: the worker has not started. -
running: the worker is purging. -
paused: the worker runs but has no TTL table to purge. This is also the state right after the worker starts. -
disabled:enabledisfalse. -
outside_window: an active window is in effect and the current time is outside it. -
error: the worker failed more than 10 times in a row and stopped. It is started again automatically.
pausedandstoppedare normal states, not faults. -
-
schema_watcher_runningandpurge_worker_running: whether the thread that tracks TTL tables and the thread that purges are running. -
current_tableandcurrent_partition: the table, as"db/table", and the partition that the worker purges now.""and 0 while the worker is outside its active window or has no TTL table. While the worker is disabled, they can still show the last table it purged. -
active_window: the window that is in effect, as"HH:MM-HH:MM"in UTC, or""when purging runs around the clock. -
active_window_source: where that window comes from:"ttl_purge_ctrl"for the cluster-wide window,"config"for the window of this node, or"".
The worker updates state, current_table and the window fields only
while it takes part in purging. When mysql.ttl_purge_nodes lists other
nodes but not this one, the worker does not purge and /status keeps
showing the values it had before, for example paused right after
startup. When the worker is disabled, the window fields show the window
from the last time it was enabled.
Metrics#
The worker purges in rounds. In a round it deletes one batch of expired
rows from one partition of each TTL table, and moves on to the next
partition of that table in the next round.
GET /0.1.0/ttl-purge/metrics returns counters over all TTL tables:
{"tables_count":12,"rows_purged_total":184220,"rows_purged_last_round":50,
"last_round_duration_ms":87,"last_purge_time_epoch_ms":1767225600000,
"rounds_completed":5321}
-
tables_count: the number of TTL tables this node knows. -
rows_purged_total: the rows this node has deleted sincerdrs2started. -
rows_purged_last_round: the rows deleted in the last completed round. It is a gauge that drops to 0 after a round without expired rows. Do not add it up over time; userows_purged_totalfor totals. -
last_round_duration_ms: the duration of the last completed round, without the pause after it. It covers all tables, so it does not show which table is slow. There is no timing per table. -
last_purge_time_epoch_ms: when the last round completed, in milliseconds since the Unix epoch. It is updated even when the round deleted no rows, so it shows that the worker is working, not that it deletes rows. It does not change while the worker is disabled, outside its active window, or has no TTL table. -
rounds_completed: the number of completed rounds.
Per-table metrics#
GET /0.1.0/ttl-purge/tables returns the TTL tables one page at a time,
ordered by database and table name. The query parameters are offset
(default 0) and limit (default 20, at most 100). A value that is not a
number is ignored and the default is used:
curl "http://<rdrs-host>:4406/0.1.0/ttl-purge/tables?offset=0&limit=2"
{"total":12,"offset":0,"limit":2,"tables":[
{"database":"mydb","table":"events","table_id":17,"ttl_sec":86400,
"ttl_column_no":1,"current_partition":4,"partition_count":8,
"current_batch_size":50,"rows_purged":120344,
"last_purge_time_epoch_ms":1767225600000},
{"database":"mydb","table":"sessions","table_id":21,"ttl_sec":3600,
"ttl_column_no":2,"current_partition":0,"partition_count":8,
"current_batch_size":5,"rows_purged":981,
"last_purge_time_epoch_ms":1767225600000}]}
GET /0.1.0/ttl-purge/tables/{db}/{table} returns the object of one
table. It returns 404 with the error Table db.table not found when
this node does not know the table as a TTL table. A 404 right after a
TTL table was created is expected: the node detects a new table within a
few seconds.
Each request reads the current list, so the pages are not a consistent
snapshot. When tables are created or dropped between two requests,
entries move from one page to another. With up to 100 TTL tables, read
them all with one request and limit=100.
-
database,tableandtable_id: the table.table_idis the NDB table id, which helps to match table ids in the cluster log to table names. -
ttl_sec: the TTL of the table in seconds. -
ttl_column_no: the position of the TTL column in the table, counting from 0. -
current_partitionandpartition_count: the partition the worker purges next, and the number of partitions. -
current_batch_size: the batch size for the next batch of this table. -
rows_purged: the rows of this table that this node has deleted sincerdrs2started. It starts again from 0 when the table loses its TTL or is dropped and later comes back.rows_purged_totalin/metricsis not affected. -
last_purge_time_epoch_ms: when the worker last purged a batch of this table, in milliseconds since the Unix epoch, or 0 if it has not yet.
A table appears in the list as soon as the node detects it, with its counters at zero.
The response does not show whether the worker reads a table through
ttl_index or scans the whole table. If purging costs more than
expected, check that each TTL table has an index named ttl_index with
the TTL column as its first column.
Combined view#
GET /0.1.0/ttl-purge returns the responses of /config, /status and
/metrics in one object:
HTTP status codes#
| Code | Meaning |
|---|---|
| 200 | OK |
| 400 | PUT /config: the body is empty, not valid JSON, or has an invalid active_window |
| 400, 401 | PUT /config: the API key is missing or not valid |
| 404 | /tables/{db}/{table}: the node does not know the table as a TTL table |
| 503 | The purge worker could not be initialized on this node (TTL purger not initialized) |
Common tasks#
Stop purging on one node for a while
Send {"enabled": false} to PUT /config and check that /status
reports disabled. Send {"enabled": true} to start again. A restart
of rdrs2 also returns the node to the value of TTLPurge.Enable.
Find out which active window is in effect
Read active_window and active_window_source in /status on each
purging node.
Check whether purging keeps up
When a table has more expired rows than the worker deletes, its
current_batch_size stays at max_batch_size round after round, and
the worker runs rounds without pausing. Increase max_batch_size, add
purge nodes, or widen the active window. When the active window closes
while the worker is in this state, the rdrs2 log also shows a warning
that a backlog of expired rows likely remains.
Measure the purge rate
Read rows_purged_total twice, a known time apart. The difference
divided by the time is the purge rate of this node. Compare the sum over
all purge nodes with the rate at which rows expire. For the total of the
cluster, add up rows_purged_total of all rdrs2 nodes.
List every TTL table
Call /tables?limit=100, and use offset for more than 100 tables.
Monitor the purge worker
Alert when state is error, when purge_worker_running or
schema_watcher_running is false, or when last_purge_time_epoch_ms
stops advancing while state is running.
Follow one table
Call /tables/{db}/{table} a few times. rows_purged grows while
expired rows are deleted, and current_partition moves through all
partitions of the table that this node purges.