### Start and Terminate a Supervised Process Source: https://context7.com/jupyterhub/simpervisor/llms.txt Demonstrates how to start a supervised process, check its running status and PID, and then terminate it. Use this for basic process lifecycle management without automatic restarts. ```python import asyncio import sys from simpervisor import SupervisedProcess async def main(): # Create a supervised process that runs a Python script proc = SupervisedProcess( "my-worker", # Process name for logging sys.executable, "-c", # Command and arguments "import time; time.sleep(10)", always_restart=False, # Don't restart on clean exit ) await proc.start() print(f"Process running: {proc.running}") # True print(f"Process PID: {proc.pid}") # e.g., 12345 # Wait a bit then terminate await asyncio.sleep(1) await proc.terminate() print(f"Process running: {proc.running}") # False print(f"Return code: {proc.returncode}") # -15 (SIGTERM on POSIX) asyncio.run(main()) ``` -------------------------------- ### Supervised Process with HTTP Readiness Check Source: https://context7.com/jupyterhub/simpervisor/llms.txt Illustrates using a custom `ready_func` to check if a supervised HTTP server is responding before considering it ready. Includes environment variable setup and a timeout for the readiness check. ```python import asyncio import os import sys import aiohttp from simpervisor import SupervisedProcess async def check_http_ready(proc): """Check if HTTP server is responding.""" url = "http://localhost:8080" async with aiohttp.ClientSession() as session: try: async with session.get(url) as resp: return resp.status == 200 except aiohttp.ClientConnectionError: return False async def main(): env = os.environ.copy() env["PORT"] = "8080" proc = SupervisedProcess( "http-server", sys.executable, "server.py", ready_func=check_http_ready, # Custom readiness checker ready_timeout=10, # Wait up to 10 seconds for ready env=env, # Environment variables ) await proc.start() # Wait for server to be ready (returns True/False) is_ready = await proc.ready() if is_ready: print("Server is ready to accept connections!") else: print("Server failed to become ready within timeout") # Clean up await proc.kill() asyncio.run(main()) ``` -------------------------------- ### Integrate Custom Logging with SupervisedProcess Source: https://context7.com/jupyterhub/simpervisor/llms.txt Shows how to provide a custom logger instance to `SupervisedProcess` for detailed debug output, enabling integration with an application's existing logging infrastructure. Debug logs will indicate process start, exit, and other lifecycle events. ```python import asyncio import logging import sys from simpervisor import SupervisedProcess # Configure logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("my-app.supervisor") async def main(): proc = SupervisedProcess( "logged-process", sys.executable, "-c", "print('Hello'); import time; time.sleep(1)", log=logger, # Custom logger instance ) await proc.start() # Debug logs will show: "Trying to start logged-process" # Debug logs will show: "Started logged-process" await asyncio.sleep(2) # Debug logs will show: "logged-process exited with code 0" asyncio.run(main()) ``` -------------------------------- ### Update version and tag with tbump (dry run) Source: https://github.com/jupyterhub/simpervisor/blob/main/RELEASE.md Performs a dry run of the version update and tagging process using `tbump`. This command simulates the release without making actual changes, allowing for review. Ensure `tbump` is installed via pip. ```shell pip install tbump tbump --dry-run ${VERSION} ``` -------------------------------- ### Terminate and Kill Supervised Processes Source: https://context7.com/jupyterhub/simpervisor/llms.txt Demonstrates graceful termination using `terminate()` (SIGTERM) and immediate termination using `kill()` (SIGKILL). Shows how `KilledProcessError` is raised when operating on an already killed process. ```python import asyncio import sys from simpervisor import SupervisedProcess, KilledProcessError async def main(): proc = SupervisedProcess( "long-running", sys.executable, "-c", "import time; time.sleep(60)", always_restart=True, ) await proc.start() print(f"Running: {proc.running}") # True # Graceful termination with SIGTERM await proc.terminate() print(f"After terminate - running: {proc.running}") # False # Return code: -15 on POSIX (SIGTERM), 1 on Windows # Attempting any operation after kill raises an error try: await proc.start() except KilledProcessError as e: print(f"Error: {e}") # Process has already been explicitly killed # Example with kill() instead of terminate() proc2 = SupervisedProcess( "another-process", sys.executable, "-c", "import time; time.sleep(60)", ) await proc2.start() await proc2.kill() # Immediate termination with SIGKILL # Return code: -9 on POSIX (SIGKILL), 1 on Windows asyncio.run(main()) ``` -------------------------------- ### Signal Handling with atexitasync Source: https://context7.com/jupyterhub/simpervisor/llms.txt Demonstrates how Simpervisor's `atexitasync` module automatically propagates SIGINT and SIGTERM signals to supervised processes, ensuring a clean shutdown of child processes when the parent receives these signals. ```python import asyncio import sys from simpervisor import SupervisedProcess async def main(): # When the parent process receives SIGTERM or SIGINT, # simpervisor automatically propagates the signal to all # supervised processes before exiting proc1 = SupervisedProcess("worker-1", sys.executable, "worker.py") proc2 = SupervisedProcess("worker-2", sys.executable, "worker.py") await proc1.start() await proc2.start() # Both processes are now supervised and will receive # signals when the parent process is terminated # Keep running until interrupted try: while True: await asyncio.sleep(1) except asyncio.CancelledError: # Clean shutdown await proc1.terminate() await proc2.terminate() asyncio.run(main()) ``` -------------------------------- ### Auto-Restart Supervised Process on Failure Source: https://context7.com/jupyterhub/simpervisor/llms.txt Shows how to configure a supervised process to automatically restart, even after a successful exit, using `always_restart=True`. This is useful for services that must remain available. ```python import asyncio import sys from simpervisor import SupervisedProcess async def main(): # Process that always restarts, even on success proc = SupervisedProcess( "persistent-worker", sys.executable, "-c", "import time; time.sleep(0.5); exit(0)", # Exits successfully always_restart=True, # Restart even on success ) await proc.start() first_pid = proc.pid print(f"First PID: {first_pid}") # Wait for process to exit and restart await asyncio.sleep(2) # Process should have restarted with a new PID print(f"Still running: {proc.running}") # True print(f"New PID: {proc.pid}") # Different from first_pid # Clean up - must explicitly terminate await proc.terminate() asyncio.run(main()) ``` -------------------------------- ### Monitor Supervised Process Properties Source: https://context7.com/jupyterhub/simpervisor/llms.txt Shows how to access essential properties of a `SupervisedProcess` instance, including its PID, running status, name, and return code after it has exited. Useful for monitoring and debugging. ```python import asyncio import sys from simpervisor import SupervisedProcess async def main(): proc = SupervisedProcess( "monitored-process", sys.executable, "-c", "import time; time.sleep(0.5); exit(42)", always_restart=False, ) await proc.start() # Available properties print(f"Process ID: {proc.pid}") # OS process ID (e.g., 12345) print(f"Is running: {proc.running}") # True print(f"Name: {proc.name}") # "monitored-process" # Wait for natural exit await asyncio.sleep(1) print(f"Is running: {proc.running}") # False print(f"Return code: {proc.returncode}") # 42 asyncio.run(main()) ``` -------------------------------- ### Checkout and update main branch Source: https://github.com/jupyterhub/simpervisor/blob/main/RELEASE.md Ensures the local main branch is synchronized with the remote repository before proceeding with release steps. Use this to prepare for version updates. ```shell git checkout main git fetch origin main git reset --hard origin/main ``` -------------------------------- ### Update version and tag with tbump Source: https://github.com/jupyterhub/simpervisor/blob/main/RELEASE.md Executes the version update and pushes a git tag for the release using `tbump`. This is the actual command to perform the release after a successful dry run. The CI system will then build and publish the release. ```shell tbump ${VERSION} ``` -------------------------------- ### Reset version to development state Source: https://github.com/jupyterhub/simpervisor/blob/main/RELEASE.md Resets the version number to a development state (e.g., `1.0.1.dev`) after a release (e.g., `1.0.0`). This command uses `tbump` without creating a tag, preparing for the next development cycle. ```shell tbump --no-tag ${NEXT_VERSION}.dev ``` -------------------------------- ### Handle KilledProcessError Exception Source: https://context7.com/jupyterhub/simpervisor/llms.txt Illustrates the `KilledProcessError` exception, which is raised when attempting to restart, terminate, or kill a `SupervisedProcess` that has already been explicitly killed. Each process instance can only be killed once. ```python import asyncio import sys from simpervisor import SupervisedProcess, KilledProcessError async def main(): proc = SupervisedProcess( "one-shot-process", sys.executable, "-c", "import time; time.sleep(1)", ) await proc.start() await proc.kill() # All these will raise KilledProcessError for method in ['start', 'terminate', 'kill']: try: await getattr(proc, method)() except KilledProcessError as e: print(f"{method}() raised: {e}") # Output: Process one-shot-process has already been explicitly killed asyncio.run(main()) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.