Enhance Windows Compatibility with Event Loop Policy and Path Resolution (#3986)

Co-authored-by: Suchintan <suchintan@users.noreply.github.com>
Co-authored-by: Shuchang Zheng <wintonzheng0325@gmail.com>
Co-authored-by: Stanislav Novosad <stas@skyvern.com>
This commit is contained in:
Mohamed Khalil
2025-11-20 05:16:16 +02:00
committed by GitHub
parent db68d8a60c
commit d975ca0913
6 changed files with 71 additions and 11 deletions

View File

@@ -1,3 +1,7 @@
import logging
import platform
from typing import Any
from pydantic_settings import BaseSettings, SettingsConfigDict
from skyvern import constants
@@ -16,6 +20,9 @@ _DEFAULT_ENV_FILES = (
)
LOG = logging.getLogger(__name__)
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=_DEFAULT_ENV_FILES, extra="ignore")
@@ -46,7 +53,11 @@ class Settings(BaseSettings):
LONG_RUNNING_TASK_WARNING_RATIO: float = 0.95
MAX_RETRIES_PER_STEP: int = 5
DEBUG_MODE: bool = False
DATABASE_STRING: str = "postgresql+psycopg://skyvern@localhost/skyvern"
DATABASE_STRING: str = (
"postgresql+asyncpg://skyvern@localhost/skyvern"
if platform.system() == "Windows"
else "postgresql+psycopg://skyvern@localhost/skyvern"
)
DATABASE_STATEMENT_TIMEOUT_MS: int = 60000
DISABLE_CONNECTION_POOL: bool = False
PROMPT_ACTION_HISTORY_WINDOW: int = 1
@@ -460,6 +471,29 @@ class Settings(BaseSettings):
},
}
def model_post_init(self, __context: Any) -> None: # type: ignore[override]
super().model_post_init(__context)
if platform.system() != "Windows":
return
scheme, sep, remainder = self.DATABASE_STRING.partition("://")
if not sep:
return
dialect, driver_sep, driver = scheme.partition("+")
if not driver_sep or driver not in {"psycopg", "psycopg2"}:
return
updated_string = f"{dialect}+asyncpg://{remainder}"
if updated_string == self.DATABASE_STRING:
return
LOG.warning(
"Detected Windows environment: switching DATABASE_STRING driver from psycopg to asyncpg "
"for compatibility with the Proactor event loop policy."
)
object.__setattr__(self, "DATABASE_STRING", updated_string)
def is_cloud_environment(self) -> bool:
"""
:return: True if env is not local, else False