snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
78
internal/controllers/controller_postgres_schema.sql
Normal file
78
internal/controllers/controller_postgres_schema.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
-- PostgreSQL Controller schema template.
|
||||
-- Placeholders: __PREFIX__ → e.g. "cf_" (includes trailing underscore).
|
||||
--
|
||||
-- Tables:
|
||||
-- __PREFIX__controller_messages — control message outbox (partitioned by created_at, daily)
|
||||
-- __PREFIX__controller_shard_lock — per-shard serialization lock rows
|
||||
-- __PREFIX__controller_schema_version — schema version tracking
|
||||
--
|
||||
-- Functions:
|
||||
-- __PREFIX__controller_publish(BYTEA, TEXT, INTEGER) — shard lock + INSERT + NOTIFY
|
||||
|
||||
-- Messages outbox table — always partitioned by created_at (daily).
|
||||
CREATE TABLE IF NOT EXISTS __PREFIX__controller_messages (
|
||||
id BIGSERIAL,
|
||||
shard_id SMALLINT NOT NULL DEFAULT 0,
|
||||
node_id TEXT NOT NULL DEFAULT '',
|
||||
data BYTEA NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (id, created_at)
|
||||
) PARTITION BY RANGE (created_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS __PREFIX__controller_messages_shard_id_idx
|
||||
ON __PREFIX__controller_messages (shard_id, id);
|
||||
|
||||
-- Per-shard serialization lock. Rows populated by EnsureSchema (0..NumShards-1).
|
||||
-- The publish function acquires a FOR UPDATE lock on the relevant row before
|
||||
-- INSERT, ensuring BIGSERIAL id assignment matches commit order within a shard.
|
||||
CREATE TABLE IF NOT EXISTS __PREFIX__controller_shard_lock (
|
||||
shard_id SMALLINT PRIMARY KEY
|
||||
);
|
||||
|
||||
-- Schema version tracking.
|
||||
CREATE TABLE IF NOT EXISTS __PREFIX__controller_schema_version (
|
||||
id INTEGER PRIMARY KEY,
|
||||
schema_version INTEGER NOT NULL
|
||||
);
|
||||
INSERT INTO __PREFIX__controller_schema_version (id, schema_version) VALUES (1, 1)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- Publish function: shard lock + INSERT + NOTIFY.
|
||||
-- Acquires a FOR UPDATE lock on the shard_lock row for the computed shard,
|
||||
-- serializing concurrent publishes within the same shard. This ensures the
|
||||
-- BIGSERIAL id order matches commit order — no gaps for cursor-based polling.
|
||||
CREATE OR REPLACE FUNCTION __PREFIX__controller_publish(
|
||||
p_data BYTEA,
|
||||
p_node_id TEXT DEFAULT '',
|
||||
p_num_shards INTEGER DEFAULT NULL
|
||||
) RETURNS BIGINT AS $$
|
||||
DECLARE
|
||||
v_id BIGINT;
|
||||
v_shard_id INTEGER;
|
||||
BEGIN
|
||||
-- Auto-derive num_shards from shard_lock table when not provided.
|
||||
IF p_num_shards IS NULL OR p_num_shards <= 0 THEN
|
||||
SELECT COUNT(*)::INTEGER INTO p_num_shards FROM __PREFIX__controller_shard_lock;
|
||||
END IF;
|
||||
|
||||
-- All messages go to shard 0 when num_shards=1. With multiple shards,
|
||||
-- distribute by hash of node_id (targeted) or round-robin via txid (broadcast).
|
||||
IF p_num_shards <= 1 THEN
|
||||
v_shard_id := 0;
|
||||
ELSIF p_node_id != '' THEN
|
||||
v_shard_id := abs(hashtext(p_node_id)::bigint) % p_num_shards;
|
||||
ELSE
|
||||
v_shard_id := (txid_current() % p_num_shards)::INTEGER;
|
||||
END IF;
|
||||
|
||||
-- Serialize within shard.
|
||||
PERFORM 1 FROM __PREFIX__controller_shard_lock WHERE shard_id = v_shard_id FOR UPDATE;
|
||||
|
||||
INSERT INTO __PREFIX__controller_messages (shard_id, node_id, data)
|
||||
VALUES (v_shard_id, p_node_id, p_data)
|
||||
RETURNING id INTO v_id;
|
||||
|
||||
PERFORM pg_notify('__PREFIX__controller_notify', '');
|
||||
RETURN v_id;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
Reference in New Issue
Block a user