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):
self.webapp_process = None
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
def handle_sigterm(self, _signum: int, _frame) -> None:
@ -78,8 +82,21 @@ class ProcessManager:
logger.warning("Process didn't terminate gracefully, killing it.")
self.webapp_process.kill()
self.webapp_process.join()
self.print_farewell_message()
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
process_manager = ProcessManager()

View file

@ -178,12 +178,6 @@ class ProgressIndicator:
click.echo()
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:
"""Create a progress indicator with predefined Langflow initialization steps."""
@ -206,18 +200,32 @@ def create_langflow_progress(*, verbose: bool = False) -> ProgressIndicator:
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."""
progress = ProgressIndicator(verbose=verbose)
# Define the shutdown steps in reverse order of initialization
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"),
]
if multiple_workers:
import os
steps = [
(f"[Worker PID {os.getpid()}] Stopping Server", "Gracefully stopping the web server"),
(
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:
progress.add_step(title, description)

View file

@ -191,10 +191,14 @@ def get_lifespan(*, fix_migration=False, version=None):
finally:
# Clean shutdown with progress indicator
# 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
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:
# Step 0: Stopping Server
@ -227,7 +231,6 @@ def get_lifespan(*, fix_migration=False, version=None):
# Show completion summary and farewell
shutdown_progress.print_shutdown_summary()
shutdown_progress.print_farewell_message()
except (sqlalchemy.exc.OperationalError, sqlalchemy.exc.DBAPIError) as e:
# Case where the database connection is closed during shutdown

6
uv.lock generated
View file

@ -4085,11 +4085,11 @@ wheels = [
[[package]]
name = "junitparser"
version = "4.0.0"
version = "4.0.1"
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 = [
{ 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]]