codeant-ai-for-open-source[bot] commented on code in PR #38597:
URL: https://github.com/apache/superset/pull/38597#discussion_r2923771521


##########
helm/superset/templates/_helpers.tpl:
##########
@@ -61,83 +75,569 @@ Create chart name and version as used by the chart label.
   {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" -}}
 {{- end -}}
 
+{{/*
+Common labels for all resources - follows Kubernetes recommended labels
+https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
+*/}}
+{{- define "superset.labels" -}}
+helm.sh/chart: {{ include "superset.chart" . }}
+{{ include "superset.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/part-of: superset
+{{- if .Values.extraLabels }}
+{{ toYaml .Values.extraLabels }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Selector labels - used by selectors and matchLabels
+*/}}
+{{- define "superset.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Component labels - extends superset.labels with component-specific labels
+Usage: {{ include "superset.componentLabels" (dict "component" "web" "root" .) 
}}
+*/}}
+{{- define "superset.componentLabels" -}}
+{{ include "superset.labels" .root }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+{{/*
+Component selector labels - for matchLabels with component
+Usage: {{ include "superset.componentSelectorLabels" (dict "component" "web" 
"root" .) }}
+*/}}
+{{- define "superset.componentSelectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" .root }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+
+{{- define "superset.config" }}
+{{- /* Check for deprecated configuration values */}}
+{{- include "superset.checkDeprecatedValues" . }}
+{{- /* SECURITY: Validate admin password is set if admin creation is enabled 
*/}}
+{{- /* Note: JWT secret validation is in deployment-ws.yaml since websocket 
config is in a separate secret */}}
+{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) 
(eq .Values.init.adminUser.password "")) }}
+{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password 
is empty. You must set a secure password using --set 
init.adminUser.password='your-password' or via external secret." }}
+{{- end }}
+{{- /* PRODUCTION: Validate resource limits are set for production deployments 
*/}}
+{{- if and (not .Values.resources.limits) (not .Values.resources.requests) }}
+{{- /* Note: This is a warning - pre-install validation job will also check 
this */}}
+{{- /* Resource limits are critical for production to prevent resource 
exhaustion */}}
+{{- end }}
 
-{{- define "superset-config" }}
 import os
+{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig 
.Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled 
}}
 from flask_caching.backends.rediscache import RedisCache
+{{- end }}
 
 def env(key, default=None):
     return os.getenv(key, default)
 
-# Redis Base URL
-{{- if .Values.supersetNode.connections.redis_password }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_USER', 
'')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Database Configuration - Superset always requires a database */}}
+{{- if .Values.database.uri }}
+SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
 {{- else }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Determine database host - use explicit host, or default to service name 
*/}}
+{{- $dbHost := .Values.database.host }}
+{{- if not $dbHost }}
+{{- if .Values.cluster.databaseServiceName }}
+{{- $dbHost = .Values.cluster.databaseServiceName }}
+{{- else }}
+{{- $dbHost = printf "%s-postgresql" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $driver := .Values.database.driver | default "postgresql+psycopg2" }}
+{{- $sslParams := "" }}
+{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
+{{- $sslMode := .Values.database.ssl.mode | default "require" }}
+{{- $sslParams = printf "?sslmode=%s" $sslMode }}
+{{- end }}
+SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{{ .Values.database.user }}:{{ 
.Values.database.password }}@{{ $dbHost }}:{{ .Values.database.port }}/{{ 
.Values.database.name }}{{ $sslParams }}"
+{{- end }}
+{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
+SQLALCHEMY_TRACK_MODIFICATIONS = {{ 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | lower }}

Review Comment:
   **Suggestion:** Rendering booleans with `| lower` produces Python literals 
`true`/`false`, which are invalid in Python config files and will crash 
Superset config loading when this option is set. Render explicit `True`/`False` 
instead. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Web and Celery pods fail loading generated config.
   - ⚠️ Helm value override for this setting becomes unsafe.
   ```
   </details>
   
   ```suggestion
   SQLALCHEMY_TRACK_MODIFICATIONS = {{ if 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS }}True{{ else }}False{{ end }}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Set `config.SQLALCHEMY_TRACK_MODIFICATIONS: true` in Helm values; this 
key is
   explicitly consumed at `helm/superset/templates/_helpers.tpl:167`.
   
   2. Run `helm install` so `secret-superset-config.yaml` renders 
`superset_config.py` via
   `include "superset.config"` at 
`helm/superset/templates/secret-superset-config.yaml:41`.
   
   3. Deployments mount that generated config Secret at `/app/pythonpath`
   (`deployment.yaml:143-146`, `deployment-worker.yaml:141-144`,
   `deployment-beat.yaml:130-133`, `deployment-flower.yaml:118-121`).
   
   4. On startup commands (`values.yaml:632-636`, `777-780`, `893-897`, 
`983-987`),
   Superset/Celery import config and hit `SQLALCHEMY_TRACK_MODIFICATIONS = 
true`, which is
   invalid Python identifier usage (`true` instead of `True`), causing startup 
failure.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** helm/superset/templates/_helpers.tpl
   **Line:** 167:167
   **Comment:**
        *Type Error: Rendering booleans with `| lower` produces Python literals 
`true`/`false`, which are invalid in Python config files and will crash 
Superset config loading when this option is set. Render explicit `True`/`False` 
instead.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=02fc8c8ce79e0e557e473df0413fdaf23d2b6e0a2cf2c21e126bef27b02bef82&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=02fc8c8ce79e0e557e473df0413fdaf23d2b6e0a2cf2c21e126bef27b02bef82&reaction=dislike'>👎</a>



##########
helm/superset/templates/_helpers.tpl:
##########
@@ -61,83 +75,569 @@ Create chart name and version as used by the chart label.
   {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" -}}
 {{- end -}}
 
+{{/*
+Common labels for all resources - follows Kubernetes recommended labels
+https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
+*/}}
+{{- define "superset.labels" -}}
+helm.sh/chart: {{ include "superset.chart" . }}
+{{ include "superset.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/part-of: superset
+{{- if .Values.extraLabels }}
+{{ toYaml .Values.extraLabels }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Selector labels - used by selectors and matchLabels
+*/}}
+{{- define "superset.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Component labels - extends superset.labels with component-specific labels
+Usage: {{ include "superset.componentLabels" (dict "component" "web" "root" .) 
}}
+*/}}
+{{- define "superset.componentLabels" -}}
+{{ include "superset.labels" .root }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+{{/*
+Component selector labels - for matchLabels with component
+Usage: {{ include "superset.componentSelectorLabels" (dict "component" "web" 
"root" .) }}
+*/}}
+{{- define "superset.componentSelectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" .root }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+
+{{- define "superset.config" }}
+{{- /* Check for deprecated configuration values */}}
+{{- include "superset.checkDeprecatedValues" . }}
+{{- /* SECURITY: Validate admin password is set if admin creation is enabled 
*/}}
+{{- /* Note: JWT secret validation is in deployment-ws.yaml since websocket 
config is in a separate secret */}}
+{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) 
(eq .Values.init.adminUser.password "")) }}
+{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password 
is empty. You must set a secure password using --set 
init.adminUser.password='your-password' or via external secret." }}
+{{- end }}
+{{- /* PRODUCTION: Validate resource limits are set for production deployments 
*/}}
+{{- if and (not .Values.resources.limits) (not .Values.resources.requests) }}
+{{- /* Note: This is a warning - pre-install validation job will also check 
this */}}
+{{- /* Resource limits are critical for production to prevent resource 
exhaustion */}}
+{{- end }}
 
-{{- define "superset-config" }}
 import os
+{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig 
.Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled 
}}
 from flask_caching.backends.rediscache import RedisCache
+{{- end }}
 
 def env(key, default=None):
     return os.getenv(key, default)
 
-# Redis Base URL
-{{- if .Values.supersetNode.connections.redis_password }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_USER', 
'')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Database Configuration - Superset always requires a database */}}
+{{- if .Values.database.uri }}
+SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
 {{- else }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Determine database host - use explicit host, or default to service name 
*/}}
+{{- $dbHost := .Values.database.host }}
+{{- if not $dbHost }}
+{{- if .Values.cluster.databaseServiceName }}
+{{- $dbHost = .Values.cluster.databaseServiceName }}
+{{- else }}
+{{- $dbHost = printf "%s-postgresql" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $driver := .Values.database.driver | default "postgresql+psycopg2" }}
+{{- $sslParams := "" }}
+{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
+{{- $sslMode := .Values.database.ssl.mode | default "require" }}
+{{- $sslParams = printf "?sslmode=%s" $sslMode }}
+{{- end }}
+SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{{ .Values.database.user }}:{{ 
.Values.database.password }}@{{ $dbHost }}:{{ .Values.database.port }}/{{ 
.Values.database.name }}{{ $sslParams }}"
+{{- end }}
+{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
+SQLALCHEMY_TRACK_MODIFICATIONS = {{ 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | lower }}
+{{- else }}
+SQLALCHEMY_TRACK_MODIFICATIONS = False
 {{- end }}
 
-# Redis URL Params
-{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-REDIS_URL_PARAMS = f"?ssl_cert_reqs={env('REDIS_SSL_CERT_REQS')}"
+{{- /* Redis Configuration - only if Redis cache is configured */}}
+{{- if .Values.cache.enabled }}
+{{- if .Values.cache.cacheUrl }}
+CACHE_REDIS_URL = {{ .Values.cache.cacheUrl | quote }}
+{{- else }}
+{{- /* Automatically use rediss (SSL) protocol when SSL is enabled, otherwise 
use redis */}}
+{{- /* Determine Redis host - use explicit host, or default to service name 
*/}}
+{{- $redisHost := .Values.cache.host }}
+{{- if not $redisHost }}
+{{- if .Values.cluster.redisServiceName }}
+{{- $redisHost = .Values.cluster.redisServiceName }}
+{{- else }}
+{{- $redisHost = printf "%s-redis-headless" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $redisUser := .Values.cache.user | default "" }}
+{{- $redisPort := .Values.cache.port }}
+{{- $redisPassword := .Values.cache.password }}
+{{- $useSSL := and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+{{- if $redisPassword }}
+{{- if $redisUser }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisUser }}:{{ $redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://:{{ 
$redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- if $useSSL }}
+{{- $sslCertReqs := .Values.cache.ssl.ssl_cert_reqs | default "required" }}
+REDIS_URL_PARAMS = f"?ssl_cert_reqs={{ $sslCertReqs }}"
 {{- else }}
 REDIS_URL_PARAMS = ""
-{{- end}}
-
-# Build Redis URLs
-CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_DB', 1)}{REDIS_URL_PARAMS}"
-CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_CELERY_DB', 
0)}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- $cacheDb := .Values.cache.cacheDb | default 1 }}
+CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{{ $cacheDb }}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- if .Values.cache.celeryUrl }}
+CELERY_REDIS_URL = {{ .Values.cache.celeryUrl | quote }}
+{{- else if not .Values.cache.cacheUrl }}
+{{- $celeryDb := .Values.cache.celeryDb | default 0 }}
+CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{{ $celeryDb }}{REDIS_URL_PARAMS}"
+{{- else }}
+{{- /* SECURITY: If cacheUrl is set but celeryUrl is not, Celery will fail. 
Validate this. */}}
+{{- if or .Values.config.celeryConfig (not .Values.cache.enabled) }}
+{{- /* Custom celeryConfig provided or cache disabled - OK */}}
+{{- else }}
+{{- fail "CONFIGURATION ERROR: cache.cacheUrl is set but cache.celeryUrl is 
not set. When using cacheUrl, you must also set celeryUrl for Celery to work. 
Alternatively, set config.celeryConfig to provide a custom Celery 
configuration." }}
+{{- end }}
+{{- end }}
+{{- end }}
 
-MAPBOX_API_KEY = env('MAPBOX_API_KEY', '')
+{{- /* Cache Configuration */}}
+{{- if .Values.config.cacheConfig }}
+CACHE_CONFIG = {{ .Values.config.cacheConfig | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
 CACHE_CONFIG = {
-      'CACHE_TYPE': 'RedisCache',
-      'CACHE_DEFAULT_TIMEOUT': 300,
-      'CACHE_KEY_PREFIX': 'superset_',
-      'CACHE_REDIS_URL': CACHE_REDIS_URL,
+    'CACHE_TYPE': 'RedisCache',
+    'CACHE_DEFAULT_TIMEOUT': {{ .Values.cache.defaultTimeout | default 
(.Values.config.cacheDefaultTimeout | default 86400) | int }},
+    'CACHE_KEY_PREFIX': {{ .Values.cache.keyPrefix | default "superset_" | 
quote }},
+    'CACHE_REDIS_URL': CACHE_REDIS_URL,
 }
+{{- end }}
+
+{{- if .Values.config.dataCacheConfig }}
+DATA_CACHE_CONFIG = {{ .Values.config.dataCacheConfig | toJson | indent 2 }}
+{{- else if .Values.config.cacheConfig }}
 DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- else if .Values.cache.enabled }}
+DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- end }}
 
+{{- /* SQLLAB_ASYNC_TIME_LIMIT_SEC - Required for async_queries module import 
(default: 6 hours) */}}
+{{- /* This MUST be set before Celery config imports async_queries, as it 
accesses current_app.config at module level */}}
+{{- if .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC }}
+SQLLAB_ASYNC_TIME_LIMIT_SEC = {{ .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC | 
int }}
+{{- else }}
+from datetime import timedelta
+SQLLAB_ASYNC_TIME_LIMIT_SEC = int(timedelta(hours=6).total_seconds())
+{{- end }}
 
-if os.getenv("SQLALCHEMY_DATABASE_URI"):
-    SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
-else:
-    {{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else }}
-    {{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 
'mysql'." .Values.supersetNode.connections.db_type) }}
-    {{- end }}
+{{- /* Celery Configuration */}}
+{{- if .Values.config.celeryConfig }}
+{{- if kindIs "string" .Values.config.celeryConfig }}
+{{ .Values.config.celeryConfig }}
+{{- else }}
+class CeleryConfig:
+{{- range $key, $value := .Values.config.celeryConfig }}
+    {{ $key }} = {{ $value | toJson }}
+{{- end }}
 
-SQLALCHEMY_TRACK_MODIFICATIONS = True
+CELERY_IMPORTS = CeleryConfig.imports
+CELERY_CONFIG = CeleryConfig
+{{- end }}
+{{- else if .Values.cache.enabled }}
+from celery.schedules import crontab
+from datetime import timedelta
 
 class CeleryConfig:
-  imports  = ("superset.sql_lab", )
-  broker_url = CELERY_REDIS_URL
-  result_backend = CELERY_REDIS_URL
+    imports = (
+        "superset.sql_lab",
+        "superset.tasks.scheduler",
+        "superset.tasks.thumbnails",
+        "superset.tasks.cache",
+        # NOTE: async_queries is temporarily excluded due to a bug where it 
accesses current_app.config
+        # at module import time without an app context. This causes 
worker/beat/flower to crash.
+        # TODO: Re-enable when Superset fixes the issue or provides a 
workaround
+        # "superset.tasks.async_queries",  # REQUIRED for GAQ
+    )
+    broker_connection_retry_on_startup = True
+    worker_prefetch_multiplier = 10
+    task_acks_late = True
+    broker_url = CELERY_REDIS_URL
+    result_backend = CELERY_REDIS_URL
+    task_annotations = {
+        "sql_lab.get_sql_results": {
+            "rate_limit": "100/s",
+        },
+    }
+    beat_schedule = {
+        "reports.scheduler": {
+            "task": "reports.scheduler",
+            "schedule": crontab(minute="*", hour="*"),
+            "options": {"expires": int(timedelta(weeks=1).total_seconds())},
+        },
+        "reports.prune_log": {
+            "task": "reports.prune_log",
+            "schedule": crontab(minute=0, hour=0),
+        },
+    }
 
+CELERY_IMPORTS = CeleryConfig.imports
 CELERY_CONFIG = CeleryConfig
+{{- end }}
+
+{{- /* Celery Worker Health Check - File-based health probes for Kubernetes 
*/}}
+{{- /* See: 
https://medium.com/ambient-innovation/health-checks-for-celery-in-kubernetes-cf3274a3e106
 */}}
+{{- /* NOTE: These signals only fire for Celery workers, not beat or flower 
*/}}
+{{- if and .Values.supersetWorker.healthCheck 
.Values.supersetWorker.healthCheck.enabled }}
+# Celery Worker Health Check Configuration
+# File paths are injected at deploy time from values.yaml
+# NOTE: worker_ready/worker_shutdown signals only fire for workers, not beat
+import threading
+from celery import bootsteps
+from celery.signals import worker_ready, worker_shutdown, worker_init
+
+# File paths for health check probes (from values.yaml)
+_readiness_file = {{ .Values.supersetWorker.healthCheck.readinessFile | 
default "/tmp/celery_worker_ready" | quote }}
+_liveness_file = {{ .Values.supersetWorker.healthCheck.livenessFile | default 
"/tmp/celery_worker_alive" | quote }}
+_heartbeat_interval = {{ 
.Values.supersetWorker.healthCheck.livenessHeartbeatInterval | default 10 | int 
}}
+_liveness_thread = None
+_liveness_stop_event = None
+
+# Readiness Probe: Create/remove file based on worker state
+# These signals only fire for workers, safe to register globally
+@worker_ready.connect
+def create_ready_file(sender, **kwargs):
+    """Create readiness file when Celery worker is ready to process tasks"""
+    try:
+        open(_readiness_file, 'w').close()
+        print(f"Celery worker ready - created {_readiness_file}")
+    except Exception as e:
+        print(f"Warning: Could not create readiness file: {e}")
+
+@worker_shutdown.connect
+def remove_ready_file(sender, **kwargs):
+    """Remove readiness file when Celery worker is shutting down"""
+    global _liveness_thread, _liveness_stop_event
+    # Stop the liveness heartbeat thread
+    if _liveness_stop_event:
+        _liveness_stop_event.set()
+    if _liveness_thread:
+        _liveness_thread.join(timeout=5)
+    # Remove health check files
+    try:
+        if os.path.exists(_readiness_file):
+            os.remove(_readiness_file)
+            print(f"Celery worker shutdown - removed {_readiness_file}")
+        if os.path.exists(_liveness_file):
+            os.remove(_liveness_file)
+            print(f"Celery worker shutdown - removed {_liveness_file}")
+    except Exception as e:
+        print(f"Warning: Could not remove health check files: {e}")
+
+# Liveness Probe: Start heartbeat thread when worker initializes
+# worker_init only fires for workers, not beat
+@worker_init.connect
+def start_liveness_heartbeat(sender, **kwargs):
+    """Start the liveness heartbeat thread when worker initializes"""
+    global _liveness_thread, _liveness_stop_event
+    _liveness_stop_event = threading.Event()
+
+    def update_liveness():
+        while not _liveness_stop_event.is_set():
+            try:
+                with open(_liveness_file, 'w') as f:
+                    f.write(str(os.getpid()))
+            except Exception as e:
+                print(f"Warning: Could not update liveness file: {e}")
+            _liveness_stop_event.wait(_heartbeat_interval)
+
+    _liveness_thread = threading.Thread(target=update_liveness, daemon=True)
+    _liveness_thread.start()
+    print(f"Celery liveness heartbeat started - updating {_liveness_file} 
every {_heartbeat_interval}s")
+{{- else }}
+CELERY_WORKER_HEALTH_CHECK_ENABLED = False
+{{- end }}
+
+{{- /* Results Backend */}}
+{{- if .Values.config.resultsBackend }}
+{{- if kindIs "string" .Values.config.resultsBackend }}
+RESULTS_BACKEND = {{ .Values.config.resultsBackend }}
+{{- else }}
 RESULTS_BACKEND = RedisCache(
-      host=env('REDIS_HOST'),
-      {{- if .Values.supersetNode.connections.redis_password }}
-      password=env('REDIS_PASSWORD'),
-      {{- end }}
-      port=env('REDIS_PORT'),
-      key_prefix='superset_results',
-      {{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-      ssl=True,
-      ssl_cert_reqs=env('REDIS_SSL_CERT_REQS'),
-      {{- end }}
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
 )
+{{- end }}
+{{- else if .Values.cache.enabled }}
+RESULTS_BACKEND = RedisCache(
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
+)
+{{- end }}
+
+{{- /* Global Async Queries Cache Backend - Required when using 
GLOBAL_ASYNC_QUERIES feature flag */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
+    "CACHE_TYPE": "RedisCache",
+    "CACHE_REDIS_HOST": {{ .Values.cache.host | quote }},
+    "CACHE_REDIS_PORT": {{ .Values.cache.port | int }},
+    "CACHE_REDIS_USER": {{ .Values.cache.user | default "" | quote }},
+    {{- if .Values.cache.password }}
+    "CACHE_REDIS_PASSWORD": {{ .Values.cache.password | quote }},
+    {{- else }}
+    "CACHE_REDIS_PASSWORD": "",
+    {{- end }}
+    "CACHE_REDIS_DB": {{ .Values.cache.asyncQueries.db | default 
.Values.cache.cacheDb | default 0 | int }},
+    "CACHE_KEY_PREFIX": {{ .Values.cache.asyncQueries.keyPrefix | default 
"qc-" | quote }},
+    "CACHE_DEFAULT_TIMEOUT": {{ .Values.cache.asyncQueries.timeout | default 
86400 | int }},
+    {{- if .Values.cache.sentinel }}
+    {{- if .Values.cache.sentinel.sentinels }}
+    "CACHE_REDIS_SENTINELS": {{ .Values.cache.sentinel.sentinels | toJson }},
+    {{- else }}
+    {{- fail "CONFIGURATION ERROR: cache.sentinel.enabled is true but 
cache.sentinel.sentinels is not set. You must provide Sentinel host(s) in 
cache.sentinel.sentinels (e.g., [['sentinel-host', 26379]])." }}
+    {{- end }}
+    "CACHE_REDIS_SENTINEL_MASTER": {{ .Values.cache.sentinel.master | default 
"mymaster" | quote }},
+    {{- if .Values.cache.sentinel.password }}
+    "CACHE_REDIS_SENTINEL_PASSWORD": {{ .Values.cache.sentinel.password | 
quote }},
+    {{- else }}
+    "CACHE_REDIS_SENTINEL_PASSWORD": None,
+    {{- end }}
+    {{- end }}
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    "CACHE_REDIS_SSL": True,
+    "CACHE_REDIS_SSL_CERTFILE": {{ .Values.cache.ssl.certfile | default "None" 
}},
+    "CACHE_REDIS_SSL_KEYFILE": {{ .Values.cache.ssl.keyfile | default "None" 
}},
+    "CACHE_REDIS_SSL_CERT_REQS": {{ .Values.cache.ssl.ssl_cert_reqs | default 
"required" | quote }},
+    "CACHE_REDIS_SSL_CA_CERTS": {{ .Values.cache.ssl.ca_certs | default "None" 
}},
+    {{- else }}
+    "CACHE_REDIS_SSL": False,
+    "CACHE_REDIS_SSL_CERTFILE": None,
+    "CACHE_REDIS_SSL_KEYFILE": None,
+    "CACHE_REDIS_SSL_CERT_REQS": {{ .Values.cache.ssl.ssl_cert_reqs | default 
"required" | quote }},
+    "CACHE_REDIS_SSL_CA_CERTS": None,
+    {{- end }}
+}
+{{- end }}
+
+{{- /* Global Async Queries Results Backend - Required when using 
GLOBAL_ASYNC_QUERIES feature flag */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND }}
+GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
+GLOBAL_ASYNC_QUERIES_RESULTS_BACKEND = {
+    "backend": "redis",
+    "host": {{ .Values.cache.host | quote }},
+    "port": {{ .Values.cache.port | int }},
+    "prefix": {{ .Values.cache.asyncQueries.keyPrefix | default "qc-" | quote 
}},
+    "db": {{ .Values.cache.asyncQueries.db | default .Values.cache.cacheDb | 
default 0 | int }},
+    {{- if .Values.cache.password }}
+    "password": {{ .Values.cache.password | quote }},
+    {{- end }}
+}
+{{- end }}
+
+{{- /* Feature Flags */}}
+{{- if .Values.featureFlags }}
+FEATURE_FLAGS = {
+{{- range $key, $value := .Values.featureFlags }}
+{{- if kindIs "bool" $value }}
+    "{{ $key }}": {{ if $value }}True{{ else }}False{{ end }},
+{{- else if kindIs "string" $value }}
+    "{{ $key }}": {{ $value | quote }},
+{{- else if kindIs "float64" $value }}
+    "{{ $key }}": {{ $value }},
+{{- else if kindIs "int" $value }}
+    "{{ $key }}": {{ $value }},
+{{- else }}
+    "{{ $key }}": {{ $value | toJson }},
+{{- end }}
+{{- end }}
+}
+{{- end }}
+
+{{- /* FAB Security API - Required for List Roles view in 6.0.0+ */}}
+{{- if not (hasKey .Values.config "FAB_ADD_SECURITY_API") }}
+FAB_ADD_SECURITY_API = True
+{{- end }}
+{{- if not (hasKey .Values.config "FAB_ADD_SECURITY_VIEWS") }}
+FAB_ADD_SECURITY_VIEWS = True
+{{- end }}
+
+{{- /* Global Async Queries Transport - Auto-configure for websockets if 
enabled */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_TRANSPORT }}
+GLOBAL_ASYNC_QUERIES_TRANSPORT = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_TRANSPORT | quote }}
+{{- else if .Values.supersetWebsockets.enabled }}
+GLOBAL_ASYNC_QUERIES_TRANSPORT = "ws"
+{{- else }}
+GLOBAL_ASYNC_QUERIES_TRANSPORT = "polling"
+{{- end }}
+
+{{- /* Global Async Queries WebSocket URL - Auto-configure if websockets are 
enabled */}}
+{{- $wsUrl := "" }}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL }}
+{{- $wsUrl = .Values.config.GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL }}
+GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
+{{- else if and .Values.supersetWebsockets.enabled 
.Values.supersetWebsockets.websocketUrl }}
+{{- $wsUrl = .Values.supersetWebsockets.websocketUrl }}
+GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
+{{- else if .Values.supersetWebsockets.enabled }}
+{{- /* Default: Use service name - user should override with external URL 
accessible from browser */}}
+{{- $wsServiceName := .Values.cluster.websocketServiceName }}
+{{- if not $wsServiceName }}
+{{- $wsServiceName = printf "%s-ws" (include "superset.fullname" .) }}
+{{- end }}
+{{- $wsPort := .Values.supersetWebsockets.service.port | default 8080 }}
+{{- $wsPath := "/ws" }}
+{{- $clusterDomain := .Values.cluster.domain | default ".svc.cluster.local" }}
+{{- $wsUrl = printf "ws://%s.%s%s:%d%s" $wsServiceName .Release.Namespace 
$clusterDomain $wsPort $wsPath }}
+GLOBAL_ASYNC_QUERIES_WEBSOCKET_URL = {{ $wsUrl | quote }}
+{{- end }}
+
+{{- /* Global Async Queries JWT Secret - Required when using 
GLOBAL_ASYNC_QUERIES feature flag */}}
+{{- /* Must match the JWT secret in the websocket server config.json */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_JWT_SECRET }}
+GLOBAL_ASYNC_QUERIES_JWT_SECRET = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_JWT_SECRET | quote }}
+{{- else if and .Values.supersetWebsockets.enabled 
.Values.supersetWebsockets.config.jwtSecret }}
+GLOBAL_ASYNC_QUERIES_JWT_SECRET = {{ 
.Values.supersetWebsockets.config.jwtSecret | quote }}
+{{- end }}
+
+{{- /* Global Async Queries JWT Cookie Settings - Important for HTTPS/WSS */}}
+{{- /* SECURE: Must be True when using HTTPS/WSS, otherwise browser won't send 
the cookie */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE }}

Review Comment:
   **Suggestion:** The condition checks truthiness instead of key presence, so 
explicitly setting the secure-cookie option to `false` is ignored and 
overridden by auto-detection logic. Use `hasKey` so explicit false values are 
honored. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Explicit false override for JWT cookie secure ignored.
   - ⚠️ Websocket GAQ cookie behavior may not match values.
   ```
   </details>
   
   ```suggestion
   {{- if hasKey .Values.config "GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE" }}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Enable websockets and set `config.GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE: 
false`
   intentionally.
   
   2. During render, `_helpers.tpl` checks truthiness at `542`; explicit 
`false` skips the
   explicit-value branch.
   
   3. Control falls into auto-detection branch (`544-549`) which can force
   `GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = True` when TLS/wss indicators are 
present.
   
   4. Generated `superset_config.py` (via `secret-superset-config.yaml:41`) no 
longer
   reflects user intent, affecting websocket auth cookie behavior.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** helm/superset/templates/_helpers.tpl
   **Line:** 542:542
   **Comment:**
        *Logic Error: The condition checks truthiness instead of key presence, 
so explicitly setting the secure-cookie option to `false` is ignored and 
overridden by auto-detection logic. Use `hasKey` so explicit false values are 
honored.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=bd157a7139b288611ac16ff3cf3c7672d73ab092f26fa824f6d3d83fd50cc7be&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=bd157a7139b288611ac16ff3cf3c7672d73ab092f26fa824f6d3d83fd50cc7be&reaction=dislike'>👎</a>



##########
helm/superset/templates/_helpers.tpl:
##########
@@ -61,83 +75,569 @@ Create chart name and version as used by the chart label.
   {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" -}}
 {{- end -}}
 
+{{/*
+Common labels for all resources - follows Kubernetes recommended labels
+https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
+*/}}
+{{- define "superset.labels" -}}
+helm.sh/chart: {{ include "superset.chart" . }}
+{{ include "superset.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/part-of: superset
+{{- if .Values.extraLabels }}
+{{ toYaml .Values.extraLabels }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Selector labels - used by selectors and matchLabels
+*/}}
+{{- define "superset.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Component labels - extends superset.labels with component-specific labels
+Usage: {{ include "superset.componentLabels" (dict "component" "web" "root" .) 
}}
+*/}}
+{{- define "superset.componentLabels" -}}
+{{ include "superset.labels" .root }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+{{/*
+Component selector labels - for matchLabels with component
+Usage: {{ include "superset.componentSelectorLabels" (dict "component" "web" 
"root" .) }}
+*/}}
+{{- define "superset.componentSelectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" .root }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+
+{{- define "superset.config" }}
+{{- /* Check for deprecated configuration values */}}
+{{- include "superset.checkDeprecatedValues" . }}
+{{- /* SECURITY: Validate admin password is set if admin creation is enabled 
*/}}
+{{- /* Note: JWT secret validation is in deployment-ws.yaml since websocket 
config is in a separate secret */}}
+{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) 
(eq .Values.init.adminUser.password "")) }}
+{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password 
is empty. You must set a secure password using --set 
init.adminUser.password='your-password' or via external secret." }}
+{{- end }}
+{{- /* PRODUCTION: Validate resource limits are set for production deployments 
*/}}
+{{- if and (not .Values.resources.limits) (not .Values.resources.requests) }}
+{{- /* Note: This is a warning - pre-install validation job will also check 
this */}}
+{{- /* Resource limits are critical for production to prevent resource 
exhaustion */}}
+{{- end }}
 
-{{- define "superset-config" }}
 import os
+{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig 
.Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled 
}}
 from flask_caching.backends.rediscache import RedisCache
+{{- end }}
 
 def env(key, default=None):
     return os.getenv(key, default)
 
-# Redis Base URL
-{{- if .Values.supersetNode.connections.redis_password }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_USER', 
'')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Database Configuration - Superset always requires a database */}}
+{{- if .Values.database.uri }}
+SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
 {{- else }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Determine database host - use explicit host, or default to service name 
*/}}
+{{- $dbHost := .Values.database.host }}
+{{- if not $dbHost }}
+{{- if .Values.cluster.databaseServiceName }}
+{{- $dbHost = .Values.cluster.databaseServiceName }}
+{{- else }}
+{{- $dbHost = printf "%s-postgresql" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $driver := .Values.database.driver | default "postgresql+psycopg2" }}
+{{- $sslParams := "" }}
+{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
+{{- $sslMode := .Values.database.ssl.mode | default "require" }}
+{{- $sslParams = printf "?sslmode=%s" $sslMode }}
+{{- end }}
+SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{{ .Values.database.user }}:{{ 
.Values.database.password }}@{{ $dbHost }}:{{ .Values.database.port }}/{{ 
.Values.database.name }}{{ $sslParams }}"
+{{- end }}
+{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
+SQLALCHEMY_TRACK_MODIFICATIONS = {{ 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | lower }}
+{{- else }}
+SQLALCHEMY_TRACK_MODIFICATIONS = False
 {{- end }}
 
-# Redis URL Params
-{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-REDIS_URL_PARAMS = f"?ssl_cert_reqs={env('REDIS_SSL_CERT_REQS')}"
+{{- /* Redis Configuration - only if Redis cache is configured */}}
+{{- if .Values.cache.enabled }}
+{{- if .Values.cache.cacheUrl }}
+CACHE_REDIS_URL = {{ .Values.cache.cacheUrl | quote }}
+{{- else }}
+{{- /* Automatically use rediss (SSL) protocol when SSL is enabled, otherwise 
use redis */}}
+{{- /* Determine Redis host - use explicit host, or default to service name 
*/}}
+{{- $redisHost := .Values.cache.host }}
+{{- if not $redisHost }}
+{{- if .Values.cluster.redisServiceName }}
+{{- $redisHost = .Values.cluster.redisServiceName }}
+{{- else }}
+{{- $redisHost = printf "%s-redis-headless" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $redisUser := .Values.cache.user | default "" }}
+{{- $redisPort := .Values.cache.port }}
+{{- $redisPassword := .Values.cache.password }}
+{{- $useSSL := and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+{{- if $redisPassword }}
+{{- if $redisUser }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisUser }}:{{ $redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://:{{ 
$redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- if $useSSL }}
+{{- $sslCertReqs := .Values.cache.ssl.ssl_cert_reqs | default "required" }}
+REDIS_URL_PARAMS = f"?ssl_cert_reqs={{ $sslCertReqs }}"
 {{- else }}
 REDIS_URL_PARAMS = ""
-{{- end}}
-
-# Build Redis URLs
-CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_DB', 1)}{REDIS_URL_PARAMS}"
-CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_CELERY_DB', 
0)}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- $cacheDb := .Values.cache.cacheDb | default 1 }}
+CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{{ $cacheDb }}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- if .Values.cache.celeryUrl }}
+CELERY_REDIS_URL = {{ .Values.cache.celeryUrl | quote }}
+{{- else if not .Values.cache.cacheUrl }}
+{{- $celeryDb := .Values.cache.celeryDb | default 0 }}
+CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{{ $celeryDb }}{REDIS_URL_PARAMS}"
+{{- else }}
+{{- /* SECURITY: If cacheUrl is set but celeryUrl is not, Celery will fail. 
Validate this. */}}
+{{- if or .Values.config.celeryConfig (not .Values.cache.enabled) }}
+{{- /* Custom celeryConfig provided or cache disabled - OK */}}
+{{- else }}
+{{- fail "CONFIGURATION ERROR: cache.cacheUrl is set but cache.celeryUrl is 
not set. When using cacheUrl, you must also set celeryUrl for Celery to work. 
Alternatively, set config.celeryConfig to provide a custom Celery 
configuration." }}
+{{- end }}
+{{- end }}
+{{- end }}
 
-MAPBOX_API_KEY = env('MAPBOX_API_KEY', '')
+{{- /* Cache Configuration */}}
+{{- if .Values.config.cacheConfig }}
+CACHE_CONFIG = {{ .Values.config.cacheConfig | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
 CACHE_CONFIG = {
-      'CACHE_TYPE': 'RedisCache',
-      'CACHE_DEFAULT_TIMEOUT': 300,
-      'CACHE_KEY_PREFIX': 'superset_',
-      'CACHE_REDIS_URL': CACHE_REDIS_URL,
+    'CACHE_TYPE': 'RedisCache',
+    'CACHE_DEFAULT_TIMEOUT': {{ .Values.cache.defaultTimeout | default 
(.Values.config.cacheDefaultTimeout | default 86400) | int }},
+    'CACHE_KEY_PREFIX': {{ .Values.cache.keyPrefix | default "superset_" | 
quote }},
+    'CACHE_REDIS_URL': CACHE_REDIS_URL,
 }
+{{- end }}
+
+{{- if .Values.config.dataCacheConfig }}
+DATA_CACHE_CONFIG = {{ .Values.config.dataCacheConfig | toJson | indent 2 }}
+{{- else if .Values.config.cacheConfig }}
 DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- else if .Values.cache.enabled }}
+DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- end }}
 
+{{- /* SQLLAB_ASYNC_TIME_LIMIT_SEC - Required for async_queries module import 
(default: 6 hours) */}}
+{{- /* This MUST be set before Celery config imports async_queries, as it 
accesses current_app.config at module level */}}
+{{- if .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC }}
+SQLLAB_ASYNC_TIME_LIMIT_SEC = {{ .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC | 
int }}
+{{- else }}
+from datetime import timedelta
+SQLLAB_ASYNC_TIME_LIMIT_SEC = int(timedelta(hours=6).total_seconds())
+{{- end }}
 
-if os.getenv("SQLALCHEMY_DATABASE_URI"):
-    SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
-else:
-    {{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else }}
-    {{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 
'mysql'." .Values.supersetNode.connections.db_type) }}
-    {{- end }}
+{{- /* Celery Configuration */}}
+{{- if .Values.config.celeryConfig }}
+{{- if kindIs "string" .Values.config.celeryConfig }}
+{{ .Values.config.celeryConfig }}
+{{- else }}
+class CeleryConfig:
+{{- range $key, $value := .Values.config.celeryConfig }}
+    {{ $key }} = {{ $value | toJson }}
+{{- end }}
 
-SQLALCHEMY_TRACK_MODIFICATIONS = True
+CELERY_IMPORTS = CeleryConfig.imports

Review Comment:
   **Suggestion:** Custom Celery config dictionaries are not guaranteed to 
define an `imports` attribute, so directly accessing it raises an attribute 
error at runtime; use a safe fallback when missing. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Custom Celery dict config can crash app bootstrap.
   - ⚠️ Worker/beat/flower and web share same broken config.
   ```
   </details>
   
   ```suggestion
   CELERY_IMPORTS = getattr(CeleryConfig, "imports", ())
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Provide custom dict-style `config.celeryConfig` (documented at
   `helm/superset/values.yaml:126-128`) without an `imports` key.
   
   2. Render/install chart; `_helpers.tpl` builds `class CeleryConfig` then 
immediately
   evaluates `CELERY_IMPORTS = CeleryConfig.imports` at
   `helm/superset/templates/_helpers.tpl:263`.
   
   3. `superset_config.py` is generated through 
`secret-superset-config.yaml:41` and mounted
   into all runtime pods (`deployment*.yaml` mount paths under 
`/app/pythonpath`).
   
   4. When process starts, module-level access to missing 
`CeleryConfig.imports` raises
   `AttributeError`, aborting config load before app init
   (`superset/initialization/__init__.py:127` expects valid `CELERY_CONFIG`).
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** helm/superset/templates/_helpers.tpl
   **Line:** 263:263
   **Comment:**
        *Possible Bug: Custom Celery config dictionaries are not guaranteed to 
define an `imports` attribute, so directly accessing it raises an attribute 
error at runtime; use a safe fallback when missing.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=9ebc4bde251c76bd1444dc620178bc18ac48b26dd048030ca65b50aa9762c5cc&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=9ebc4bde251c76bd1444dc620178bc18ac48b26dd048030ca65b50aa9762c5cc&reaction=dislike'>👎</a>



##########
helm/superset/templates/_helpers.tpl:
##########
@@ -61,83 +75,569 @@ Create chart name and version as used by the chart label.
   {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" -}}
 {{- end -}}
 
+{{/*
+Common labels for all resources - follows Kubernetes recommended labels
+https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
+*/}}
+{{- define "superset.labels" -}}
+helm.sh/chart: {{ include "superset.chart" . }}
+{{ include "superset.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/part-of: superset
+{{- if .Values.extraLabels }}
+{{ toYaml .Values.extraLabels }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Selector labels - used by selectors and matchLabels
+*/}}
+{{- define "superset.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Component labels - extends superset.labels with component-specific labels
+Usage: {{ include "superset.componentLabels" (dict "component" "web" "root" .) 
}}
+*/}}
+{{- define "superset.componentLabels" -}}
+{{ include "superset.labels" .root }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+{{/*
+Component selector labels - for matchLabels with component
+Usage: {{ include "superset.componentSelectorLabels" (dict "component" "web" 
"root" .) }}
+*/}}
+{{- define "superset.componentSelectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" .root }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+
+{{- define "superset.config" }}
+{{- /* Check for deprecated configuration values */}}
+{{- include "superset.checkDeprecatedValues" . }}
+{{- /* SECURITY: Validate admin password is set if admin creation is enabled 
*/}}
+{{- /* Note: JWT secret validation is in deployment-ws.yaml since websocket 
config is in a separate secret */}}
+{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) 
(eq .Values.init.adminUser.password "")) }}
+{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password 
is empty. You must set a secure password using --set 
init.adminUser.password='your-password' or via external secret." }}
+{{- end }}
+{{- /* PRODUCTION: Validate resource limits are set for production deployments 
*/}}
+{{- if and (not .Values.resources.limits) (not .Values.resources.requests) }}
+{{- /* Note: This is a warning - pre-install validation job will also check 
this */}}
+{{- /* Resource limits are critical for production to prevent resource 
exhaustion */}}
+{{- end }}
 
-{{- define "superset-config" }}
 import os
+{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig 
.Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled 
}}
 from flask_caching.backends.rediscache import RedisCache
+{{- end }}
 
 def env(key, default=None):
     return os.getenv(key, default)
 
-# Redis Base URL
-{{- if .Values.supersetNode.connections.redis_password }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_USER', 
'')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Database Configuration - Superset always requires a database */}}
+{{- if .Values.database.uri }}
+SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
 {{- else }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Determine database host - use explicit host, or default to service name 
*/}}
+{{- $dbHost := .Values.database.host }}
+{{- if not $dbHost }}
+{{- if .Values.cluster.databaseServiceName }}
+{{- $dbHost = .Values.cluster.databaseServiceName }}
+{{- else }}
+{{- $dbHost = printf "%s-postgresql" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $driver := .Values.database.driver | default "postgresql+psycopg2" }}
+{{- $sslParams := "" }}
+{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
+{{- $sslMode := .Values.database.ssl.mode | default "require" }}
+{{- $sslParams = printf "?sslmode=%s" $sslMode }}
+{{- end }}
+SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{{ .Values.database.user }}:{{ 
.Values.database.password }}@{{ $dbHost }}:{{ .Values.database.port }}/{{ 
.Values.database.name }}{{ $sslParams }}"
+{{- end }}
+{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
+SQLALCHEMY_TRACK_MODIFICATIONS = {{ 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | lower }}
+{{- else }}
+SQLALCHEMY_TRACK_MODIFICATIONS = False
 {{- end }}
 
-# Redis URL Params
-{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-REDIS_URL_PARAMS = f"?ssl_cert_reqs={env('REDIS_SSL_CERT_REQS')}"
+{{- /* Redis Configuration - only if Redis cache is configured */}}
+{{- if .Values.cache.enabled }}
+{{- if .Values.cache.cacheUrl }}
+CACHE_REDIS_URL = {{ .Values.cache.cacheUrl | quote }}
+{{- else }}
+{{- /* Automatically use rediss (SSL) protocol when SSL is enabled, otherwise 
use redis */}}
+{{- /* Determine Redis host - use explicit host, or default to service name 
*/}}
+{{- $redisHost := .Values.cache.host }}
+{{- if not $redisHost }}
+{{- if .Values.cluster.redisServiceName }}
+{{- $redisHost = .Values.cluster.redisServiceName }}
+{{- else }}
+{{- $redisHost = printf "%s-redis-headless" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $redisUser := .Values.cache.user | default "" }}
+{{- $redisPort := .Values.cache.port }}
+{{- $redisPassword := .Values.cache.password }}
+{{- $useSSL := and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+{{- if $redisPassword }}
+{{- if $redisUser }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisUser }}:{{ $redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://:{{ 
$redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- if $useSSL }}
+{{- $sslCertReqs := .Values.cache.ssl.ssl_cert_reqs | default "required" }}
+REDIS_URL_PARAMS = f"?ssl_cert_reqs={{ $sslCertReqs }}"
 {{- else }}
 REDIS_URL_PARAMS = ""
-{{- end}}
-
-# Build Redis URLs
-CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_DB', 1)}{REDIS_URL_PARAMS}"
-CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_CELERY_DB', 
0)}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- $cacheDb := .Values.cache.cacheDb | default 1 }}
+CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{{ $cacheDb }}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- if .Values.cache.celeryUrl }}
+CELERY_REDIS_URL = {{ .Values.cache.celeryUrl | quote }}
+{{- else if not .Values.cache.cacheUrl }}
+{{- $celeryDb := .Values.cache.celeryDb | default 0 }}
+CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{{ $celeryDb }}{REDIS_URL_PARAMS}"
+{{- else }}
+{{- /* SECURITY: If cacheUrl is set but celeryUrl is not, Celery will fail. 
Validate this. */}}
+{{- if or .Values.config.celeryConfig (not .Values.cache.enabled) }}
+{{- /* Custom celeryConfig provided or cache disabled - OK */}}
+{{- else }}
+{{- fail "CONFIGURATION ERROR: cache.cacheUrl is set but cache.celeryUrl is 
not set. When using cacheUrl, you must also set celeryUrl for Celery to work. 
Alternatively, set config.celeryConfig to provide a custom Celery 
configuration." }}
+{{- end }}
+{{- end }}
+{{- end }}
 
-MAPBOX_API_KEY = env('MAPBOX_API_KEY', '')
+{{- /* Cache Configuration */}}
+{{- if .Values.config.cacheConfig }}
+CACHE_CONFIG = {{ .Values.config.cacheConfig | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
 CACHE_CONFIG = {
-      'CACHE_TYPE': 'RedisCache',
-      'CACHE_DEFAULT_TIMEOUT': 300,
-      'CACHE_KEY_PREFIX': 'superset_',
-      'CACHE_REDIS_URL': CACHE_REDIS_URL,
+    'CACHE_TYPE': 'RedisCache',
+    'CACHE_DEFAULT_TIMEOUT': {{ .Values.cache.defaultTimeout | default 
(.Values.config.cacheDefaultTimeout | default 86400) | int }},
+    'CACHE_KEY_PREFIX': {{ .Values.cache.keyPrefix | default "superset_" | 
quote }},
+    'CACHE_REDIS_URL': CACHE_REDIS_URL,
 }
+{{- end }}
+
+{{- if .Values.config.dataCacheConfig }}
+DATA_CACHE_CONFIG = {{ .Values.config.dataCacheConfig | toJson | indent 2 }}
+{{- else if .Values.config.cacheConfig }}
 DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- else if .Values.cache.enabled }}
+DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- end }}
 
+{{- /* SQLLAB_ASYNC_TIME_LIMIT_SEC - Required for async_queries module import 
(default: 6 hours) */}}
+{{- /* This MUST be set before Celery config imports async_queries, as it 
accesses current_app.config at module level */}}
+{{- if .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC }}
+SQLLAB_ASYNC_TIME_LIMIT_SEC = {{ .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC | 
int }}
+{{- else }}
+from datetime import timedelta
+SQLLAB_ASYNC_TIME_LIMIT_SEC = int(timedelta(hours=6).total_seconds())
+{{- end }}
 
-if os.getenv("SQLALCHEMY_DATABASE_URI"):
-    SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
-else:
-    {{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else }}
-    {{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 
'mysql'." .Values.supersetNode.connections.db_type) }}
-    {{- end }}
+{{- /* Celery Configuration */}}
+{{- if .Values.config.celeryConfig }}
+{{- if kindIs "string" .Values.config.celeryConfig }}
+{{ .Values.config.celeryConfig }}
+{{- else }}
+class CeleryConfig:
+{{- range $key, $value := .Values.config.celeryConfig }}
+    {{ $key }} = {{ $value | toJson }}
+{{- end }}
 
-SQLALCHEMY_TRACK_MODIFICATIONS = True
+CELERY_IMPORTS = CeleryConfig.imports
+CELERY_CONFIG = CeleryConfig
+{{- end }}
+{{- else if .Values.cache.enabled }}
+from celery.schedules import crontab
+from datetime import timedelta
 
 class CeleryConfig:
-  imports  = ("superset.sql_lab", )
-  broker_url = CELERY_REDIS_URL
-  result_backend = CELERY_REDIS_URL
+    imports = (
+        "superset.sql_lab",
+        "superset.tasks.scheduler",
+        "superset.tasks.thumbnails",
+        "superset.tasks.cache",
+        # NOTE: async_queries is temporarily excluded due to a bug where it 
accesses current_app.config
+        # at module import time without an app context. This causes 
worker/beat/flower to crash.
+        # TODO: Re-enable when Superset fixes the issue or provides a 
workaround
+        # "superset.tasks.async_queries",  # REQUIRED for GAQ
+    )
+    broker_connection_retry_on_startup = True
+    worker_prefetch_multiplier = 10
+    task_acks_late = True
+    broker_url = CELERY_REDIS_URL
+    result_backend = CELERY_REDIS_URL
+    task_annotations = {
+        "sql_lab.get_sql_results": {
+            "rate_limit": "100/s",
+        },
+    }
+    beat_schedule = {
+        "reports.scheduler": {
+            "task": "reports.scheduler",
+            "schedule": crontab(minute="*", hour="*"),
+            "options": {"expires": int(timedelta(weeks=1).total_seconds())},
+        },
+        "reports.prune_log": {
+            "task": "reports.prune_log",
+            "schedule": crontab(minute=0, hour=0),
+        },
+    }
 
+CELERY_IMPORTS = CeleryConfig.imports
 CELERY_CONFIG = CeleryConfig
+{{- end }}
+
+{{- /* Celery Worker Health Check - File-based health probes for Kubernetes 
*/}}
+{{- /* See: 
https://medium.com/ambient-innovation/health-checks-for-celery-in-kubernetes-cf3274a3e106
 */}}
+{{- /* NOTE: These signals only fire for Celery workers, not beat or flower 
*/}}
+{{- if and .Values.supersetWorker.healthCheck 
.Values.supersetWorker.healthCheck.enabled }}
+# Celery Worker Health Check Configuration
+# File paths are injected at deploy time from values.yaml
+# NOTE: worker_ready/worker_shutdown signals only fire for workers, not beat
+import threading
+from celery import bootsteps
+from celery.signals import worker_ready, worker_shutdown, worker_init
+
+# File paths for health check probes (from values.yaml)
+_readiness_file = {{ .Values.supersetWorker.healthCheck.readinessFile | 
default "/tmp/celery_worker_ready" | quote }}
+_liveness_file = {{ .Values.supersetWorker.healthCheck.livenessFile | default 
"/tmp/celery_worker_alive" | quote }}
+_heartbeat_interval = {{ 
.Values.supersetWorker.healthCheck.livenessHeartbeatInterval | default 10 | int 
}}
+_liveness_thread = None
+_liveness_stop_event = None
+
+# Readiness Probe: Create/remove file based on worker state
+# These signals only fire for workers, safe to register globally
+@worker_ready.connect
+def create_ready_file(sender, **kwargs):
+    """Create readiness file when Celery worker is ready to process tasks"""
+    try:
+        open(_readiness_file, 'w').close()
+        print(f"Celery worker ready - created {_readiness_file}")
+    except Exception as e:
+        print(f"Warning: Could not create readiness file: {e}")
+
+@worker_shutdown.connect
+def remove_ready_file(sender, **kwargs):
+    """Remove readiness file when Celery worker is shutting down"""
+    global _liveness_thread, _liveness_stop_event
+    # Stop the liveness heartbeat thread
+    if _liveness_stop_event:
+        _liveness_stop_event.set()
+    if _liveness_thread:
+        _liveness_thread.join(timeout=5)
+    # Remove health check files
+    try:
+        if os.path.exists(_readiness_file):
+            os.remove(_readiness_file)
+            print(f"Celery worker shutdown - removed {_readiness_file}")
+        if os.path.exists(_liveness_file):
+            os.remove(_liveness_file)
+            print(f"Celery worker shutdown - removed {_liveness_file}")
+    except Exception as e:
+        print(f"Warning: Could not remove health check files: {e}")
+
+# Liveness Probe: Start heartbeat thread when worker initializes
+# worker_init only fires for workers, not beat
+@worker_init.connect
+def start_liveness_heartbeat(sender, **kwargs):
+    """Start the liveness heartbeat thread when worker initializes"""
+    global _liveness_thread, _liveness_stop_event
+    _liveness_stop_event = threading.Event()
+
+    def update_liveness():
+        while not _liveness_stop_event.is_set():
+            try:
+                with open(_liveness_file, 'w') as f:
+                    f.write(str(os.getpid()))
+            except Exception as e:
+                print(f"Warning: Could not update liveness file: {e}")
+            _liveness_stop_event.wait(_heartbeat_interval)
+
+    _liveness_thread = threading.Thread(target=update_liveness, daemon=True)
+    _liveness_thread.start()
+    print(f"Celery liveness heartbeat started - updating {_liveness_file} 
every {_heartbeat_interval}s")
+{{- else }}
+CELERY_WORKER_HEALTH_CHECK_ENABLED = False
+{{- end }}
+
+{{- /* Results Backend */}}
+{{- if .Values.config.resultsBackend }}
+{{- if kindIs "string" .Values.config.resultsBackend }}
+RESULTS_BACKEND = {{ .Values.config.resultsBackend }}
+{{- else }}
 RESULTS_BACKEND = RedisCache(
-      host=env('REDIS_HOST'),
-      {{- if .Values.supersetNode.connections.redis_password }}
-      password=env('REDIS_PASSWORD'),
-      {{- end }}
-      port=env('REDIS_PORT'),
-      key_prefix='superset_results',
-      {{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-      ssl=True,
-      ssl_cert_reqs=env('REDIS_SSL_CERT_REQS'),
-      {{- end }}
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
 )
+{{- end }}
+{{- else if .Values.cache.enabled }}
+RESULTS_BACKEND = RedisCache(
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
+)
+{{- end }}
+
+{{- /* Global Async Queries Cache Backend - Required when using 
GLOBAL_ASYNC_QUERIES feature flag */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
+    "CACHE_TYPE": "RedisCache",
+    "CACHE_REDIS_HOST": {{ .Values.cache.host | quote }},
+    "CACHE_REDIS_PORT": {{ .Values.cache.port | int }},
+    "CACHE_REDIS_USER": {{ .Values.cache.user | default "" | quote }},
+    {{- if .Values.cache.password }}
+    "CACHE_REDIS_PASSWORD": {{ .Values.cache.password | quote }},
+    {{- else }}
+    "CACHE_REDIS_PASSWORD": "",
+    {{- end }}
+    "CACHE_REDIS_DB": {{ .Values.cache.asyncQueries.db | default 
.Values.cache.cacheDb | default 0 | int }},
+    "CACHE_KEY_PREFIX": {{ .Values.cache.asyncQueries.keyPrefix | default 
"qc-" | quote }},
+    "CACHE_DEFAULT_TIMEOUT": {{ .Values.cache.asyncQueries.timeout | default 
86400 | int }},
+    {{- if .Values.cache.sentinel }}

Review Comment:
   **Suggestion:** Sentinel configuration is enabled based on map presence 
instead of the documented `enabled` flag, so users can accidentally trigger 
Sentinel validation/errors even when `enabled: false`; gate this block on the 
flag. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Helm rendering can fail despite sentinel disabled flag.
   - ⚠️ Sentinel users hit confusing false-positive validation errors.
   ```
   </details>
   
   ```suggestion
       {{- if and .Values.cache.sentinel .Values.cache.sentinel.enabled }}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Define a sentinel map in values with `enabled: false` (pattern documented 
under
   `cache.sentinel` comments at `helm/superset/values.yaml:77-82`).
   
   2. Run `helm install`/`helm template`; `_helpers.tpl` enters sentinel block 
because map
   presence is truthy at line `430`.
   
   3. Block immediately validates `cache.sentinel.sentinels` and can call 
`fail` at
   `_helpers.tpl:434-435`, even though sentinel is explicitly disabled.
   
   4. Rendering fails through `include "superset.config"` path
   (`secret-superset-config.yaml:41`), blocking release creation/upgrade.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** helm/superset/templates/_helpers.tpl
   **Line:** 430:430
   **Comment:**
        *Logic Error: Sentinel configuration is enabled based on map presence 
instead of the documented `enabled` flag, so users can accidentally trigger 
Sentinel validation/errors even when `enabled: false`; gate this block on the 
flag.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=142ef1d5e1d37dae85c6aea8b687673301986b5350bd8b24fff5eb79f4b8dea1&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=142ef1d5e1d37dae85c6aea8b687673301986b5350bd8b24fff5eb79f4b8dea1&reaction=dislike'>👎</a>



##########
helm/superset/templates/_helpers.tpl:
##########
@@ -61,83 +75,569 @@ Create chart name and version as used by the chart label.
   {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | 
trimSuffix "-" -}}
 {{- end -}}
 
+{{/*
+Common labels for all resources - follows Kubernetes recommended labels
+https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
+*/}}
+{{- define "superset.labels" -}}
+helm.sh/chart: {{ include "superset.chart" . }}
+{{ include "superset.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/part-of: superset
+{{- if .Values.extraLabels }}
+{{ toYaml .Values.extraLabels }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Selector labels - used by selectors and matchLabels
+*/}}
+{{- define "superset.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Component labels - extends superset.labels with component-specific labels
+Usage: {{ include "superset.componentLabels" (dict "component" "web" "root" .) 
}}
+*/}}
+{{- define "superset.componentLabels" -}}
+{{ include "superset.labels" .root }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+{{/*
+Component selector labels - for matchLabels with component
+Usage: {{ include "superset.componentSelectorLabels" (dict "component" "web" 
"root" .) }}
+*/}}
+{{- define "superset.componentSelectorLabels" -}}
+app.kubernetes.io/name: {{ include "superset.name" .root }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/component: {{ .component }}
+{{- end -}}
+
+
+{{- define "superset.config" }}
+{{- /* Check for deprecated configuration values */}}
+{{- include "superset.checkDeprecatedValues" . }}
+{{- /* SECURITY: Validate admin password is set if admin creation is enabled 
*/}}
+{{- /* Note: JWT secret validation is in deployment-ws.yaml since websocket 
config is in a separate secret */}}
+{{- if and .Values.init.createAdmin (or (not .Values.init.adminUser.password) 
(eq .Values.init.adminUser.password "")) }}
+{{- fail "SECURITY ERROR: init.createAdmin is true but init.adminUser.password 
is empty. You must set a secure password using --set 
init.adminUser.password='your-password' or via external secret." }}
+{{- end }}
+{{- /* PRODUCTION: Validate resource limits are set for production deployments 
*/}}
+{{- if and (not .Values.resources.limits) (not .Values.resources.requests) }}
+{{- /* Note: This is a warning - pre-install validation job will also check 
this */}}
+{{- /* Resource limits are critical for production to prevent resource 
exhaustion */}}
+{{- end }}
 
-{{- define "superset-config" }}
 import os
+{{- if or .Values.config.cacheConfig .Values.config.dataCacheConfig 
.Values.config.resultsBackend .Values.config.celeryConfig .Values.cache.enabled 
}}
 from flask_caching.backends.rediscache import RedisCache
+{{- end }}
 
 def env(key, default=None):
     return os.getenv(key, default)
 
-# Redis Base URL
-{{- if .Values.supersetNode.connections.redis_password }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_USER', 
'')}:{env('REDIS_PASSWORD')}@{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Database Configuration - Superset always requires a database */}}
+{{- if .Values.database.uri }}
+SQLALCHEMY_DATABASE_URI = {{ .Values.database.uri | quote }}
 {{- else }}
-REDIS_BASE_URL=f"{env('REDIS_PROTO')}://{env('REDIS_HOST')}:{env('REDIS_PORT')}"
+{{- /* Determine database host - use explicit host, or default to service name 
*/}}
+{{- $dbHost := .Values.database.host }}
+{{- if not $dbHost }}
+{{- if .Values.cluster.databaseServiceName }}
+{{- $dbHost = .Values.cluster.databaseServiceName }}
+{{- else }}
+{{- $dbHost = printf "%s-postgresql" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $driver := .Values.database.driver | default "postgresql+psycopg2" }}
+{{- $sslParams := "" }}
+{{- if and (hasKey .Values.database "ssl") .Values.database.ssl.enabled }}
+{{- $sslMode := .Values.database.ssl.mode | default "require" }}
+{{- $sslParams = printf "?sslmode=%s" $sslMode }}
+{{- end }}
+SQLALCHEMY_DATABASE_URI = f"{{ $driver }}://{{ .Values.database.user }}:{{ 
.Values.database.password }}@{{ $dbHost }}:{{ .Values.database.port }}/{{ 
.Values.database.name }}{{ $sslParams }}"
+{{- end }}
+{{- if hasKey .Values.config "SQLALCHEMY_TRACK_MODIFICATIONS" }}
+SQLALCHEMY_TRACK_MODIFICATIONS = {{ 
.Values.config.SQLALCHEMY_TRACK_MODIFICATIONS | lower }}
+{{- else }}
+SQLALCHEMY_TRACK_MODIFICATIONS = False
 {{- end }}
 
-# Redis URL Params
-{{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-REDIS_URL_PARAMS = f"?ssl_cert_reqs={env('REDIS_SSL_CERT_REQS')}"
+{{- /* Redis Configuration - only if Redis cache is configured */}}
+{{- if .Values.cache.enabled }}
+{{- if .Values.cache.cacheUrl }}
+CACHE_REDIS_URL = {{ .Values.cache.cacheUrl | quote }}
+{{- else }}
+{{- /* Automatically use rediss (SSL) protocol when SSL is enabled, otherwise 
use redis */}}
+{{- /* Determine Redis host - use explicit host, or default to service name 
*/}}
+{{- $redisHost := .Values.cache.host }}
+{{- if not $redisHost }}
+{{- if .Values.cluster.redisServiceName }}
+{{- $redisHost = .Values.cluster.redisServiceName }}
+{{- else }}
+{{- $redisHost = printf "%s-redis-headless" .Release.Name }}
+{{- end }}
+{{- end }}
+{{- $redisUser := .Values.cache.user | default "" }}
+{{- $redisPort := .Values.cache.port }}
+{{- $redisPassword := .Values.cache.password }}
+{{- $useSSL := and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+{{- if $redisPassword }}
+{{- if $redisUser }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisUser }}:{{ $redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://:{{ 
$redisPassword }}@{{ $redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- else }}
+REDIS_BASE_URL = f"{{ if $useSSL }}rediss{{ else }}redis{{ end }}://{{ 
$redisHost }}:{{ $redisPort }}"
+{{- end }}
+{{- if $useSSL }}
+{{- $sslCertReqs := .Values.cache.ssl.ssl_cert_reqs | default "required" }}
+REDIS_URL_PARAMS = f"?ssl_cert_reqs={{ $sslCertReqs }}"
 {{- else }}
 REDIS_URL_PARAMS = ""
-{{- end}}
-
-# Build Redis URLs
-CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_DB', 1)}{REDIS_URL_PARAMS}"
-CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{env('REDIS_CELERY_DB', 
0)}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- $cacheDb := .Values.cache.cacheDb | default 1 }}
+CACHE_REDIS_URL = f"{REDIS_BASE_URL}/{{ $cacheDb }}{REDIS_URL_PARAMS}"
+{{- end }}
+{{- if .Values.cache.celeryUrl }}
+CELERY_REDIS_URL = {{ .Values.cache.celeryUrl | quote }}
+{{- else if not .Values.cache.cacheUrl }}
+{{- $celeryDb := .Values.cache.celeryDb | default 0 }}
+CELERY_REDIS_URL = f"{REDIS_BASE_URL}/{{ $celeryDb }}{REDIS_URL_PARAMS}"
+{{- else }}
+{{- /* SECURITY: If cacheUrl is set but celeryUrl is not, Celery will fail. 
Validate this. */}}
+{{- if or .Values.config.celeryConfig (not .Values.cache.enabled) }}
+{{- /* Custom celeryConfig provided or cache disabled - OK */}}
+{{- else }}
+{{- fail "CONFIGURATION ERROR: cache.cacheUrl is set but cache.celeryUrl is 
not set. When using cacheUrl, you must also set celeryUrl for Celery to work. 
Alternatively, set config.celeryConfig to provide a custom Celery 
configuration." }}
+{{- end }}
+{{- end }}
+{{- end }}
 
-MAPBOX_API_KEY = env('MAPBOX_API_KEY', '')
+{{- /* Cache Configuration */}}
+{{- if .Values.config.cacheConfig }}
+CACHE_CONFIG = {{ .Values.config.cacheConfig | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
 CACHE_CONFIG = {
-      'CACHE_TYPE': 'RedisCache',
-      'CACHE_DEFAULT_TIMEOUT': 300,
-      'CACHE_KEY_PREFIX': 'superset_',
-      'CACHE_REDIS_URL': CACHE_REDIS_URL,
+    'CACHE_TYPE': 'RedisCache',
+    'CACHE_DEFAULT_TIMEOUT': {{ .Values.cache.defaultTimeout | default 
(.Values.config.cacheDefaultTimeout | default 86400) | int }},
+    'CACHE_KEY_PREFIX': {{ .Values.cache.keyPrefix | default "superset_" | 
quote }},
+    'CACHE_REDIS_URL': CACHE_REDIS_URL,
 }
+{{- end }}
+
+{{- if .Values.config.dataCacheConfig }}
+DATA_CACHE_CONFIG = {{ .Values.config.dataCacheConfig | toJson | indent 2 }}
+{{- else if .Values.config.cacheConfig }}
 DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- else if .Values.cache.enabled }}
+DATA_CACHE_CONFIG = CACHE_CONFIG
+{{- end }}
 
+{{- /* SQLLAB_ASYNC_TIME_LIMIT_SEC - Required for async_queries module import 
(default: 6 hours) */}}
+{{- /* This MUST be set before Celery config imports async_queries, as it 
accesses current_app.config at module level */}}
+{{- if .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC }}
+SQLLAB_ASYNC_TIME_LIMIT_SEC = {{ .Values.config.SQLLAB_ASYNC_TIME_LIMIT_SEC | 
int }}
+{{- else }}
+from datetime import timedelta
+SQLLAB_ASYNC_TIME_LIMIT_SEC = int(timedelta(hours=6).total_seconds())
+{{- end }}
 
-if os.getenv("SQLALCHEMY_DATABASE_URI"):
-    SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
-else:
-    {{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
-    SQLALCHEMY_DATABASE_URI = 
f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
-    {{- else }}
-    {{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 
'mysql'." .Values.supersetNode.connections.db_type) }}
-    {{- end }}
+{{- /* Celery Configuration */}}
+{{- if .Values.config.celeryConfig }}
+{{- if kindIs "string" .Values.config.celeryConfig }}
+{{ .Values.config.celeryConfig }}
+{{- else }}
+class CeleryConfig:
+{{- range $key, $value := .Values.config.celeryConfig }}
+    {{ $key }} = {{ $value | toJson }}
+{{- end }}
 
-SQLALCHEMY_TRACK_MODIFICATIONS = True
+CELERY_IMPORTS = CeleryConfig.imports
+CELERY_CONFIG = CeleryConfig
+{{- end }}
+{{- else if .Values.cache.enabled }}
+from celery.schedules import crontab
+from datetime import timedelta
 
 class CeleryConfig:
-  imports  = ("superset.sql_lab", )
-  broker_url = CELERY_REDIS_URL
-  result_backend = CELERY_REDIS_URL
+    imports = (
+        "superset.sql_lab",
+        "superset.tasks.scheduler",
+        "superset.tasks.thumbnails",
+        "superset.tasks.cache",
+        # NOTE: async_queries is temporarily excluded due to a bug where it 
accesses current_app.config
+        # at module import time without an app context. This causes 
worker/beat/flower to crash.
+        # TODO: Re-enable when Superset fixes the issue or provides a 
workaround
+        # "superset.tasks.async_queries",  # REQUIRED for GAQ
+    )
+    broker_connection_retry_on_startup = True
+    worker_prefetch_multiplier = 10
+    task_acks_late = True
+    broker_url = CELERY_REDIS_URL
+    result_backend = CELERY_REDIS_URL
+    task_annotations = {
+        "sql_lab.get_sql_results": {
+            "rate_limit": "100/s",
+        },
+    }
+    beat_schedule = {
+        "reports.scheduler": {
+            "task": "reports.scheduler",
+            "schedule": crontab(minute="*", hour="*"),
+            "options": {"expires": int(timedelta(weeks=1).total_seconds())},
+        },
+        "reports.prune_log": {
+            "task": "reports.prune_log",
+            "schedule": crontab(minute=0, hour=0),
+        },
+    }
 
+CELERY_IMPORTS = CeleryConfig.imports
 CELERY_CONFIG = CeleryConfig
+{{- end }}
+
+{{- /* Celery Worker Health Check - File-based health probes for Kubernetes 
*/}}
+{{- /* See: 
https://medium.com/ambient-innovation/health-checks-for-celery-in-kubernetes-cf3274a3e106
 */}}
+{{- /* NOTE: These signals only fire for Celery workers, not beat or flower 
*/}}
+{{- if and .Values.supersetWorker.healthCheck 
.Values.supersetWorker.healthCheck.enabled }}
+# Celery Worker Health Check Configuration
+# File paths are injected at deploy time from values.yaml
+# NOTE: worker_ready/worker_shutdown signals only fire for workers, not beat
+import threading
+from celery import bootsteps
+from celery.signals import worker_ready, worker_shutdown, worker_init
+
+# File paths for health check probes (from values.yaml)
+_readiness_file = {{ .Values.supersetWorker.healthCheck.readinessFile | 
default "/tmp/celery_worker_ready" | quote }}
+_liveness_file = {{ .Values.supersetWorker.healthCheck.livenessFile | default 
"/tmp/celery_worker_alive" | quote }}
+_heartbeat_interval = {{ 
.Values.supersetWorker.healthCheck.livenessHeartbeatInterval | default 10 | int 
}}
+_liveness_thread = None
+_liveness_stop_event = None
+
+# Readiness Probe: Create/remove file based on worker state
+# These signals only fire for workers, safe to register globally
+@worker_ready.connect
+def create_ready_file(sender, **kwargs):
+    """Create readiness file when Celery worker is ready to process tasks"""
+    try:
+        open(_readiness_file, 'w').close()
+        print(f"Celery worker ready - created {_readiness_file}")
+    except Exception as e:
+        print(f"Warning: Could not create readiness file: {e}")
+
+@worker_shutdown.connect
+def remove_ready_file(sender, **kwargs):
+    """Remove readiness file when Celery worker is shutting down"""
+    global _liveness_thread, _liveness_stop_event
+    # Stop the liveness heartbeat thread
+    if _liveness_stop_event:
+        _liveness_stop_event.set()
+    if _liveness_thread:
+        _liveness_thread.join(timeout=5)
+    # Remove health check files
+    try:
+        if os.path.exists(_readiness_file):
+            os.remove(_readiness_file)
+            print(f"Celery worker shutdown - removed {_readiness_file}")
+        if os.path.exists(_liveness_file):
+            os.remove(_liveness_file)
+            print(f"Celery worker shutdown - removed {_liveness_file}")
+    except Exception as e:
+        print(f"Warning: Could not remove health check files: {e}")
+
+# Liveness Probe: Start heartbeat thread when worker initializes
+# worker_init only fires for workers, not beat
+@worker_init.connect
+def start_liveness_heartbeat(sender, **kwargs):
+    """Start the liveness heartbeat thread when worker initializes"""
+    global _liveness_thread, _liveness_stop_event
+    _liveness_stop_event = threading.Event()
+
+    def update_liveness():
+        while not _liveness_stop_event.is_set():
+            try:
+                with open(_liveness_file, 'w') as f:
+                    f.write(str(os.getpid()))
+            except Exception as e:
+                print(f"Warning: Could not update liveness file: {e}")
+            _liveness_stop_event.wait(_heartbeat_interval)
+
+    _liveness_thread = threading.Thread(target=update_liveness, daemon=True)
+    _liveness_thread.start()
+    print(f"Celery liveness heartbeat started - updating {_liveness_file} 
every {_heartbeat_interval}s")
+{{- else }}
+CELERY_WORKER_HEALTH_CHECK_ENABLED = False
+{{- end }}
+
+{{- /* Results Backend */}}
+{{- if .Values.config.resultsBackend }}
+{{- if kindIs "string" .Values.config.resultsBackend }}
+RESULTS_BACKEND = {{ .Values.config.resultsBackend }}
+{{- else }}
 RESULTS_BACKEND = RedisCache(
-      host=env('REDIS_HOST'),
-      {{- if .Values.supersetNode.connections.redis_password }}
-      password=env('REDIS_PASSWORD'),
-      {{- end }}
-      port=env('REDIS_PORT'),
-      key_prefix='superset_results',
-      {{- if .Values.supersetNode.connections.redis_ssl.enabled }}
-      ssl=True,
-      ssl_cert_reqs=env('REDIS_SSL_CERT_REQS'),
-      {{- end }}
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
 )
+{{- end }}
+{{- else if .Values.cache.enabled }}
+RESULTS_BACKEND = RedisCache(
+    host={{ .Values.cache.host | quote }},
+    {{- if .Values.cache.password }}
+    password={{ .Values.cache.password | quote }},
+    {{- end }}
+    port={{ .Values.cache.port | int }},
+    key_prefix={{ .Values.cache.resultsBackendKeyPrefix | default 
"superset_results" | quote }},
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    ssl=True,
+    ssl_cert_reqs={{ .Values.cache.ssl.ssl_cert_reqs | default "required" | 
quote }},
+    {{- end }}
+)
+{{- end }}
+
+{{- /* Global Async Queries Cache Backend - Required when using 
GLOBAL_ASYNC_QUERIES feature flag */}}
+{{- if .Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {{ 
.Values.config.GLOBAL_ASYNC_QUERIES_CACHE_BACKEND | toJson | indent 2 }}
+{{- else if .Values.cache.enabled }}
+GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
+    "CACHE_TYPE": "RedisCache",
+    "CACHE_REDIS_HOST": {{ .Values.cache.host | quote }},
+    "CACHE_REDIS_PORT": {{ .Values.cache.port | int }},
+    "CACHE_REDIS_USER": {{ .Values.cache.user | default "" | quote }},
+    {{- if .Values.cache.password }}
+    "CACHE_REDIS_PASSWORD": {{ .Values.cache.password | quote }},
+    {{- else }}
+    "CACHE_REDIS_PASSWORD": "",
+    {{- end }}
+    "CACHE_REDIS_DB": {{ .Values.cache.asyncQueries.db | default 
.Values.cache.cacheDb | default 0 | int }},
+    "CACHE_KEY_PREFIX": {{ .Values.cache.asyncQueries.keyPrefix | default 
"qc-" | quote }},
+    "CACHE_DEFAULT_TIMEOUT": {{ .Values.cache.asyncQueries.timeout | default 
86400 | int }},
+    {{- if .Values.cache.sentinel }}
+    {{- if .Values.cache.sentinel.sentinels }}
+    "CACHE_REDIS_SENTINELS": {{ .Values.cache.sentinel.sentinels | toJson }},
+    {{- else }}
+    {{- fail "CONFIGURATION ERROR: cache.sentinel.enabled is true but 
cache.sentinel.sentinels is not set. You must provide Sentinel host(s) in 
cache.sentinel.sentinels (e.g., [['sentinel-host', 26379]])." }}
+    {{- end }}
+    "CACHE_REDIS_SENTINEL_MASTER": {{ .Values.cache.sentinel.master | default 
"mymaster" | quote }},
+    {{- if .Values.cache.sentinel.password }}
+    "CACHE_REDIS_SENTINEL_PASSWORD": {{ .Values.cache.sentinel.password | 
quote }},
+    {{- else }}
+    "CACHE_REDIS_SENTINEL_PASSWORD": None,
+    {{- end }}
+    {{- end }}
+    {{- if and (hasKey .Values.cache "ssl") .Values.cache.ssl.enabled }}
+    "CACHE_REDIS_SSL": True,
+    "CACHE_REDIS_SSL_CERTFILE": {{ .Values.cache.ssl.certfile | default "None" 
}},
+    "CACHE_REDIS_SSL_KEYFILE": {{ .Values.cache.ssl.keyfile | default "None" 
}},
+    "CACHE_REDIS_SSL_CERT_REQS": {{ .Values.cache.ssl.ssl_cert_reqs | default 
"required" | quote }},
+    "CACHE_REDIS_SSL_CA_CERTS": {{ .Values.cache.ssl.ca_certs | default "None" 
}},

Review Comment:
   **Suggestion:** SSL file path values are emitted without quotes, so any 
configured path (for example `/etc/ssl/cert.pem`) is rendered as invalid Python 
syntax. Render string paths as quoted strings and keep `None` when unset. [type 
error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ TLS path configuration can break Python config parsing.
   - ⚠️ All components consume same invalid Secret config.
   ```
   </details>
   
   ```suggestion
       "CACHE_REDIS_SSL_CERTFILE": {{ if .Values.cache.ssl.certfile }}{{ 
.Values.cache.ssl.certfile | quote }}{{ else }}None{{ end }},
       "CACHE_REDIS_SSL_KEYFILE": {{ if .Values.cache.ssl.keyfile }}{{ 
.Values.cache.ssl.keyfile | quote }}{{ else }}None{{ end }},
       "CACHE_REDIS_SSL_CA_CERTS": {{ if .Values.cache.ssl.ca_certs }}{{ 
.Values.cache.ssl.ca_certs | quote }}{{ else }}None{{ end }},
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Set TLS file paths in values (`cache.ssl.certfile/keyfile/ca_certs`), 
whose defaults
   are documented at `helm/superset/values.yaml:90-95`.
   
   2. Ensure cache is enabled (`values.yaml:37-38`, default true), which 
activates GAQ cache
   backend block at `_helpers.tpl:277-317`.
   
   3. Install/upgrade so `secret-superset-config.yaml:41` emits these lines 
unquoted at
   `_helpers.tpl:445-448` (e.g., `/etc/ssl/cert.pem`).
   
   4. Python parses `/` as operators, producing invalid config syntax and 
preventing
   Superset/Celery startup across pods mounting `/app/pythonpath` config Secret.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** helm/superset/templates/_helpers.tpl
   **Line:** 445:448
   **Comment:**
        *Type Error: SSL file path values are emitted without quotes, so any 
configured path (for example `/etc/ssl/cert.pem`) is rendered as invalid Python 
syntax. Render string paths as quoted strings and keep `None` when unset.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=db72893bf91528ce325904f5db4fafb2de9720b005e7d47a54a48617168bf463&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38597&comment_hash=db72893bf91528ce325904f5db4fafb2de9720b005e7d47a54a48617168bf463&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to