chore: move goodbye message to main process (#8695)

* move goodbye message to main process

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Jordan Frazier 2025-06-24 08:27:18 -07:00 • committed by GitHub
commit 9f817ca4fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 47 additions and 19 deletions

View file

@ -47,6 +47,10 @@ class ProcessManager:
def __init__(self): def __init__(self):
self.webapp_process = None self.webapp_process = None
self.shutdown_in_progress = False self.shutdown_in_progress = False
if platform.system() == "Windows":
self._farewell_emoji = ":)" # ASCII smiley
else:
self._farewell_emoji = "👋" # Unicode wave
# params are required for signal handlers, even if they are not used # params are required for signal handlers, even if they are not used
def handle_sigterm(self, _signum: int, _frame) -> None: def handle_sigterm(self, _signum: int, _frame) -> None:
@ -78,8 +82,21 @@ class ProcessManager:
logger.warning("Process didn't terminate gracefully, killing it.") logger.warning("Process didn't terminate gracefully, killing it.")
self.webapp_process.kill() self.webapp_process.kill()
self.webapp_process.join() self.webapp_process.join()
self.print_farewell_message()
sys.exit(0) sys.exit(0)
def print_farewell_message(self) -> None:
"""Print a nice farewell message after shutdown is complete."""
# Clear any progress indicator output that might be on the current line
sys.stdout.write("\r") # Move cursor to beginning of line
sys.stdout.write(" " * 80) # Clear the line with spaces
sys.stdout.write("\r") # Move cursor back to beginning
click.echo()
farewell = click.style(f"{self._farewell_emoji} See you next time!", fg="bright_blue", bold=True)
click.echo(farewell)
# Create a single instance of ProcessManager # Create a single instance of ProcessManager
process_manager = ProcessManager() process_manager = ProcessManager()

View file

@ -178,12 +178,6 @@ class ProgressIndicator:
click.echo() click.echo()
click.echo(click.style(f"Total shutdown time: {total_time:.2f}s", fg="bright_black")) click.echo(click.style(f"Total shutdown time: {total_time:.2f}s", fg="bright_black"))
def print_farewell_message(self) -> None:
"""Print a nice farewell message after shutdown is complete."""
click.echo()
farewell = click.style(f"{self._farewell_emoji} See you next time!", fg="bright_blue", bold=True)
click.echo(farewell)
def create_langflow_progress(*, verbose: bool = False) -> ProgressIndicator: def create_langflow_progress(*, verbose: bool = False) -> ProgressIndicator:
"""Create a progress indicator with predefined Langflow initialization steps.""" """Create a progress indicator with predefined Langflow initialization steps."""
@ -206,18 +200,32 @@ def create_langflow_progress(*, verbose: bool = False) -> ProgressIndicator:
return progress return progress
def create_langflow_shutdown_progress(*, verbose: bool = False) -> ProgressIndicator: def create_langflow_shutdown_progress(*, verbose: bool = False, multiple_workers: bool = False) -> ProgressIndicator:
"""Create a progress indicator with predefined Langflow shutdown steps.""" """Create a progress indicator with predefined Langflow shutdown steps."""
progress = ProgressIndicator(verbose=verbose) progress = ProgressIndicator(verbose=verbose)
# Define the shutdown steps in reverse order of initialization # Define the shutdown steps in reverse order of initialization
steps = [ if multiple_workers:
("Stopping Server", "Gracefully stopping the web server"), import os
("Cancelling Background Tasks", "Stopping file synchronization and background jobs"),
("Cleaning Up Services", "Teardown database connections and services"), steps = [
("Clearing Temporary Files", "Removing temporary directories and cache"), (f"[Worker PID {os.getpid()}] Stopping Server", "Gracefully stopping the web server"),
("Finalizing Shutdown", "Completing cleanup and logging"), (
] f"[Worker PID {os.getpid()}] Cancelling Background Tasks",
"Stopping file synchronization and background jobs",
),
(f"[Worker PID {os.getpid()}] Cleaning Up Services", "Teardown database connections and services"),
(f"[Worker PID {os.getpid()}] Clearing Temporary Files", "Removing temporary directories and cache"),
(f"[Worker PID {os.getpid()}] Finalizing Shutdown", "Completing cleanup and logging"),
]
else:
steps = [
("Stopping Server", "Gracefully stopping the web server"),
("Cancelling Background Tasks", "Stopping file synchronization and background jobs"),
("Cleaning Up Services", "Teardown database connections and services"),
("Clearing Temporary Files", "Removing temporary directories and cache"),
("Finalizing Shutdown", "Completing cleanup and logging"),
]
for title, description in steps: for title, description in steps:
progress.add_step(title, description) progress.add_step(title, description)

View file

@ -191,10 +191,14 @@ def get_lifespan(*, fix_migration=False, version=None):
finally: finally:
# Clean shutdown with progress indicator # Clean shutdown with progress indicator
# Create shutdown progress (show verbose timing if log level is DEBUG) # Create shutdown progress (show verbose timing if log level is DEBUG)
from langflow.__main__ import get_number_of_workers
from langflow.cli.progress import create_langflow_shutdown_progress from langflow.cli.progress import create_langflow_shutdown_progress
log_level = os.getenv("LANGFLOW_LOG_LEVEL", "info").lower() log_level = os.getenv("LANGFLOW_LOG_LEVEL", "info").lower()
shutdown_progress = create_langflow_shutdown_progress(verbose=log_level == "debug") num_workers = get_number_of_workers(get_settings_service().settings.workers)
shutdown_progress = create_langflow_shutdown_progress(
verbose=log_level == "debug", multiple_workers=num_workers > 1
)
try: try:
# Step 0: Stopping Server # Step 0: Stopping Server
@ -227,7 +231,6 @@ def get_lifespan(*, fix_migration=False, version=None):
# Show completion summary and farewell # Show completion summary and farewell
shutdown_progress.print_shutdown_summary() shutdown_progress.print_shutdown_summary()
shutdown_progress.print_farewell_message()
except (sqlalchemy.exc.OperationalError, sqlalchemy.exc.DBAPIError) as e: except (sqlalchemy.exc.OperationalError, sqlalchemy.exc.DBAPIError) as e:
# Case where the database connection is closed during shutdown # Case where the database connection is closed during shutdown

6
uv.lock generated
View file

@ -4085,11 +4085,11 @@ wheels = [
[[package]] [[package]]
name = "junitparser" name = "junitparser"
version = "4.0.0" version = "4.0.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6e/c7/c5741009c9956053f0bffdac6b25c5dd6e53f4c0c2ed4d58956ea0739d46/junitparser-4.0.0.tar.gz", hash = "sha256:e9d234356172750a8b49708500a84bd9fb47c779d629b124de89a3070b310320", size = 25598, upload-time = "2025-06-22T19:45:57.166Z" } sdist = { url = "https://files.pythonhosted.org/packages/13/cc/b6ec3f011725b06053c1e849b0be623176951ea518429128c01b73d45b8a/junitparser-4.0.1.tar.gz", hash = "sha256:00be98abaddef8c135db6bda3a52beb801b9b0f698da8cb1572ac2091ceae668", size = 25588, upload-time = "2025-06-23T21:56:43.184Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/bd/a795422f9542204e0d32095cb3d2c7916d23043be2d67fa59ba8d69c7c87/junitparser-4.0.0-py3-none-any.whl", hash = "sha256:715b624d0bc40bfc4a31099aa24202bf8aab7933c65ad537e7e34cb9290cd51f", size = 14566, upload-time = "2025-06-22T19:45:55.961Z" }, { url = "https://files.pythonhosted.org/packages/96/7f/7a2634e5bc4c4b4b02cbd3fdcd4d99763be04d4e71e2260d647f6146cfe4/junitparser-4.0.1-py3-none-any.whl", hash = "sha256:9c142c3d688c1674cd66905d96963b5e047f9fc079fe66d462b5cd12cf128d55", size = 14566, upload-time = "2025-06-23T21:56:42.004Z" },
] ]
[[package]] [[package]]