Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6bccbd6
syft-process-manager
eelcovdw Oct 22, 2025
ed05e36
fixes + cleanup
eelcovdw Oct 22, 2025
cd307f2
add widget
eelcovdw Oct 22, 2025
89ab870
add tests
eelcovdw Oct 23, 2025
419441b
add CI
eelcovdw Oct 23, 2025
f35845f
add pytest extras
eelcovdw Oct 23, 2025
3079ac3
remove jupyter-dark-detect
eelcovdw Oct 23, 2025
2904153
add anywidget
eelcovdw Oct 23, 2025
fe567d8
unpin anywidget
eelcovdw Oct 23, 2025
ad95c09
match colab psutil
eelcovdw Oct 23, 2025
c4632c6
fix versions for colab
eelcovdw Oct 23, 2025
a442115
cleanup
eelcovdw Oct 23, 2025
bd9d681
cleanup
eelcovdw Oct 23, 2025
59cfa63
debug widget sync
eelcovdw Oct 23, 2025
8a07ff9
debug prints
eelcovdw Oct 23, 2025
7782746
move polling to JS
eelcovdw Oct 23, 2025
6a155f1
widget fixes
eelcovdw Oct 23, 2025
9547f55
widget fixes
eelcovdw Oct 23, 2025
6ebf01d
add update on timer
eelcovdw Oct 24, 2025
52403ff
Merge branch 'koen/syncing-v2' into eelco/process-manager
eelcovdw Oct 24, 2025
6c6258e
run sync process
eelcovdw Oct 24, 2025
902dc52
Merge pull request #40 from OpenMined/eelco/sync-process-manager
eelcovdw Oct 24, 2025
f00179c
remove resources, fix notebooks
eelcovdw Oct 27, 2025
570ea65
cleanup pyproject
eelcovdw Oct 27, 2025
197acd7
Merge pull request #41 from OpenMined/eelco/sync-process-manager
eelcovdw Oct 27, 2025
5c39083
merge
eelcovdw Oct 28, 2025
6f75cb2
add shutdown signal
eelcovdw Oct 31, 2025
16d256d
add shutdown signal
eelcovdw Oct 31, 2025
4177109
add signal to run_forever
eelcovdw Oct 31, 2025
eb20c07
revert changes
eelcovdw Oct 31, 2025
7fc307d
remove old notebook
eelcovdw Oct 31, 2025
7355051
cleanup deps
eelcovdw Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: pytest

on:
pull_request:
push:
branches: [main]

jobs:
test-packages:
runs-on: ubuntu-latest
strategy:
matrix:
package: ["syft-process-manager"]

steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Install ${{ matrix.package }}
run: uv sync --locked --all-extras --dev
working-directory: packages/${{ matrix.package }}

- name: Run tests for ${{ matrix.package }}
run: uv run pytest tests -n auto
working-directory: packages/${{ matrix.package }}
11 changes: 11 additions & 0 deletions packages/syft-process-manager/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info

# Virtual environments
.venv
experimental/
154 changes: 154 additions & 0 deletions packages/syft-process-manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# syft-process-manager

A Python library for managing long-running background processes with built-in logging, health checks, and Jupyter notebook integration.

## Features

- Start, stop, and monitor detached background processes
- Run Python functions as detached processes with cloudpickle
- Stream stdout/stderr logs
- Persistent state across Python sessions
- Interactive Jupyter widgets with live log streaming
- Optional TTL and health checks

## Quick Start

### Running Commands

```python
import syft_process_manager as syftpm

# Start a process
handle = syftpm.run(
name="my-server",
cmd=["python", "-m", "http.server", "8000"]
)

# Check status and view logs
print(handle.status) # "running"
print(handle.pid)
print(handle.stdout.tail(10))

# Terminate
handle.terminate()
```

### Running Python Functions

```python
import time
from syft_process_manager import run_function

def my_background_task(message):
i = 0
while True:
print(f"Iteration {i}: {message}")
i += 1
time.sleep(1)

# Run in background with auto-termination
handle = run_function(
my_background_task,
message="Hello from background!",
name="my-task",
ttl_seconds=120,
)

print(handle.uptime)
print(handle.stdout.tail())
```

### Managing Multiple Processes

```python
from syft_process_manager import ProcessManager

pm = ProcessManager()

# Start multiple processes
pm.create_and_run(name="worker-1", cmd=["python", "worker.py"])
pm.create_and_run(name="worker-2", cmd=["python", "worker.py"])

# List all processes
for handle in pm.list():
print(f"{handle.name}: {handle.status} (PID: {handle.pid})")

# Cleanup
pm.terminate_all()
```

## Core Components

### ProcessManager

Main entry point for creating and managing processes. Maintains a registry in `~/.syft-process-manager` by default.

### ProcessHandle

Represents a managed process with methods:

- `start()`, `terminate()`, `is_running()`, `refresh()`, `info()`

Key properties:

- `status`: "running", "stopped", or "unhealthy"
- `pid`, `uptime`: Process information
- `stdout`, `stderr`: LogStream objects
- `health`: Optional health check data

### LogStream

Access process logs with `tail(n)`, `head(n)`, or `read_lines()`.

## Advanced Features

```python
# Custom environment variables
handle = syftpm.run(
name="my-app",
cmd=["python", "app.py"],
env={"DEBUG": "true"}
)

# Replace existing process
handle = syftpm.run(
name="my-app",
cmd=["python", "app.py"],
overwrite=True
)

# TTL (auto-terminate)
handle = syftpm.run_function(
my_task,
ttl_seconds=3600,
name="temporary-task"
)
```

### Health Checks

Write health information from your process:

```python
import json, os
from pathlib import Path

process_dir = Path(os.environ["SYFTPM_PROCESS_DIR"])
(process_dir / "health.json").write_text(json.dumps({
"timestamp": "2025-01-15T12:00:00Z",
"status": "healthy",
"details": {"requests_served": 1234}
}))

# Read from manager
health = handle.health
```

## Jupyter Notebook Integration

ProcessHandle objects automatically render as interactive widgets with real-time status updates, live log streaming, and theme-aware styling:

```python
handle = syftpm.run(name="notebook-server", cmd=["python", "app.py"])
handle # Displays interactive widget
```
Loading
Loading