|
1 | | -## Spock Samples |
| 1 | +# Zodan: Zero-Downtime Node Addition for Spock |
2 | 2 |
|
3 | | -The `samples` directory includes unmaintained helper tutorials, functions, and procedures for the Spock extension. Sample programs in this directory should be considered illustrative only, and should be well tested before being used in a production environment. |
| 3 | +Zodan provides tools to add a new node to a PostgreSQL logical replication cluster **without any downtime**. |
4 | 4 |
|
5 | | -The content of this directory is subject to change or removal at any time. To contribute a sample to this directory, open a Pull Request and attach the content; a developer will review the content for inclusion. |
| 5 | +It includes two components: |
| 6 | + |
| 7 | +- **[zodan.py](zodan.py)**: A Python CLI script that uses `psql` to perform automated node addition. |
| 8 | +- **[zodan.sql](zodan.sql)**: A complete SQL-based workflow using `dblink` to perform the same operations from within PostgreSQL. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## Overview |
| 13 | + |
| 14 | +Zodan is designed to streamline the process of adding a new node to an existing Spock cluster. It handles creation of the new node, subscription management (both to and from the new node), replication slot creation, data synchronization, replication slot advancement, and final activation of subscriptions. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## Components |
| 19 | + |
| 20 | +### 1. zodan.py |
| 21 | + |
| 22 | +This Python script leverages `psql` and is intended for use in environments where you have shell and Python access. |
| 23 | + |
| 24 | +#### Requirements |
| 25 | + |
| 26 | +- PostgreSQL 15 or later |
| 27 | +- Spock extension installed and configured |
| 28 | +- dblink extension enabled on all nodes |
| 29 | +- Python 3 |
| 30 | +- Passwordless access or a properly configured `.pgpass` file for remote connections |
| 31 | + |
| 32 | +#### Usage |
| 33 | + |
| 34 | +```bash |
| 35 | +./zodan.py \ |
| 36 | + --src-node-name <source_node> \ |
| 37 | + --src-dsn "<source_dsn>" \ |
| 38 | + --new-node-name <new_node> \ |
| 39 | + --new-node-dsn "<new_node_dsn>" \ |
| 40 | + [options] |
| 41 | +``` |
| 42 | + |
| 43 | +**Options:** |
| 44 | + |
| 45 | +- `--src-node-name`: Name of an existing node in the cluster. |
| 46 | +- `--src-dsn`: DSN of the source node (e.g., `"host=127.0.0.1 dbname=pgedge port=5431 user=pgedge password=pgedge"`). |
| 47 | +- `--new-node-name`: Name of the new node to add. |
| 48 | +- `--new-node-dsn`: DSN of the new node. |
| 49 | +- `--new-node-location`: Location of the new node (default: "NY"). |
| 50 | +- `--new-node-country`: Country of the new node (default: "USA"). |
| 51 | +- `--new-node-info`: A JSON string with additional metadata (default: "{}"). |
| 52 | + |
| 53 | +--- |
| 54 | + |
| 55 | +### 2. zodan.sql |
| 56 | + |
| 57 | +The SQL-based implementation utilizes PostgreSQL’s `dblink` extension to handle node addition directly from within the database. This method is ideal for environments where you may not have access to shell or Python. |
| 58 | + |
| 59 | +#### How to Use |
| 60 | + |
| 61 | +Execute the following command in your PostgreSQL session: |
| 62 | + |
| 63 | +```sql |
| 64 | +CALL add_node( |
| 65 | + 'source_node_name', |
| 66 | + 'source_node_dsn', |
| 67 | + 'new_node_name', |
| 68 | + 'new_node_dsn', |
| 69 | + 'new_node_location', -- optional |
| 70 | + 'new_node_country', -- optional |
| 71 | + '{}'::jsonb -- optional info |
| 72 | +); |
| 73 | +``` |
| 74 | + |
| 75 | +#### Example |
| 76 | + |
| 77 | +```sql |
| 78 | +CALL add_node( |
| 79 | + 'n1', |
| 80 | + 'host=127.0.0.1 dbname=pgedge port=5431 user=pgedge password=pgedge', |
| 81 | + 'n4', |
| 82 | + 'host=127.0.0.1 dbname=pgedge port=5434 user=pgedge password=pgedge' |
| 83 | +); |
| 84 | +``` |
| 85 | + |
| 86 | +#### Major SQL Components |
| 87 | + |
| 88 | +- **add_node**: Main procedure to orchestrate the full workflow. |
| 89 | +- **create_node**: Registers a new node via `spock.node_create`. |
| 90 | +- **get_spock_nodes**: Fetches current node metadata from a remote node. |
| 91 | +- **create_sub / enable_sub**: Manages subscription creation and activation. |
| 92 | +- **create_replication_slot**: Sets up logical replication slots. |
| 93 | +- **sync_event / wait_for_sync_event**: Coordinates data synchronization events. |
| 94 | +- **get_commit_timestamp / advance_replication_slot**: Aligns replication states. |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +## When to Use |
| 99 | + |
| 100 | +| Use Case | Use zodan.py | Use zodan.sql | |
| 101 | +| ---------------------------------- | :----------: | :-----------: | |
| 102 | +| CLI automation / scripting | ✅ | | |
| 103 | +| SQL-only environments | | ✅ | |
| 104 | +| No Python or shell access | | ✅ | |
| 105 | +| PostgreSQL extension workflows | ✅ | ✅ | |
| 106 | + |
| 107 | +--- |
0 commit comments