Files
parrhesia/compose.node-sync-three-node-e2e.yaml
self f8cdeb388a
CI / Test (OTP 27.2 / Elixir 1.18.2) (push) Failing after 1m51s
CI / Test (OTP 28.4 / Elixir 1.19.4 + E2E) (push) Failing after 1m36s
feat: page historical sync backfill
Add an internal SYNC-PAGE websocket frame and use it from req_stream sync workers to backfill protected event history deterministically by (created_at, id) before starting the live tail.

The worker discovers a remote cutoff, ingests bounded ascending pages up to that cutoff without advancing the live cursor early, and only advances the cursor when the historical window is complete. The three-node Docker gap scenario now runs req_stream with a small backfill page size to exercise multi-page catch-up.
2026-05-21 13:21:23 +02:00

162 lines
6.5 KiB
YAML

services:
db-a:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: parrhesia_a
POSTGRES_USER: parrhesia
POSTGRES_PASSWORD: parrhesia
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 12
volumes:
- postgres-a-data:/var/lib/postgresql/data
db-b:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: parrhesia_b
POSTGRES_USER: parrhesia
POSTGRES_PASSWORD: parrhesia
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 12
volumes:
- postgres-b-data:/var/lib/postgresql/data
db-c:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_DB: parrhesia_c
POSTGRES_USER: parrhesia
POSTGRES_PASSWORD: parrhesia
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 12
volumes:
- postgres-c-data:/var/lib/postgresql/data
migrate-a:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: "no"
depends_on:
db-a:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-a:5432/parrhesia_a
POOL_SIZE: ${POOL_SIZE:-20}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
command: ["eval", "Parrhesia.Release.migrate()"]
migrate-b:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: "no"
depends_on:
db-b:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-b:5432/parrhesia_b
POOL_SIZE: ${POOL_SIZE:-20}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
command: ["eval", "Parrhesia.Release.migrate()"]
migrate-c:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: "no"
depends_on:
db-c:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-c:5432/parrhesia_c
POOL_SIZE: ${POOL_SIZE:-20}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
command: ["eval", "Parrhesia.Release.migrate()"]
parrhesia-a:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: unless-stopped
depends_on:
db-a:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-a:5432/parrhesia_a
POOL_SIZE: ${POOL_SIZE:-20}
PORT: 4413
PARRHESIA_RELAY_URL: ${PARRHESIA_NODE_A_RELAY_URL:-ws://parrhesia-a:4413/relay}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
PARRHESIA_RELAY_IDENTITY_PATH: /tmp/parrhesia-a/server_identity.json
PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE: ${PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_NODE_IDENTITY_PATH: /tmp/parrhesia-a/node_identity.json
PARRHESIA_NODE_IDENTITY_AUTO_GENERATE: ${PARRHESIA_NODE_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_SYNC_PATH: /tmp/parrhesia-a/sync_servers.json
PARRHESIA_LIMITS_MAX_FILTER_LIMIT: ${PARRHESIA_LIMITS_MAX_FILTER_LIMIT:-30000}
PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES: ${PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES:-60000}
PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW:-50000}
ports:
- "${PARRHESIA_NODE_A_HOST_PORT:-45231}:4413"
parrhesia-b:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: unless-stopped
depends_on:
db-b:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-b:5432/parrhesia_b
POOL_SIZE: ${POOL_SIZE:-20}
PORT: 4413
PARRHESIA_RELAY_URL: ${PARRHESIA_NODE_B_RELAY_URL:-ws://parrhesia-b:4413/relay}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
PARRHESIA_RELAY_IDENTITY_PATH: /tmp/parrhesia-b/server_identity.json
PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE: ${PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_NODE_IDENTITY_PATH: /tmp/parrhesia-b/node_identity.json
PARRHESIA_NODE_IDENTITY_AUTO_GENERATE: ${PARRHESIA_NODE_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_SYNC_PATH: /tmp/parrhesia-b/sync_servers.json
PARRHESIA_LIMITS_MAX_FILTER_LIMIT: ${PARRHESIA_LIMITS_MAX_FILTER_LIMIT:-30000}
PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES: ${PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES:-60000}
PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW:-50000}
ports:
- "${PARRHESIA_NODE_B_HOST_PORT:-45232}:4413"
parrhesia-c:
image: ${PARRHESIA_IMAGE:-parrhesia:latest}
restart: unless-stopped
depends_on:
db-c:
condition: service_healthy
environment:
DATABASE_URL: ecto://parrhesia:parrhesia@db-c:5432/parrhesia_c
POOL_SIZE: ${POOL_SIZE:-20}
PORT: 4413
PARRHESIA_RELAY_URL: ${PARRHESIA_NODE_C_RELAY_URL:-ws://parrhesia-c:4413/relay}
PARRHESIA_ACL_PROTECTED_FILTERS: ${PARRHESIA_ACL_PROTECTED_FILTERS}
PARRHESIA_RELAY_IDENTITY_PATH: /tmp/parrhesia-c/server_identity.json
PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE: ${PARRHESIA_RELAY_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_NODE_IDENTITY_PATH: /tmp/parrhesia-c/node_identity.json
PARRHESIA_NODE_IDENTITY_AUTO_GENERATE: ${PARRHESIA_NODE_IDENTITY_AUTO_GENERATE:-true}
PARRHESIA_SYNC_PATH: /tmp/parrhesia-c/sync_servers.json
PARRHESIA_LIMITS_MAX_FILTER_LIMIT: ${PARRHESIA_LIMITS_MAX_FILTER_LIMIT:-30000}
PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES: ${PARRHESIA_LIMITS_MAX_QUERY_CANDIDATES:-60000}
PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_IP_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_RELAY_MAX_EVENT_INGEST_PER_WINDOW:-50000}
PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW: ${PARRHESIA_LIMITS_MAX_EVENT_INGEST_PER_WINDOW:-50000}
ports:
- "${PARRHESIA_NODE_C_HOST_PORT:-45233}:4413"
volumes:
postgres-a-data:
postgres-b-data:
postgres-c-data: