Metadata-Version: 2.4
Name: django-taskly
Version: 0.1.0
Summary: A reusable Django app for monitoring and administering Django 6.0 Tasks API jobs.
License-Expression: MIT
Project-URL: Homepage, https://github.com/acandincer/django-taskly
Project-URL: Repository, https://github.com/acandincer/django-taskly
Project-URL: Changelog, https://github.com/acandincer/django-taskly/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/acandincer/django-taskly/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Framework :: Django :: 6.0
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-django>=4.9; extra == "dev"
Requires-Dist: pytest-cov>=6.0; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Dynamic: license-file

# django-taskly

[![PyPI](https://img.shields.io/pypi/v/django-taskly)](https://pypi.org/project/django-taskly/)
[![Python](https://img.shields.io/pypi/pyversions/django-taskly)](https://pypi.org/project/django-taskly/)
[![Django](https://img.shields.io/badge/django-6.0%2B-green)](https://www.djangoproject.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A reusable Django app for monitoring and administering **Django 6.0 Tasks API** jobs.

django-taskly captures task results via signals, persists them as `TaskSnapshot`
records, and provides a real-time monitoring dashboard with statistics,
filtering, search, and per-task detail pages — all integrated into the Django
admin UI.

## Screenshots

| Dashboard | Task List |
|:---------:|:---------:|
| ![Dashboard](docs/images/dashboard.png) | ![Task List](docs/images/task_list.png) |

| Task Detail | Task Snapshot (Admin) |
|:-----------:|:---------------------:|
| ![Task Detail](docs/images/task_detail.png) | ![Task Snapshot](docs/images/tasksnapshot.png) |

## Features

- **Monitoring dashboard** — live stats cards (total, successful, failed, slow), slow-tasks table, and recent-tasks table
- **Manual & auto-refresh** — one-click refresh button plus a configurable auto-refresh timer (set your own interval, runs until you stop it)
- **Task list with filters** — paginated, filterable by status, searchable by task name, with HTMX-powered partial updates
- **Task detail view** — full snapshot inspection including timing, attempts, error class, and traceback
- **Django admin integration** — browse and inspect snapshots directly from the admin site (read-only)
- **Signal-based automatic capture** — listens to `task_finished` and records results with zero boilerplate
- **Cleanup management command** — prune excess snapshots with `taskly_cleanup`, with `--dry-run` preview
- **Configurable** — control retention limits, slow-task thresholds, and the dashboard title via a single `TASKLY` dict

## Quick Start

### 1. Install

```bash
pip install django-taskly
```

### 2. Add to `INSTALLED_APPS`

```python
INSTALLED_APPS = [
    # ...
    "django_taskly",
]
```

### 3. Include the URLs

```python
# urls.py
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
    path("taskly/", include("django_taskly.urls")),
]
```

### 4. Run migrations

```bash
python manage.py migrate
```

### 5. Configure the Django Tasks backend

django-taskly monitors tasks that run through the Django 6.0 Tasks API.
Configure at least one backend in your project settings:

```python
TASKS = {
    "default": {
        "BACKEND": "django.tasks.backends.immediate.ImmediateBackend",
    }
}
```

Visit `http://localhost:8000/taskly/` to open the monitoring dashboard.

## Configuration

All settings live under a single `TASKLY` dict. Every key is optional — the
values shown below are the defaults:

```python
TASKLY = {
    # Set to False to disable signal-based task capture entirely.
    "ENABLED": True,

    # Tasks that take longer than this (seconds) are flagged as "slow".
    "SLOW_TASK_SECONDS": 5,

    # Maximum number of TaskSnapshot rows to retain in the database.
    "MAX_SNAPSHOTS": 1000,

    # Title displayed in the dashboard header.
    "DASHBOARD_TITLE": "Django Taskly",
}
```

### Settings reference

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `ENABLED` | `bool` | `True` | Enable or disable automatic task capture via signals |
| `SLOW_TASK_SECONDS` | `int/float` | `5` | Duration threshold (seconds) above which a task is marked slow |
| `MAX_SNAPSHOTS` | `int` | `1000` | Maximum number of `TaskSnapshot` rows kept in the database |
| `DASHBOARD_TITLE` | `str` | `"Django Taskly"` | Title shown in the monitoring dashboard |

## Dashboard Pages

| URL | Name | Description |
|-----|------|-------------|
| `/taskly/` | `dashboard` | Stats cards, slow tasks, recent tasks |
| `/taskly/tasks/` | `task_list` | Paginated, filterable, searchable snapshot list |
| `/taskly/tasks/<task_id>/` | `task_detail` | Full detail view for a single snapshot |

All pages are staff-only (`@staff_member_required`) and extend `admin/base_site.html`
for seamless integration with the Django admin.

Navigation buttons are provided on each page to move between the dashboard and
the task list.

### HTMX partials

These endpoints are used internally for live updates and can also be consumed
by custom integrations:

| URL | Description |
|-----|-------------|
| `/taskly/partials/dashboard-stats/` | Stats cards only |
| `/taskly/partials/dashboard-content/` | Full dashboard body (stats + tables) |
| `/taskly/partials/task-list/` | Task table `<tbody>` rows |

## Management Commands

### `taskly_cleanup`

Removes the oldest `TaskSnapshot` rows that exceed the configured retention limit.

```bash
# Delete snapshots beyond the MAX_SNAPSHOTS setting (default: 1000).
python manage.py taskly_cleanup

# Override the retention limit for this run only.
python manage.py taskly_cleanup --max-snapshots 500

# Preview what would be deleted without touching the database.
python manage.py taskly_cleanup --dry-run
```

| Option | Description |
|--------|-------------|
| `--max-snapshots N` | Retain at most `N` snapshots (overrides the setting for this run) |
| `--dry-run` | Print the count of snapshots that would be deleted, without deleting |

## How It Works

1. **Signal capture** — When a Django 6.0 task finishes, Django emits a
   `task_finished` signal. django-taskly's `AppConfig.ready()` connects a
   handler that automatically snapshots the result.

2. **Collector** — `TaskCollector.snapshot_from_result()` reads the `TaskResult`
   fields (id, status, timing, errors) and persists them via `update_or_create`
   on the `TaskSnapshot` model.

3. **Dashboard** — Views query `TaskSnapshot` using the custom manager methods
   (`.failed()`, `.slow()`, `.recent()`) and render HTMX-enabled templates.

4. **Cleanup** — The `taskly_cleanup` command (or `TaskCollector.cleanup()`)
   deletes the oldest rows beyond the retention limit.

## Requirements

- **Python** 3.11+
- **Django** 6.0+

No additional runtime dependencies. HTMX is loaded from a CDN by the built-in
templates; no JavaScript build step is needed.

## Development

```bash
git clone https://github.com/acandincer/django-taskly.git
cd django-taskly
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=django_taskly --cov-report=term-missing

# Lint and format
ruff check django_taskly/
ruff format django_taskly/
```

## License

MIT. See [LICENSE](LICENSE) for details.
