From a4b38e7521bfd139e3c631115e625f221e836499 Mon Sep 17 00:00:00 2001 From: crazywoola <100913391+crazywoola@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:40:41 +0800 Subject: [PATCH 1/5] Revert "Sync log detail drawer with conversation_id query parameter, so that we can share a specific conversation" (#27382) --- web/app/components/app/log/list.tsx | 120 ++++------------------------ 1 file changed, 17 insertions(+), 103 deletions(-) diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 258d06ac79..8b3370b678 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -14,7 +14,6 @@ import timezone from 'dayjs/plugin/timezone' import { createContext, useContext } from 'use-context-selector' import { useShallow } from 'zustand/react/shallow' import { useTranslation } from 'react-i18next' -import { usePathname, useRouter, useSearchParams } from 'next/navigation' import type { ChatItemInTree } from '../../base/chat/types' import Indicator from '../../header/indicator' import VarPanel from './var-panel' @@ -43,10 +42,6 @@ import cn from '@/utils/classnames' import { noop } from 'lodash-es' import PromptLogModal from '../../base/prompt-log-modal' -type AppStoreState = ReturnType -type ConversationListItem = ChatConversationGeneralDetail | CompletionConversationGeneralDetail -type ConversationSelection = ConversationListItem | { id: string; isPlaceholder?: true } - dayjs.extend(utc) dayjs.extend(timezone) @@ -206,7 +201,7 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) { const { formatTime } = useTimestamp() const { onClose, appDetail } = useContext(DrawerContext) const { notify } = useContext(ToastContext) - const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow((state: AppStoreState) => ({ + const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({ currentLogItem: state.currentLogItem, setCurrentLogItem: state.setCurrentLogItem, showMessageLogModal: state.showMessageLogModal, @@ -898,113 +893,20 @@ const ChatConversationDetailComp: FC<{ appId?: string; conversationId?: string } const ConversationList: FC = ({ logs, appDetail, onRefresh }) => { const { t } = useTranslation() const { formatTime } = useTimestamp() - const router = useRouter() - const pathname = usePathname() - const searchParams = useSearchParams() - const conversationIdInUrl = searchParams.get('conversation_id') ?? undefined const media = useBreakpoints() const isMobile = media === MediaType.mobile const [showDrawer, setShowDrawer] = useState(false) // Whether to display the chat details drawer - const [currentConversation, setCurrentConversation] = useState() // Currently selected conversation - const closingConversationIdRef = useRef(null) - const pendingConversationIdRef = useRef(null) - const pendingConversationCacheRef = useRef(undefined) + const [currentConversation, setCurrentConversation] = useState() // Currently selected conversation const isChatMode = appDetail.mode !== 'completion' // Whether the app is a chat app const isChatflow = appDetail.mode === 'advanced-chat' // Whether the app is a chatflow app - const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow((state: AppStoreState) => ({ + const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow(state => ({ setShowPromptLogModal: state.setShowPromptLogModal, setShowAgentLogModal: state.setShowAgentLogModal, setShowMessageLogModal: state.setShowMessageLogModal, }))) - const activeConversationId = conversationIdInUrl ?? pendingConversationIdRef.current ?? currentConversation?.id - - const buildUrlWithConversation = useCallback((conversationId?: string) => { - const params = new URLSearchParams(searchParams.toString()) - if (conversationId) - params.set('conversation_id', conversationId) - else - params.delete('conversation_id') - - const queryString = params.toString() - return queryString ? `${pathname}?${queryString}` : pathname - }, [pathname, searchParams]) - - const handleRowClick = useCallback((log: ConversationListItem) => { - if (conversationIdInUrl === log.id) { - if (!showDrawer) - setShowDrawer(true) - - if (!currentConversation || currentConversation.id !== log.id) - setCurrentConversation(log) - return - } - - pendingConversationIdRef.current = log.id - pendingConversationCacheRef.current = log - if (!showDrawer) - setShowDrawer(true) - - if (currentConversation?.id !== log.id) - setCurrentConversation(undefined) - - router.push(buildUrlWithConversation(log.id), { scroll: false }) - }, [buildUrlWithConversation, conversationIdInUrl, currentConversation, router, showDrawer]) - - const currentConversationId = currentConversation?.id - - useEffect(() => { - if (!conversationIdInUrl) { - if (pendingConversationIdRef.current) - return - - if (showDrawer || currentConversationId) { - setShowDrawer(false) - setCurrentConversation(undefined) - } - closingConversationIdRef.current = null - pendingConversationCacheRef.current = undefined - return - } - - if (closingConversationIdRef.current === conversationIdInUrl) - return - - if (pendingConversationIdRef.current === conversationIdInUrl) - pendingConversationIdRef.current = null - - const matchedConversation = logs?.data?.find((item: ConversationListItem) => item.id === conversationIdInUrl) - const nextConversation: ConversationSelection = matchedConversation - ?? pendingConversationCacheRef.current - ?? { id: conversationIdInUrl, isPlaceholder: true } - - if (!showDrawer) - setShowDrawer(true) - - if (!currentConversation || currentConversation.id !== conversationIdInUrl || (matchedConversation && currentConversation !== matchedConversation)) - setCurrentConversation(nextConversation) - - if (pendingConversationCacheRef.current?.id === conversationIdInUrl || matchedConversation) - pendingConversationCacheRef.current = undefined - }, [conversationIdInUrl, currentConversation, isChatMode, logs?.data, showDrawer]) - - const onCloseDrawer = useCallback(() => { - onRefresh() - setShowDrawer(false) - setCurrentConversation(undefined) - setShowPromptLogModal(false) - setShowAgentLogModal(false) - setShowMessageLogModal(false) - pendingConversationIdRef.current = null - pendingConversationCacheRef.current = undefined - closingConversationIdRef.current = conversationIdInUrl ?? null - - if (conversationIdInUrl) - router.replace(buildUrlWithConversation(), { scroll: false }) - }, [buildUrlWithConversation, conversationIdInUrl, onRefresh, router, setShowAgentLogModal, setShowMessageLogModal, setShowPromptLogModal]) - // Annotated data needs to be highlighted const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => { return ( @@ -1023,6 +925,15 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) ) } + const onCloseDrawer = () => { + onRefresh() + setShowDrawer(false) + setCurrentConversation(undefined) + setShowPromptLogModal(false) + setShowAgentLogModal(false) + setShowMessageLogModal(false) + } + if (!logs) return @@ -1049,8 +960,11 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) const rightValue = get(log, isChatMode ? 'message_count' : 'message.answer') return handleRowClick(log)}> + className={cn('cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover', currentConversation?.id !== log.id ? '' : 'bg-background-default-hover')} + onClick={() => { + setShowDrawer(true) + setCurrentConversation(log) + }}> {!log.read_at && (
From 634fb192efe2cabedf664497ca0e2f95f086f8d0 Mon Sep 17 00:00:00 2001 From: Novice Date: Fri, 24 Oct 2025 10:41:14 +0800 Subject: [PATCH 2/5] fix: remove unnecessary Flask context preservation to avoid circular import in audio service (#27380) --- api/services/audio_service.py | 81 +++++++++++++++++------------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/api/services/audio_service.py b/api/services/audio_service.py index 1158fc5197..41ee9c88aa 100644 --- a/api/services/audio_service.py +++ b/api/services/audio_service.py @@ -82,54 +82,51 @@ class AudioService: message_id: str | None = None, is_draft: bool = False, ): - from app import app - def invoke_tts(text_content: str, app_model: App, voice: str | None = None, is_draft: bool = False): - with app.app_context(): - if voice is None: - if app_model.mode in {AppMode.ADVANCED_CHAT, AppMode.WORKFLOW}: - if is_draft: - workflow = WorkflowService().get_draft_workflow(app_model=app_model) - else: - workflow = app_model.workflow - if ( - workflow is None - or "text_to_speech" not in workflow.features_dict - or not workflow.features_dict["text_to_speech"].get("enabled") - ): + if voice is None: + if app_model.mode in {AppMode.ADVANCED_CHAT, AppMode.WORKFLOW}: + if is_draft: + workflow = WorkflowService().get_draft_workflow(app_model=app_model) + else: + workflow = app_model.workflow + if ( + workflow is None + or "text_to_speech" not in workflow.features_dict + or not workflow.features_dict["text_to_speech"].get("enabled") + ): + raise ValueError("TTS is not enabled") + + voice = workflow.features_dict["text_to_speech"].get("voice") + else: + if not is_draft: + if app_model.app_model_config is None: + raise ValueError("AppModelConfig not found") + text_to_speech_dict = app_model.app_model_config.text_to_speech_dict + + if not text_to_speech_dict.get("enabled"): raise ValueError("TTS is not enabled") - voice = workflow.features_dict["text_to_speech"].get("voice") - else: - if not is_draft: - if app_model.app_model_config is None: - raise ValueError("AppModelConfig not found") - text_to_speech_dict = app_model.app_model_config.text_to_speech_dict + voice = text_to_speech_dict.get("voice") - if not text_to_speech_dict.get("enabled"): - raise ValueError("TTS is not enabled") - - voice = text_to_speech_dict.get("voice") - - model_manager = ModelManager() - model_instance = model_manager.get_default_model_instance( - tenant_id=app_model.tenant_id, model_type=ModelType.TTS - ) - try: - if not voice: - voices = model_instance.get_tts_voices() - if voices: - voice = voices[0].get("value") - if not voice: - raise ValueError("Sorry, no voice available.") - else: + model_manager = ModelManager() + model_instance = model_manager.get_default_model_instance( + tenant_id=app_model.tenant_id, model_type=ModelType.TTS + ) + try: + if not voice: + voices = model_instance.get_tts_voices() + if voices: + voice = voices[0].get("value") + if not voice: raise ValueError("Sorry, no voice available.") + else: + raise ValueError("Sorry, no voice available.") - return model_instance.invoke_tts( - content_text=text_content.strip(), user=end_user, tenant_id=app_model.tenant_id, voice=voice - ) - except Exception as e: - raise e + return model_instance.invoke_tts( + content_text=text_content.strip(), user=end_user, tenant_id=app_model.tenant_id, voice=voice + ) + except Exception as e: + raise e if message_id: try: From fa6d03c979b4c2c5403fe243bdca3feb577483db Mon Sep 17 00:00:00 2001 From: Yunlu Wen Date: Fri, 24 Oct 2025 13:09:34 +0800 Subject: [PATCH 3/5] Fix/refresh token (#27381) --- api/controllers/console/auth/login.py | 3 ++- api/libs/token.py | 29 ++++----------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/api/controllers/console/auth/login.py b/api/controllers/console/auth/login.py index c0a565b5da..77ecd5a5e4 100644 --- a/api/controllers/console/auth/login.py +++ b/api/controllers/console/auth/login.py @@ -29,6 +29,7 @@ from libs.token import ( clear_access_token_from_cookie, clear_csrf_token_from_cookie, clear_refresh_token_from_cookie, + extract_refresh_token, set_access_token_to_cookie, set_csrf_token_to_cookie, set_refresh_token_to_cookie, @@ -270,7 +271,7 @@ class EmailCodeLoginApi(Resource): class RefreshTokenApi(Resource): def post(self): # Get refresh token from cookie instead of request body - refresh_token = request.cookies.get("refresh_token") + refresh_token = extract_refresh_token(request) if not refresh_token: return {"result": "fail", "message": "No refresh token provided"}, 401 diff --git a/api/libs/token.py b/api/libs/token.py index 0b40f18143..b53663c89a 100644 --- a/api/libs/token.py +++ b/api/libs/token.py @@ -38,9 +38,6 @@ def _real_cookie_name(cookie_name: str) -> str: def _try_extract_from_header(request: Request) -> str | None: - """ - Try to extract access token from header - """ auth_header = request.headers.get("Authorization") if auth_header: if " " not in auth_header: @@ -55,27 +52,19 @@ def _try_extract_from_header(request: Request) -> str | None: return None +def extract_refresh_token(request: Request) -> str | None: + return request.cookies.get(_real_cookie_name(COOKIE_NAME_REFRESH_TOKEN)) + + def extract_csrf_token(request: Request) -> str | None: - """ - Try to extract CSRF token from header or cookie. - """ return request.headers.get(HEADER_NAME_CSRF_TOKEN) def extract_csrf_token_from_cookie(request: Request) -> str | None: - """ - Try to extract CSRF token from cookie. - """ return request.cookies.get(_real_cookie_name(COOKIE_NAME_CSRF_TOKEN)) def extract_access_token(request: Request) -> str | None: - """ - Try to extract access token from cookie, header or params. - - Access token is either for console session or webapp passport exchange. - """ - def _try_extract_from_cookie(request: Request) -> str | None: return request.cookies.get(_real_cookie_name(COOKIE_NAME_ACCESS_TOKEN)) @@ -83,20 +72,10 @@ def extract_access_token(request: Request) -> str | None: def extract_webapp_access_token(request: Request) -> str | None: - """ - Try to extract webapp access token from cookie, then header. - """ - return request.cookies.get(_real_cookie_name(COOKIE_NAME_WEBAPP_ACCESS_TOKEN)) or _try_extract_from_header(request) def extract_webapp_passport(app_code: str, request: Request) -> str | None: - """ - Try to extract app token from header or params. - - Webapp access token (part of passport) is only used for webapp session. - """ - def _try_extract_passport_token_from_cookie(request: Request) -> str | None: return request.cookies.get(_real_cookie_name(COOKIE_NAME_PASSPORT + "-" + app_code)) From eabdb09f8eb9fb233794b47dba140071953efd71 Mon Sep 17 00:00:00 2001 From: Novice Date: Fri, 24 Oct 2025 13:29:47 +0800 Subject: [PATCH 4/5] fix: support webapp passport token with end_user_id in web API auth (#27396) --- api/extensions/ext_login.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/api/extensions/ext_login.py b/api/extensions/ext_login.py index ed4fe332c1..74299956c0 100644 --- a/api/extensions/ext_login.py +++ b/api/extensions/ext_login.py @@ -6,10 +6,11 @@ from flask_login import user_loaded_from_request, user_logged_in from werkzeug.exceptions import NotFound, Unauthorized from configs import dify_config +from constants import HEADER_NAME_APP_CODE from dify_app import DifyApp from extensions.ext_database import db from libs.passport import PassportService -from libs.token import extract_access_token +from libs.token import extract_access_token, extract_webapp_passport from models import Account, Tenant, TenantAccountJoin from models.model import AppMCPServer, EndUser from services.account_service import AccountService @@ -61,14 +62,30 @@ def load_user_from_request(request_from_flask_login): logged_in_account = AccountService.load_logged_in_account(account_id=user_id) return logged_in_account elif request.blueprint == "web": - decoded = PassportService().verify(auth_token) - end_user_id = decoded.get("end_user_id") - if not end_user_id: - raise Unauthorized("Invalid Authorization token.") - end_user = db.session.query(EndUser).where(EndUser.id == decoded["end_user_id"]).first() - if not end_user: - raise NotFound("End user not found.") - return end_user + app_code = request.headers.get(HEADER_NAME_APP_CODE) + webapp_token = extract_webapp_passport(app_code, request) if app_code else None + + if webapp_token: + decoded = PassportService().verify(webapp_token) + end_user_id = decoded.get("end_user_id") + if not end_user_id: + raise Unauthorized("Invalid Authorization token.") + end_user = db.session.query(EndUser).where(EndUser.id == end_user_id).first() + if not end_user: + raise NotFound("End user not found.") + return end_user + else: + if not auth_token: + raise Unauthorized("Invalid Authorization token.") + decoded = PassportService().verify(auth_token) + end_user_id = decoded.get("end_user_id") + if end_user_id: + end_user = db.session.query(EndUser).where(EndUser.id == end_user_id).first() + if not end_user: + raise NotFound("End user not found.") + return end_user + else: + raise Unauthorized("Invalid Authorization token for web API.") elif request.blueprint == "mcp": server_code = request.view_args.get("server_code") if request.view_args else None if not server_code: From dc7ce125ad0f406bba445811c48e5aa0d22dd612 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Fri, 24 Oct 2025 13:46:36 +0800 Subject: [PATCH 5/5] chore: disable postgres timeouts for docker workflows (#27397) --- docker/.env.example | 10 ++++++---- docker/docker-compose-template.yaml | 4 ++-- docker/docker-compose.middleware.yaml | 4 ++-- docker/docker-compose.yaml | 8 ++++---- docker/middleware.env.example | 10 ++++++---- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docker/.env.example b/docker/.env.example index ca580dcb79..cbf9cbb912 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -260,16 +260,18 @@ POSTGRES_MAINTENANCE_WORK_MEM=64MB POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB # Sets the maximum allowed duration of any statement before termination. -# Default is 60000 milliseconds. +# Default is 0 (no timeout). # # Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT -POSTGRES_STATEMENT_TIMEOUT=60000 +# A value of 0 prevents the server from timing out statements. +POSTGRES_STATEMENT_TIMEOUT=0 # Sets the maximum allowed duration of any idle in-transaction session before termination. -# Default is 60000 milliseconds. +# Default is 0 (no timeout). # # Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT -POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT=60000 +# A value of 0 prevents the server from terminating idle sessions. +POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT=0 # ------------------------------ # Redis Configuration diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 9650be90db..886335a96b 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -115,8 +115,8 @@ services: -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' - -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-60000}' - -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-60000}' + -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}' + -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}' volumes: - ./volumes/db/data:/var/lib/postgresql/data healthcheck: diff --git a/docker/docker-compose.middleware.yaml b/docker/docker-compose.middleware.yaml index 9a1b9b53ba..0497e9d1f6 100644 --- a/docker/docker-compose.middleware.yaml +++ b/docker/docker-compose.middleware.yaml @@ -15,8 +15,8 @@ services: -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' - -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-60000}' - -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-60000}' + -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}' + -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}' volumes: - ${PGDATA_HOST_VOLUME:-./volumes/db/data}:/var/lib/postgresql/data ports: diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index d2ca6b859e..a18138509c 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -68,8 +68,8 @@ x-shared-env: &shared-api-worker-env POSTGRES_WORK_MEM: ${POSTGRES_WORK_MEM:-4MB} POSTGRES_MAINTENANCE_WORK_MEM: ${POSTGRES_MAINTENANCE_WORK_MEM:-64MB} POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB} - POSTGRES_STATEMENT_TIMEOUT: ${POSTGRES_STATEMENT_TIMEOUT:-60000} - POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: ${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-60000} + POSTGRES_STATEMENT_TIMEOUT: ${POSTGRES_STATEMENT_TIMEOUT:-0} + POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT: ${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0} REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_USERNAME: ${REDIS_USERNAME:-} @@ -724,8 +724,8 @@ services: -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' - -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-60000}' - -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-60000}' + -c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}' + -c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}' volumes: - ./volumes/db/data:/var/lib/postgresql/data healthcheck: diff --git a/docker/middleware.env.example b/docker/middleware.env.example index c9bb8c0528..24629c2d89 100644 --- a/docker/middleware.env.example +++ b/docker/middleware.env.example @@ -41,16 +41,18 @@ POSTGRES_MAINTENANCE_WORK_MEM=64MB POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB # Sets the maximum allowed duration of any statement before termination. -# Default is 60000 milliseconds. +# Default is 0 (no timeout). # # Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT -POSTGRES_STATEMENT_TIMEOUT=60000 +# A value of 0 prevents the server from timing out statements. +POSTGRES_STATEMENT_TIMEOUT=0 # Sets the maximum allowed duration of any idle in-transaction session before termination. -# Default is 60000 milliseconds. +# Default is 0 (no timeout). # # Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT -POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT=60000 +# A value of 0 prevents the server from terminating idle sessions. +POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT=0 # ----------------------------- # Environment Variables for redis Service