# rust-fafb-q server configuration
# Copy this file to config.toml and adjust values for your environment.
# All sections are optional — defaults shown below are applied when omitted.
# Environment variables override file values (see env var names in comments).

# TCP listener for subscribe/publish connections.
[tcp]
bind_address = "127.0.0.1"  # FAFB_TCP_ADDRESS
port = 9876                  # FAFB_TCP_PORT
max_message_size = 1048576   # FAFB_MAX_MESSAGE_SIZE — max frame size in bytes (default 1MB, minimum 1024)
subscriber_channel_buffer = 1024         # per-subscriber delivery buffer size (default 1024)
slow_consumer_policy = "drop_for_slow"   # "drop_for_slow" or "disconnect_slow" (default: drop_for_slow)
slow_consumer_threshold = 100            # consecutive send failures before marking slow (default 100)
slow_consumer_disconnect_after = 1000    # consecutive drops before disconnect (disconnect_slow only, default 1000)
# idle_timeout_secs = 30           # FAFB_TCP_IDLE_TIMEOUT — seconds of inactivity before
                                    # closing a connection. Clients must send periodic Ping
                                    # frames (recommended every 10s) to stay connected.
                                    # 0 = disabled. Default: 30.

# HTTP server for publish, query, and fetch endpoints.
[http]
bind_address = "127.0.0.1"  # FAFB_HTTP_ADDRESS
port = 8080                  # FAFB_HTTP_PORT
max_fetch_response_bytes = 4194304  # max response size for HTTP fetch endpoint (default 4MB)
                                     # Larger than TCP frame limit (1MB) — serves as fallback for oversized messages

# Filesystem storage for queue durability.
[storage]
data_dir = "./data"                    # FAFB_DATA_DIR
fsync_strategy = "every_batch"         # "every_write" (max durability, slower), "every_batch" (default), "os_managed" (fastest, OS writeback)
batch_flush_interval_ms = 100          # interval between background flush cycles
batch_flush_size_bytes = 4194304       # early flush when a topic accumulates this many unflushed bytes (default 4MB, 0 = disabled)
max_open_fds = 1024                    # FAFB_MAX_OPEN_FDS — max open segment file descriptors (LRU eviction when exceeded)
max_segments_per_topic = 64            # oldest segments deleted when limit exceeded during rotation
retention_check_interval_secs = 60     # interval between retention enforcement sweeps (default 60s)
# index_interval = 256                   # records between sparse index entries (default 256, lower = faster seek)
# segment_merge_threshold_bytes = 16777216   # merge segments smaller than 16MB (default, 0 = disabled)
# compaction_interval_secs = 300             # seconds between merge sweeps (default 5 min)

# Logging configuration.
# When omitted, defaults to INFO level on stdout only (no file output).
# The RUST_LOG environment variable overrides the level setting below.
[logging]
level = "info"                         # FAFB_LOG_LEVEL / RUST_LOG — RUST_LOG syntax supported. Per-module examples:
                                       #   "info,rust_fafb_q::storage::fs=debug"  — debug storage segment ops
                                       #   "info,rust_fafb_q::auth=debug"         — debug auth attempts
                                       #   "info,rust_fafb_q::queue::engine=trace" — trace publish/consume
                                       # The RUST_LOG env var overrides this when set.
format = "text"                        # FAFB_LOG_FORMAT — "text" or "json"
stdout = true                          # write to stdout
file_enabled = false                   # write to rotating log files
file_dir = "./logs"                    # log file directory (created automatically)
file_prefix = "fafb-q"                # log file name prefix
rotation = "daily"                     # "daily" or "hourly"
max_age_days = 14                      # delete log files older than 14 days
max_total_size_mb = 50                 # delete oldest when total exceeds 50MB

# Graceful deployment / shutdown.
[deploy]
drain_timeout_secs = 30        # time for clients to disconnect voluntarily before force-close (0 = immediate)
shutdown_timeout_secs = 10     # time for engine/storage shutdown after drain
going_away_reason = "upgrade"  # reason in GoingAway frames: "upgrade", "maintenance", "shutdown"
# admin_api_key = ""            # API key for admin endpoints (/admin/*). Must be >= 24 characters. If not set, admin endpoints return 403.

# Metrics / observability.
[metrics]
enabled = true                         # FAFB_METRICS_ENABLED — set to false to disable Prometheus metrics endpoint and recorder overhead

# Hot-reload configuration.
# When watch_file is true, the server monitors the config file for changes
# and automatically reloads (with debounce). Config changes can also be
# triggered manually via POST /admin/reload regardless of this setting.
# These settings are Tier 3 (restart-only) — changing them requires a restart.
[hot_reload]
watch_file = false      # watch config file for changes and auto-reload (default: false)
debounce_secs = 2       # debounce window in seconds — coalesces rapid changes (default: 2)

# Cluster configuration.
# When enabled, this node joins a primary-backup cluster for replication and failover.
# Requires --features cluster at build time. All fields with (Tier 3) require restart.
# [cluster]
# enabled = false                              # (Tier 3) master switch
# node_id = 1                                  # (Tier 3) unique ID for this node (must be > 0)
# bind = "0.0.0.0:9877"                       # (Tier 3) node-to-node communication port
# peers = ["192.168.1.2:9877"]                # (Tier 3) all other nodes in the cluster
# heartbeat_interval_ms = 1000                 # (Tier 1) leader → follower heartbeat frequency
# failover_timeout_ms = 5000                   # (Tier 1) missed heartbeats before leader suspect
# failover_no_clients_timeout_ms = 30000       # (Tier 1) auto-promote when no client corroboration
# replication_buffer_max_entries = 100000       # (Tier 1) stream replay buffer (entry count)
# replication_buffer_max_bytes = 268435456     # (Tier 1) stream replay buffer (256MB)
# time_server = "pool.ntp.org"                 # (Tier 1) NTP server (empty = disabled)
# time_sync_interval_secs = 300                # (Tier 1) re-sync frequency
# clock_skew_warn_threshold_ms = 500           # (Tier 1) skew warning threshold
# cluster_secret = ""                          # (Tier 3) shared secret for node-to-node auth (≥32 chars)

# Queue engine tuning.
[queue]
max_depth = 100000                         # FAFB_MAX_DEPTH — max in-memory messages per topic
backpressure_policy = "DropOldest"         # FAFB_BACKPRESSURE_POLICY — "Reject", "DropOldest", or "Block"
max_redelivery_attempts = 5                # attempts before routing to DLQ
dlq_topic_suffix = "__dlq"                 # suffix for dead-letter topics ("" to disable)
default_topic_max_bytes = 268435456        # max bytes per topic (default 256MB, 0 = unlimited)
global_max_memory_bytes = 4294967296       # FAFB_GLOBAL_MAX_MEMORY_BYTES — global memory budget (default 4GB, 0 = unlimited)
max_consumer_groups_per_topic = 1000       # max consumer groups per topic
# disk_backed = false                      # FAFB_DISK_BACKED — when true, disk capacity gates publish instead of memory budget
# disk_capacity_threshold_pct = 90         # FAFB_DISK_CAPACITY_THRESHOLD_PCT — reject publishes when disk usage exceeds this % (disk_backed only)
# Note: cold_batch_size (default 256) is a ManagerConfig runtime parameter, not a TOML field.

# Namespaces — at least one required.
# Each namespace has its own API key and permission set.
# Permissions: "Subscribe", "Publish", "Query", "Fetch"

# Full access — push, pull, publish, query
[namespaces.default]
api_key = "change-me-in-production-key"   # minimum 24 characters
permissions = ["Subscribe", "Publish", "Query", "Fetch"]
# max_total_messages = 1000000            # per-namespace message quota (optional, default unlimited)
# max_topics = 10000                      # per-namespace topic limit (optional, default unlimited)
# topic_max_depth = 50000                 # override global max_depth for this namespace (optional)
# topic_max_bytes = 134217728             # override global default_topic_max_bytes (optional, 128MB)
# backpressure_policy = "Reject"          # override global backpressure for this namespace (optional)
# max_connections = 5000                  # per-namespace connection limit (optional, default unlimited)
# max_disk_bytes = 10737418240            # per-namespace disk quota in bytes (optional, default unlimited, 10GB shown)

# Retention policy — all fields optional. Omit section to keep data forever.
# When multiple limits are set, the most aggressive wins.
# Retention never deletes segments an active subscriber still needs.
# [namespaces.default.retention]
# max_age_secs = 604800                  # delete segments older than 7 days
# max_bytes = 10737418240                # delete oldest when total > 10GB per topic
# max_segments = 64                      # keep at most 64 segments per topic
# topic_inactive_secs = 604800           # reap entire topic after 7 days of inactivity (optional, default: no reaping)
# topic_reap_grace_period_secs = 86400   # grace period before hard delete (optional, default: 24 hours)
#
# Per-topic overrides — first matching pattern wins. 0 = never reap.
# [[namespaces.default.retention.topic_inactive_overrides]]
# pattern = "system.>"
# inactive_secs = 0

[namespaces.analytics]
api_key = "analytics-publish-only-key00"  # minimum 24 characters
permissions = ["Publish", "Query"]

# Pull-only consumer — can fetch but not subscribe (no server-side state)
[namespaces.batch-consumer]
api_key = "batch-consumer-key-00000000"   # minimum 24 characters
permissions = ["Fetch"]

# Legacy pattern — push subscribe + publish, no pull
[namespaces.streaming-only]
api_key = "streaming-only-key-000000000"  # minimum 24 characters
permissions = ["Subscribe", "Publish", "Query"]
