Metadata-Version: 2.4
Name: phzyx-pulse
Version: 0.1.0a1
Summary: Phzyx Pulse — reliable-by-default background tasks for modern Python (Redis-first).
Project-URL: Homepage, https://phzyx.xyz
Project-URL: Documentation, https://phzyx.xyz
Project-URL: Repository, https://github.com/phzyxyz/pulse
Project-URL: Issues, https://github.com/phzyxyz/pulse/issues
Author: Athul Nandaswaroop
License-Expression: MIT
License-File: LICENSE
Keywords: async,background,phzyx,pulse,queue,redis,tasks
Requires-Python: >=3.11
Requires-Dist: click>=8.1
Requires-Dist: croniter>=2.0
Requires-Dist: pydantic>=2.6
Requires-Dist: redis>=5
Provides-Extra: dev
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: msgspec
Requires-Dist: msgspec>=0.18; extra == 'msgspec'
Provides-Extra: press
Requires-Dist: celery>=5.3; extra == 'press'
Requires-Dist: dramatiq[redis]>=1.17; extra == 'press'
Requires-Dist: taskiq-redis>=1.0; extra == 'press'
Requires-Dist: taskiq>=0.11; extra == 'press'
Provides-Extra: redis
Requires-Dist: redis>=5; extra == 'redis'
Description-Content-Type: text/markdown

# Pulse (`phzyx-pulse`)

**Reliable-by-default background tasks for modern Python.**

| | |
|--|--|
| **Status** | **0.1.0a1** — core MVP (memory + Redis, worker, late ACK, retries, DLQ, beat, dashboard) |
| **Package** | `phzyx-pulse` |
| **Import** | `phzyx.pulse` |
| **CLI** | `pulse` |
| **Python** | ≥ 3.11 |
| **Brokers** | Memory (default) · Redis (included; `redis` is a core dependency) |
| **Docs** | [phzyx.xyz/pulse](https://phzyx.xyz/pulse) |
| **Repo** | [github.com/phzyxyz/pulse](https://github.com/phzyxyz/pulse) |
| **License** | MIT |

## Install

```bash
uv add phzyx-pulse
```

```bash
export PULSE_BROKER_URL=redis://localhost:6379/0
export PULSE_IMPORTS=myapp.tasks
pulse worker
```

## Quick start (eager — no worker)

```python
from phzyx.pulse import Pulse, set_app, task

set_app(Pulse(eager=True))

@task
def add(x: int, y: int) -> int:
    return x + y

print(add.delay(1, 2).get())  # 3
```

## Worker mode

```python
# tasks.py
from phzyx.pulse import task

@task
def add(x: int, y: int) -> int:
    return x + y
```

```bash
export PULSE_IMPORTS=tasks
export PULSE_BROKER_URL=redis://localhost:6379/0
# terminal A
pulse worker -v
# terminal B — enqueue from Python with the same tasks imported
```

## CLI

```bash
pulse --version
pulse info
pulse doctor
pulse worker --queue default
pulse beat
pulse dashboard --port 8787
pulse retry <job-id>
```

## Design locks

- Import **`phzyx.pulse`** only (not `phzyx_pulse`)
- **Late ACK** by default
- **No pickle** default serializer (JSON)
- **ETA** stored on broker (not worker RAM)
- **Built-in DLQ** + lease tokens + visibility reclaim
- **Not** part of Forge — separate product under `phzyxyz/pulse`

## Docs

- Site: https://phzyx.xyz/pulse
- Local guides under `docs/` (getting started, Celery migration, edge cases, press)

## Realistic stack (OrbStack)

```bash
./examples/realistic_stack/scripts/up.sh
# API  http://127.0.0.1:18443/health
# Dash http://127.0.0.1:18787/
# Redis localhost:16379
```

## Stack press (benchmarks)

```bash
uv pip install 'phzyx-pulse[press]'
PYTHONPATH=src:. uv run python -m benchmarks.press.run_all_mp \
  --n 1000 --work-iters 5000 --workers 2 4
# → benchmarks/press/RESULTS/SUMMARY_MP.md
```

## Not under forge

Product code lives **only** here. Do not add Pulse packages to the Forge tree.
