Skip to content

Commit

Permalink
box: rfc for persistent triggers in Tarantool
Browse files Browse the repository at this point in the history
Part of #4343
  • Loading branch information
kshcherbatov committed Sep 9, 2019
1 parent 664788a commit 3549c39
Showing 1 changed file with 113 additions and 0 deletions.
113 changes: 113 additions & 0 deletions doc/rfc/4343-persistent-triggers.md
@@ -0,0 +1,113 @@
# Persistent triggers in Tarantool

* **Status**: In progress
* **Start date**: 10-05-2019
* **Authors**: Kirill Shcherbatov @kshcherbatov kshcherbatov@tarantool.org, Georgy Kirichenko @GeorgyKirichenko georgy@tarantool.org
* **Issues**: [#4343](https://github.com/tarantool/tarantool/issues/4343)

## Summary
Triggers are currently not persistent: triggers disappear when the instance is shut down. Official manual recommends putting function definitions and trigger settings into Tarantool’s initialization script to make them permanent, but this is not a complex solution of this problem.

## Background and motivation
Triggers, also known as callbacks, are functions which the server executes when certain events happen.
There are six types of triggers in Tarantool:
- connection triggers, which are executed when a session begins or ends,
- authentication triggers, which are executed during authentication,
- replace triggers, which are for database events,
- transaction triggers, which are executed during commit or rollback,
- server triggers, which are executed when the server starts or stops.
- member triggers, which are executed when a SWIM member is updated.

Currently triggers are stored in the Tarantool instance’s memory, not in the database. Therefore triggers disappear when the instance is shut down.

With introducing the machinery for persistent function it becomes possible to
implement persistent triggers using very same approach.

Making triggers permanent and being defined in database schema is a very important step, because this works even in replicated environment.

## Proposal

### Data dictionary
Currently Tarantool has `_func` and `_trigger` spaces that defines persistent functions and (persistent) SQL triggers (that currently works only in SQL).

The `_trigger` space has the following format:
```
- [{'name': 'name', 'type': 'string'},
{'name': 'space_id', 'type': 'unsigned'},
{'name': 'opts', 'type': 'map'}]
```
The map typically contains `sql` key with SQL request that produced this SQL trigger. We need to extend this schema to also define persistent LUA functions.

At the same time, the `on_replace_dd_func` infrastructure has advanced procedures to build persistent Lua functions. The code that assembles Lua function object by given definition solves a really similar task.

To engage all benefits of all existent methods, let's split persistent trigger
creation on to two DDL operations: defining trigger routine itself in `_func` space
and defining the source/destination relation in `_trigger` space.

I. Let's introduce a new **trigger** `routine_type(s)` for `_func` space.
Each persistent trigger object (all triggers would be persistent) would
define a persistent function to execute (examples with LUA and SQL languages are given below):
```
- [99, 1, 'lua_trigger1', 1, 'LUA',
'function(old, new) new[1] = old[1] end', 'TRIGGER',
['any', 'any'], 'any', 'none', 'none', false, false,
true, ['LUA'], {}, '',
'2019-08-14 14:09:37', '2019-08-14 14:09:37']
-- example with SQL LANGUAGE that is not currently supported
- [100, 1, 'sql_trigger1', 1, 'SQL',
'INSERT INTO t2 VALUES(1);', 'TRIGGER', [], 'any', 'none',
'none', false, false, true, [], {}, '',
'2019-09-08 14:09:37', '2019-09-08 14:09:37']
```
The on_replace_dd_func_would assemble the corresponding function object and register it in function cache.

II. Let's rework the `_trigger` space.
1. name: ``name``\
type: ``string``\
The name of the trigger.
2. name: ``func_id``\
type: ``unsigned``\
The identifier of the trigger function. There should be a
corresponding record in `_func` space and it must have
`routine_type == trigger`.
3. name: ``type``\
type: ``string``\
The type of the Tarantool's trigger object: a one of `replace`, `connection`, `authentication`, `transaction`, `server`, `member`
4. name: ``space_id``\
type: ``unsigned``\
The identifier of the space where trigger is fired or 0 when undefined (for
all triggers types except `replace` triggers).
5. name: ``event_manipulation``\
type: ``string``\
The trigger event. This is the type of operation on the associated space for which the trigger activates. The value is `INSERT` (a row was inserted), `DELETE` (a row was deleted), or `UPDATE` (a row was modified).
default: ``insert``\
6. name: ``action_order``\
type: ``unsigned``\
default: 1
The ordinal position of the trigger's action within the list of triggers on the same table with the same `event_manipulation` and `action_timing` values.
7. name: ``action_condition``\
type: ``string``\
This value is always `NULL`.
8. name: ``action_orientation``\
type: ``string``\
This value is always `ROW`.
9. name: ``action_timing``\
type: ``string``\
Whether the trigger activates before or after the triggering event. The value is `BEFORE` or `AFTER`.

The `on_replace_dd_trigger` trigger would link previously-constructed function object and target object, e.g. space for `replace` trigger type.

### User interface
As it was described above, technically you need to define a function and
insert the trigger definition in `_trigger` space.

Currently we have the following abilities to define a trigger:
1. `space_object:on_replace()` and `space_object:before_replace()`
2. `box.session.on_connect()` and `box.session.on_disconnect()`
3. `box.session.on_auth()`
4. `box.on_commit()` and `box.on_rollback()`
5. `box.ctl.on_schema_init()` and `box.ctl.on_shutdown()`
6. `swim_object:on_member_event()`

They are now taking the Lua function object. The best way to transition to persistent trigger functionality is to pass the registered function's name as an argument instead of function object. Each endpoint would prepare a corresponding tuple for `_trigger` space taking into account all endpoint-specific details.

0 comments on commit 3549c39

Please sign in to comment.