From cf1ded9f89834309532ce9a8e3935a5af409cf7a Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Tue, 1 Sep 2026 09:26:57 -0700 Subject: [PATCH 1/2] feat: listen_backlog --- README.md | 22 +- scripts/generate-schema.py | 343 -------------- scripts/schema-overrides.yaml | 642 --------------------------- templates/config.yaml | 3 + test/values-pgdog-config-extras.yaml | 4 +- values.yaml | 5 + 6 files changed, 30 insertions(+), 989 deletions(-) delete mode 100755 scripts/generate-schema.py delete mode 100644 scripts/schema-overrides.yaml diff --git a/README.md b/README.md index 0d8ab57..ae6d200 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ mounts yours instead: ```yaml usersSecret: name: my-pgdog-users # existing Secret in the same namespace - key: users.toml # key holding the users.toml content (default: users.toml) + key: users.toml # key holding the users.toml content (default: users.toml) ``` Create the Secret, for example: @@ -254,7 +254,7 @@ database hosts or the admin password sourced from a secrets manager: ```yaml configSecret: name: my-pgdog-config # existing Secret in the same namespace - key: pgdog.toml # key holding the pgdog.toml content (default: pgdog.toml) + key: pgdog.toml # key holding the pgdog.toml content (default: pgdog.toml) ``` Create the Secret, for example: @@ -291,7 +291,7 @@ otel: endpoint: https://otlp.example.com/v1/metrics # your OTLP endpoint datadogApiKeySecret: name: my-datadog # existing Secret in the same namespace - key: dd-api-key # key holding the API key (default: dd-api-key) + key: dd-api-key # key holding the API key (default: dd-api-key) ``` Create the Secret, for example: @@ -422,6 +422,22 @@ These settings control the TCP keep-alive behavior for database connections. All time values are in milliseconds. If not specified, system defaults are used. +### Connection storms + +`listenBacklog` controls the maximum number of pending client connections in +PgDog's listening TCP socket. The kernel caps the queue length at +`net.core.somaxconn`, so configure both values when increasing the connection backlog: + +```yaml +listenBacklog: 4096 +podSecurityContext: + sysctls: + - name: net.core.somaxconn + value: "4096" +``` + +Read more about configuring `sysctl` [here](https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/). + ## Contributions Contributions are welcome. Please open a pull request / issue with diff --git a/scripts/generate-schema.py b/scripts/generate-schema.py deleted file mode 100755 index 29fc59e..0000000 --- a/scripts/generate-schema.py +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/env python3 -"""Generate values.schema.json from Helm template .Values references. - -Scans all templates for .Values.* usage, infers types from context -(pgdog.intval → integer, | quote → string, toYaml → object, etc.), -and merges manually maintained overrides (enums, descriptions, required -fields) from scripts/schema-overrides.yaml. - -Usage: - python3 scripts/generate-schema.py # writes values.schema.json - python3 scripts/generate-schema.py --check # exits non-zero if schema is stale -""" - -import json -import os -import re -import sys -from pathlib import Path - -# Optional: PyYAML for overrides. Falls back gracefully if not installed. -try: - import yaml -except ImportError: - yaml = None - -REPO_ROOT = Path(__file__).resolve().parent.parent -TEMPLATES_DIR = REPO_ROOT / "templates" -SCHEMA_PATH = REPO_ROOT / "values.schema.json" -OVERRIDES_PATH = REPO_ROOT / "scripts" / "schema-overrides.yaml" - -# --------------------------------------------------------------------------- -# 1. Extract .Values references and their template context -# --------------------------------------------------------------------------- - -# Matches .Values.foo.bar.baz (captures the dotted path after .Values.) -VALUES_RE = re.compile(r"\.Values\.([a-zA-Z_][\w]*(?:\.[a-zA-Z_][\w]*)*)") - -# Context patterns that hint at a type. Order matters: first match wins. -# NOTE: boolean is never auto-inferred — it must come from overrides. -# Template `if .Values.X` is a truthiness check, not a type indicator. -CONTEXT_PATTERNS = [ - # pgdog.intval → integer (accepts int or underscore-separated string) - (re.compile(r'include\s+"pgdog\.intval".*\.Values\.{path}\b'), "integer"), - (re.compile(r'\.Values\.{path}\b.*\|\s*int\b'), "integer"), - # | toYaml / with .Values.X → object - (re.compile(r"\.Values\.{path}\b\s*\|\s*toYaml"), "object"), - (re.compile(r"toYaml\s+\.Values\.{path}\b"), "object"), - (re.compile(r"with\s+\.Values\.{path}\b\s"), "object"), - # | toToml → array - (re.compile(r"\.Values\.{path}\b\s*\|\s*toToml"), "array"), - # range .Values.X → array - (re.compile(r"range\s+\.Values\.{path}\b"), "array"), - # | quote → string (allow intermediate filters like `| default "foo" | quote`) - (re.compile(r"\.Values\.{path}\b[^}]*\|\s*quote"), "string"), -] - - -def scan_templates(): - """Return {dotted_path: set_of_inferred_types} from all template files.""" - refs = {} # path → set of type hints - - for tpl in TEMPLATES_DIR.rglob("*"): - if tpl.is_dir() or tpl.suffix not in (".yaml", ".yml", ".tpl", ".txt"): - continue - text = tpl.read_text() - - for m in VALUES_RE.finditer(text): - path = m.group(1) - if path not in refs: - refs[path] = set() - - # Try each context pattern to infer type - for pattern, typ in CONTEXT_PATTERNS: - concrete = pattern.pattern.replace("{path}", re.escape(path)) - if re.search(concrete, text): - refs[path].add(typ) - break - - return refs - - -# --------------------------------------------------------------------------- -# 2. Build a nested property tree -# --------------------------------------------------------------------------- - - -def build_tree(refs): - """Convert flat dotted paths into a nested dict. - - Each leaf is {"_types": set(), "_is_leaf": True}. - Intermediate nodes are plain dicts. - """ - tree = {} - for dotted, types in refs.items(): - parts = dotted.split(".") - node = tree - for i, part in enumerate(parts): - if part not in node: - node[part] = {} - node = node[part] - if i == len(parts) - 1: - node["_types"] = types - node["_is_leaf"] = True - return tree - - -# --------------------------------------------------------------------------- -# 3. Resolve types -# --------------------------------------------------------------------------- - -# Fields whose template usage looks boolean (if .Values.X) but are actually -# strings/numbers are handled via overrides. This function just picks the -# best single type from the inferred set. - -TYPE_PRIORITY = {"integer": 0, "string": 1, "array": 2, "object": 3, "boolean": 4} - - -def pick_type(types): - """Pick the most specific type from a set of inferred types.""" - if not types: - return "string" # safe default for unknown - # If we have both object and string (e.g. toYaml + quote in different - # contexts), prefer object since quote may be from a sub-field. - if "object" in types: - return "object" - if "array" in types: - return "array" - if "integer" in types: - return "integer" - # Return the highest-priority (most specific) type - return min(types, key=lambda t: TYPE_PRIORITY.get(t, 99)) - - -# --------------------------------------------------------------------------- -# 4. Load overrides -# --------------------------------------------------------------------------- - - -def load_overrides(): - """Load schema-overrides.yaml if it exists and PyYAML is available.""" - if yaml is None: - print("WARNING: PyYAML not installed; skipping overrides", file=sys.stderr) - return {} - if not OVERRIDES_PATH.exists(): - return {} - with open(OVERRIDES_PATH) as f: - data = yaml.safe_load(f) or {} - return data - - -# --------------------------------------------------------------------------- -# 5. Generate JSON Schema -# --------------------------------------------------------------------------- - -# Shared $defs that are referenced via $ref -DEFS = { - "resources": { - "type": "object", - "description": "Kubernetes resource requests and limits", - "additionalProperties": False, - "properties": { - "requests": { - "type": "object", - "additionalProperties": False, - "properties": { - "cpu": {"type": ["string", "number"]}, - "memory": {"type": "string"}, - }, - }, - "limits": { - "type": "object", - "additionalProperties": False, - "properties": { - "cpu": {"type": ["string", "number"]}, - "memory": {"type": "string"}, - }, - }, - }, - }, - "awsLb": { - "type": "object", - "description": "AWS Load Balancer Controller configuration", - "additionalProperties": False, - "properties": { - "enabled": {"type": "boolean", "description": "Enable AWS LB annotations"}, - "scheme": { - "type": "string", - "description": "Load balancer scheme", - "enum": ["internet-facing", "internal"], - }, - }, - }, - "flexibleType": { - "description": ( - "pgdog FlexibleType: a bare integer, or a string (UUID or " - "arbitrary key). Numbers render as bare TOML integers; strings " - "render quoted." - ), - "type": ["integer", "string"], - }, -} - -# Properties that should use a $ref instead of being auto-generated -REF_MAP = { - "resources": "#/$defs/resources", - "prometheusResources": "#/$defs/resources", - "gateway.resources": "#/$defs/resources", - "prometheusCollector.resources": "#/$defs/resources", - "service.aws": "#/$defs/awsLb", - "prometheusCollector.service.aws": "#/$defs/awsLb", -} - - -def apply_overrides(prop, override): - """Merge override keys into a property dict.""" - for key in ("description", "enum", "minimum", "maximum", "pattern", - "minItems", "maxItems"): - if key in override: - prop[key] = override[key] - if "type" in override: - prop["type"] = override["type"] - if "required" in override: - prop["required"] = override["required"] - if "items" in override: - prop["items"] = override["items"] - - -def tree_to_schema(tree, overrides, path_prefix=""): - """Recursively convert property tree to JSON Schema properties dict.""" - properties = {} - - for key, node in sorted(tree.items()): - if key.startswith("_"): - continue - - full_path = f"{path_prefix}.{key}" if path_prefix else key - override = overrides.get(full_path, {}) - - # Check if this should be a $ref - ref_path = REF_MAP.get(full_path) - if ref_path: - prop = {"$ref": ref_path} - if "description" in override: - prop["description"] = override["description"] - properties[key] = prop - continue - - is_leaf = node.get("_is_leaf", False) - types = node.get("_types", set()) - - # Filter out internal keys to find children - children = {k: v for k, v in node.items() - if not k.startswith("_") and isinstance(v, dict)} - - if children and not is_leaf: - # Pure object node - child_props = tree_to_schema(children, overrides, full_path) - prop = { - "type": "object", - "additionalProperties": False, - "properties": child_props, - } - elif children and is_leaf: - # Node that is both used directly AND has children - # This means the templates access both .Values.X and .Values.X.foo - # Treat as object with children - child_props = tree_to_schema(children, overrides, full_path) - prop = { - "type": "object", - "additionalProperties": False, - "properties": child_props, - } - else: - # Leaf node - resolved = pick_type(types) - prop = {"type": resolved} - - if resolved == "integer": - prop["minimum"] = 0 - if resolved == "array": - prop["items"] = {"type": "object"} - - apply_overrides(prop, override) - properties[key] = prop - - return properties - - -def generate(): - print("Scanning templates...", file=sys.stderr) - refs = scan_templates() - print(f" Found {len(refs)} .Values.* references", file=sys.stderr) - - tree = build_tree(refs) - overrides = load_overrides() - - properties = tree_to_schema(tree, overrides) - - schema = { - "$schema": "https://json-schema.org/draft-07/schema#", - "title": "PgDog Helm Chart Values", - "description": ( - "Schema for validating PgDog Helm chart values. " - "All object levels use additionalProperties: false to catch typos. " - "Generated by scripts/generate-schema.py — do not edit by hand." - ), - "type": "object", - "additionalProperties": False, - "properties": properties, - "$defs": DEFS, - } - - return schema - - -def main(): - check_mode = "--check" in sys.argv - - schema = generate() - new_content = json.dumps(schema, indent=2, ensure_ascii=False) + "\n" - - if check_mode: - if SCHEMA_PATH.exists(): - existing = SCHEMA_PATH.read_text() - if existing == new_content: - print("values.schema.json is up to date.", file=sys.stderr) - sys.exit(0) - else: - print( - "values.schema.json is STALE. Run: python3 scripts/generate-schema.py", - file=sys.stderr, - ) - sys.exit(1) - else: - print("values.schema.json does not exist.", file=sys.stderr) - sys.exit(1) - - SCHEMA_PATH.write_text(new_content) - print(f"Wrote {SCHEMA_PATH}", file=sys.stderr) - - -if __name__ == "__main__": - main() diff --git a/scripts/schema-overrides.yaml b/scripts/schema-overrides.yaml deleted file mode 100644 index f51a912..0000000 --- a/scripts/schema-overrides.yaml +++ /dev/null @@ -1,642 +0,0 @@ -# Schema overrides for values that can't be fully inferred from templates. -# Keys are dotted paths matching .Values.* references. -# Supported fields: type, description, enum, minimum, maximum, pattern, -# required, items, minItems, maxItems - -# --- Top-level settings --- -nameOverride: - description: Override the chart name -fullnameOverride: - description: Override the full release name -labels: - description: Custom labels for resources -selectorLabels: - description: Custom selector labels for resources -annotations: - description: Custom annotations for the deployment -podLabels: - description: Custom labels for pods -podAnnotations: - description: Custom annotations for pods -restartOnConfigChange: - type: boolean - description: Trigger rolling restart when pgdog config changes -clusterName: - description: Kubernetes cluster name, added as a label to Prometheus metrics - -# --- Image --- -image.repository: - type: string - description: Docker image repository -image.tag: - type: string - description: Docker image tag (defaults to Chart appVersion) -image.digest: - type: string - description: Image digest (overrides tag when specified) -image.pullPolicy: - enum: ["Always", "IfNotPresent", "Never"] - description: Image pull policy -image.name: - type: string - description: "DEPRECATED: Full image name (use repository and tag instead)" - -# --- Ports --- -port: - type: integer - description: Port on which PgDog will run - minimum: 1 - maximum: 65535 -healthcheckPort: - type: integer - description: Port for healthcheck endpoint - minimum: 1 - maximum: 65535 -openMetricsPort: - type: integer - description: Port for OpenMetrics (Prometheus) export - minimum: 1 - maximum: 65535 -prometheusPort: - type: integer - description: Port for the Prometheus sidecar - minimum: 1 - maximum: 65535 - -# --- Replicas --- -replicas: - type: integer - description: Number of PgDog replicas - minimum: 1 - -# --- Scheduling --- -priorityClassName: - type: string - description: PriorityClass name for pgdog pods -terminationGracePeriodSeconds: - type: integer - description: Grace period for pod termination -preStopSleepSeconds: - type: integer - description: Delay before stopping container to allow endpoint updates - -# --- Probes (free-form objects) --- -livenessProbe: - type: object - description: Container liveness probe configuration -readinessProbe: - type: object - description: Container readiness probe configuration -startupProbe: - type: object - description: Container startup probe configuration -strategy: - type: object - description: Deployment rollout strategy - -# --- StatefulSet --- -statefulSet.enabled: - type: boolean - description: Deploy as StatefulSet instead of Deployment - -# --- Env --- -env: - type: array - description: Custom environment variables for the pgdog container - items: - type: object - required: ["name"] - properties: - name: - type: string - value: - type: string - valueFrom: - type: object - -# --- Extra containers/volumes --- -extraInitContainers: - type: array - description: Additional init containers - items: - type: object -extraVolumes: - type: array - description: Additional volumes for the pod - items: - type: object -extraVolumeMounts: - type: array - description: Additional volume mounts for the pgdog container - items: - type: object - -# --- Resources --- -noCpuLimits: - type: boolean - description: Remove CPU limits from containers -resources: - description: Resource requests and limits for the pgdog container -prometheusResources: - description: Resource requests and limits for the prometheus sidecar - -# --- Image pull secrets --- -imagePullSecrets: - type: array - description: Image pull secrets for private registries - items: - type: object - additionalProperties: false - required: ["name"] - properties: - name: - type: string - -# --- Logging --- -logFormat: - enum: ["text", "json"] - description: Log output format -logLevel: - enum: ["error", "warn", "info", "debug", "trace", "off"] - description: Log level (RUST_LOG syntax) -logConnections: - type: ["boolean", "string"] - description: Log connections -logDisconnections: - type: ["boolean", "string"] - description: Log disconnections - -# --- Pool & connection settings --- -poolerMode: - enum: ["transaction", "session", "statement"] - description: Connection pooler mode -loadBalancingStrategy: - enum: ["round_robin", "random", "least_active_connections"] - description: Load balancing strategy -workers: - type: integer - minimum: 1 - description: Number of worker threads -defaultPoolSize: - type: integer - minimum: 1 - description: Default connection pool size -connectAttempts: - type: integer - minimum: 1 - description: Number of connection attempts - -# --- Boolean/string fields where templates use both forms --- -dryRun: - type: ["boolean", "string"] - description: Enable dry run mode -crossShardDisabled: - type: ["boolean", "string"] - description: Disable cross-shard queries -expandedExplain: - type: ["boolean", "string"] - description: Enable expanded explain -tlsClientRequired: - type: ["boolean", "string"] - description: Require TLS client certificates -mirrorExposure: - type: ["number", "string"] - description: Mirror traffic exposure ratio - -# --- Query parser --- -queryParser: - type: string - enum: ["auto", "on", "off", "session_control", "session_control_and_locks"] - description: Query parser mode -queryParserEnabled: - type: boolean - description: "DEPRECATED: use queryParser instead" - -# --- TLS --- -tlsGenerateSelfSignedCert: - type: boolean - description: Generate self-signed TLS certificate -rdsCertificateBundle.enabled: - type: boolean - description: Mount the RDS CA bundle -rdsCertificateBundle.type: - enum: ["global", "govcloud"] - description: RDS CA bundle type - -# --- Databases array --- -databases: - type: array - description: Database entries for pgdog.toml - items: - type: object - additionalProperties: false - required: ["name", "host"] - properties: - name: - type: string - host: - type: string - port: - type: integer - minimum: 1 - maximum: 65535 - shard: - type: integer - minimum: 0 - databaseName: - type: string - user: - type: string - password: - type: string - poolSize: - type: integer - minimum: 0 - minPoolSize: - type: integer - minimum: 0 - poolerMode: - type: string - statementTimeout: - type: integer - minimum: 0 - idleTimeout: - type: integer - minimum: 0 - readOnly: - type: boolean - role: - type: string - serverLifetime: - type: integer - minimum: 0 - reshardingOnly: - type: boolean - lbWeight: - type: integer - minimum: 0 - -# --- Users array --- -users: - type: array - description: User entries for users.toml - items: - type: object - -# --- Mirrors array --- -mirrors: - type: array - description: Mirror database entries - items: - type: object - additionalProperties: false - required: ["sourceDb", "destinationDb"] - properties: - sourceDb: - type: string - destinationDb: - type: string - queueLength: - type: integer - minimum: 0 - queueDepth: - type: integer - minimum: 0 - exposure: - type: number - level: - type: string - -# --- Query parser array --- -queryParsers: - type: array - description: Per-database query parser entries - items: - type: object - additionalProperties: false - required: ["database", "level"] - properties: - database: - type: string - level: - type: string - engine: - type: string - -# --- Sharded schemas --- -shardedSchemas: - type: array - description: Sharded schema entries - items: - type: object - additionalProperties: false - required: ["database", "shard"] - properties: - database: - type: string - name: - type: string - shard: - type: integer - minimum: 0 - -# --- Sharded tables --- -shardedTables: - type: array - description: Sharded table entries - items: - type: object - additionalProperties: false - required: ["database", "column", "dataType"] - properties: - database: - type: string - name: - type: string - column: - type: string - dataType: - type: string - mapping: - type: array - description: List/range/default sharding rules for this table - items: - type: object - additionalProperties: false - required: ["shard"] - properties: - shard: - type: integer - minimum: 0 - values: - type: array - items: - $ref: "#/$defs/flexibleType" - start: - $ref: "#/$defs/flexibleType" - end: - $ref: "#/$defs/flexibleType" - -# --- Sharded mappings (Deprecated) --- -shardedMappings: - type: array - description: Sharded mapping entries - items: - type: object - additionalProperties: false - required: ["database", "column", "kind", "shard"] - properties: - database: - type: string - column: - type: string - kind: - type: string - enum: ["list", "range"] - shard: - type: integer - minimum: 0 - values: - type: array - items: - $ref: "#/$defs/flexibleType" - start: - $ref: "#/$defs/flexibleType" - end: - $ref: "#/$defs/flexibleType" - -# --- Omnisharded tables --- -omnishardedTables: - type: array - description: Omnisharded table entries - items: - type: object - additionalProperties: false - required: ["database", "tables"] - properties: - database: - type: string - sticky: - type: boolean - tables: - type: array - items: - type: string - -# --- Plugins --- -plugins: - type: array - description: Plugin entries - items: - type: object - additionalProperties: false - required: ["name"] - properties: - name: - type: string - config: - type: string - -# --- Service --- -service.type: - enum: ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"] - description: Service type -service.trafficDistribution: - type: string - description: Traffic distribution mode - -# --- Node scheduling --- -nodeSelector: - type: object - description: Node selector for pod scheduling -tolerations: - type: array - description: Pod tolerations - items: - type: object -affinity: - type: object - description: Pod affinity rules -topologySpreadConstraints: - type: array - description: Topology spread constraints - items: - type: object -multiAz.enabled: - type: boolean - description: Enable spreading pods evenly across availability zones -multiAz.whenUnsatisfiable: - enum: ["DoNotSchedule", "ScheduleAnyway"] - description: Action to take when the zone spread constraint cannot be satisfied - -# --- Pod anti-affinity --- -podAntiAffinity.enabled: - type: boolean - description: Enable default anti-affinity rules -podAntiAffinity.type: - enum: ["soft", "hard"] - description: Anti-affinity type - -# --- PDB --- -podDisruptionBudget.enabled: - type: boolean - description: Enable PDB -podDisruptionBudget.minAvailable: - type: ["integer", "string"] - description: "Minimum available pods (number or percentage string)" -podDisruptionBudget.maxUnavailable: - type: ["integer", "string"] - description: "Maximum unavailable pods (number or percentage string)" - -# --- Service account --- -serviceAccount.create: - type: boolean -serviceAccount.name: - type: string - -# --- RBAC --- -rbac.create: - type: boolean - -# --- External secrets --- -externalSecrets.enabled: - type: boolean -externalSecrets.create: - type: boolean -externalSecrets.name: - type: string -externalSecrets.secretName: - type: string -externalSecrets.refreshInterval: - type: string -externalSecrets.secretStoreRef.name: - type: string -externalSecrets.secretStoreRef.kind: - enum: ["SecretStore", "ClusterSecretStore"] -externalSecrets.remoteRefs: - type: array - items: - type: object - -# --- Grafana remote write --- -grafanaRemoteWrite.url: - type: string -grafanaRemoteWrite.basicAuth.username: - type: string -grafanaRemoteWrite.basicAuth.password: - type: string -grafanaRemoteWrite.queueConfig.capacity: - type: integer - minimum: 1 -grafanaRemoteWrite.queueConfig.maxShards: - type: integer - minimum: 1 -grafanaRemoteWrite.queueConfig.minShards: - type: integer - minimum: 1 -grafanaRemoteWrite.queueConfig.maxSamplesPerSend: - type: integer - minimum: 1 -grafanaRemoteWrite.queueConfig.batchSendDeadline: - type: string -grafanaRemoteWrite.queueConfig.minBackoff: - type: string -grafanaRemoteWrite.queueConfig.maxBackoff: - type: string - -# --- Service monitor --- -serviceMonitor.enabled: - type: boolean - -# --- Prometheus collector labels/scheduling --- -prometheusCollector.labels: - type: object -prometheusCollector.selectorLabels: - type: object -prometheusCollector.podAnnotations: - type: object -prometheusCollector.nodeSelector: - type: object -prometheusCollector.tolerations: - type: array - items: - type: object -prometheusCollector.affinity: - type: object -prometheusCollector.service.annotations: - type: object - -# --- Prometheus collector --- -prometheusCollector.enabled: - type: boolean -prometheusCollector.image.pullPolicy: - enum: ["Always", "IfNotPresent", "Never"] -prometheusCollector.port: - type: integer - minimum: 1 - maximum: 65535 -prometheusCollector.scrapeInterval: - type: string -prometheusCollector.evaluationInterval: - type: string -prometheusCollector.basicAuth.enabled: - type: boolean -prometheusCollector.basicAuth.username: - type: string -prometheusCollector.basicAuth.password: - type: string -prometheusCollector.basicAuth.passwordHash: - type: string -prometheusCollector.tls.enabled: - type: boolean -prometheusCollector.storage.size: - type: string -prometheusCollector.retention.time: - type: string -prometheusCollector.retention.size: - type: string -prometheusCollector.service.type: - enum: ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"] - -# --- Security contexts (free-form) --- -securityContext: - type: object - description: Container security context -podSecurityContext: - type: object - description: Pod security context - -# --- OpenTelemetry --- -otel.headers: - type: object - description: Custom headers for OTEL export - -# --- Rewrite --- -rewrite.enabled: - type: ["boolean", "string"] - -# --- QoS --- -qos.enabled: - type: boolean -queryStats.enabled: - type: boolean -control.enabled: - type: boolean -control.endpoint: - type: string -control.token: - type: string - -# --- Two-phase commit booleans --- -twoPhaseCommit: - type: boolean -twoPhaseCommitAuto: - type: boolean -omnishardedSticky: - type: boolean -reloadSchemaOnDdl: - type: boolean -cutoverSaveConfig: - type: boolean -tcpKeepalive: - type: boolean diff --git a/templates/config.yaml b/templates/config.yaml index cb1c86a..481c2de 100644 --- a/templates/config.yaml +++ b/templates/config.yaml @@ -13,6 +13,9 @@ data: {{- if hasKey .Values "port" }} port = {{ include "pgdog.intval" .Values.port }} {{- end }} + {{- if hasKey .Values "listenBacklog" }} + listen_backlog = {{ include "pgdog.intval" .Values.listenBacklog }} + {{- end }} {{- if hasKey .Values "workers" }} workers = {{ include "pgdog.intval" .Values.workers }} {{- end }} diff --git a/test/values-pgdog-config-extras.yaml b/test/values-pgdog-config-extras.yaml index 5c9169c..689c09a 100644 --- a/test/values-pgdog-config-extras.yaml +++ b/test/values-pgdog-config-extras.yaml @@ -1,9 +1,11 @@ # Test recently-added pgdog-config settings. -# Covers: ban_replica_lag*, 2PC WAL persistence, resharding copy retries, +# Covers: listen_backlog, ban_replica_lag*, 2PC WAL persistence, resharding copy retries, # query_log, rewrite_shard_key_updates, unique_id_*, cutover_*, # tcp user_timeout/congestion_control, mirroring queue_length/level, # query_parsers table, database lb_weight/resharding_only, multi_tenant, otel. +listenBacklog: 4_096 + banReplicaLag: 60_000 banReplicaLagBytes: 10_000_000 diff --git a/values.yaml b/values.yaml index f218531..6da4e4d 100644 --- a/values.yaml +++ b/values.yaml @@ -61,6 +61,11 @@ image: # host: "::" # port on which PgDog will run. port: 6432 +# listenBacklog is the maximum number of pending client connections queued by +# the listening socket. The kernel caps the effective value at +# net.core.somaxconn, so raise both settings when increasing this value. +# Defaults to 1024. This setting cannot be changed at runtime. +# listenBacklog: 1024 # healthcheckPort on which PgDog will expose healthcheck endpoint # (if not specified, no separate healthcheck port is configured) # healthcheckPort: 8080 From 74294165a036183432727687c56af9bd77cdf6c6 Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Tue, 1 Sep 2026 09:28:27 -0700 Subject: [PATCH 2/2] chart version --- Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index c3e2816..b61dd42 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -1,4 +1,4 @@ apiVersion: v1 name: pgdog -version: v0.75 -appVersion: "v0.1.52" +version: v0.76 +appVersion: "v0.1.56"