Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [1.7.0] - 2026-09-28

**Upgrading to 1.7.0:** No database migration is required. Upgrade workers to recover their own unconfirmed claims. Recovery runs only in `Worker.run()`, the loop used by `ox_worker`, on PostgreSQL with psycopg 3, MySQL and SQLite. `Worker.run_once()`, `testing.run_tasks()` and PostgreSQL with psycopg2 retain 1.6.0 behavior on claim errors. A mixed fleet with 1.5.0 and 1.6.0 workers was tested; recovery applies only to upgraded workers' own claims.

If a claim commits but its reply is lost, the loop looks for eligible rows on later poll passes, or once at stop, and returns them to `READY` with the attempt refunded within `LOCK_TIMEOUT` and before lease expiry. Recovery is not guaranteed: worker death, prolonged outages, late commit visibility or continuous shared-Worker claims can leave rows for the reaper, consuming the attempt and becoming `LOST` on the final attempt. Stop-time recovery has backend-specific waiting limits, not a shutdown deadline. With Django's PostgreSQL pool, budget up to `max_size + 3` server connections per worker process during that look, rather than `max_size + 2`.

A Worker inherited across a fork takes a new child id. Fork before the Worker claims anything; handing an already-claimed row to a child is unsupported. This does not make inherited connections or arbitrary native forks safe. An inherited shared heartbeat path proves only that one writer is alive. The recovery log events join the stable log contract.

### Fixed

Expand Down Expand Up @@ -1795,6 +1801,7 @@ Initial release.
the public API surface, the pre-1.0 SemVer rule, the deprecation
window, and the supported Python and Django matrix.

[1.7.0]: https://github.com/oxpull/django-ox/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/oxpull/django-ox/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/oxpull/django-ox/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/oxpull/django-ox/compare/v1.3.1...v1.4.0
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ input by string formatting.

| Version | Supported |
| ------- | --------- |
| 1.6.x | yes |
| 1.7.x | yes |
| older | no |

## Reporting a vulnerability
Expand Down
15 changes: 11 additions & 4 deletions docs/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6531,7 +6531,7 @@ process that shares a database before anything writes the new status. The
release notes name the value, say how it reads through `django.tasks`, and
give the upgrade and rollback steps.

Pin accordingly: `django-ox~=1.6.0` accepts patch releases only;
Pin accordingly: `django-ox~=1.7.0` accepts patch releases only;
`django-ox~=1.3` accepts the current major line.

## Deprecation policy
Expand Down Expand Up @@ -6697,8 +6697,8 @@ the `django-tasks` backport; Pro does not.
schedule rows on a queue no backend accepts reports `oxpull.E008`
instead. Workflows need Oxpull Pro 1.3.0 or later.

Each Pro release pins django-ox exactly: `oxpull==1.6.0` pins
`django-ox==1.6.0`.
Each Pro release pins django-ox exactly: `oxpull==1.7.0` pins
`django-ox==1.7.0`.

Pro runs on the databases the free tier tests in CI: SQLite,
PostgreSQL and MySQL 8. MariaDB 10.6+ takes the same claim path but is not
Expand Down Expand Up @@ -7111,7 +7111,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [1.7.0] - 2026-09-28

**Upgrading to 1.7.0:** No database migration is required. Upgrade workers to recover their own unconfirmed claims. Recovery runs only in `Worker.run()`, the loop used by `ox_worker`, on PostgreSQL with psycopg 3, MySQL and SQLite. `Worker.run_once()`, `testing.run_tasks()` and PostgreSQL with psycopg2 retain 1.6.0 behavior on claim errors. A mixed fleet with 1.5.0 and 1.6.0 workers was tested; recovery applies only to upgraded workers' own claims.

If a claim commits but its reply is lost, the loop looks for eligible rows on later poll passes, or once at stop, and returns them to `READY` with the attempt refunded within `LOCK_TIMEOUT` and before lease expiry. Recovery is not guaranteed: worker death, prolonged outages, late commit visibility or continuous shared-Worker claims can leave rows for the reaper, consuming the attempt and becoming `LOST` on the final attempt. Stop-time recovery has backend-specific waiting limits, not a shutdown deadline. With Django's PostgreSQL pool, budget up to `max_size + 3` server connections per worker process during that look, rather than `max_size + 2`.

A Worker inherited across a fork takes a new child id. Fork before the Worker claims anything; handing an already-claimed row to a child is unsupported. This does not make inherited connections or arbitrary native forks safe. An inherited shared heartbeat path proves only that one writer is alive. The recovery log events join the stable log contract.

### Fixed

Expand Down Expand Up @@ -8901,6 +8907,7 @@ Initial release.
the public API surface, the pre-1.0 SemVer rule, the deprecation
window, and the supported Python and Django matrix.

[1.7.0]: https://github.com/oxpull/django-ox/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/oxpull/django-ox/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/oxpull/django-ox/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/oxpull/django-ox/compare/v1.3.1...v1.4.0
Expand Down
4 changes: 2 additions & 2 deletions docs/pro.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ the `django-tasks` backport; Pro does not.
schedule rows on a queue no backend accepts reports `oxpull.E008`
instead. Workflows need Oxpull Pro 1.3.0 or later.

Each Pro release pins django-ox exactly: `oxpull==1.6.0` pins
`django-ox==1.6.0`.
Each Pro release pins django-ox exactly: `oxpull==1.7.0` pins
`django-ox==1.7.0`.

Pro runs on the databases the free tier tests in CI: SQLite,
PostgreSQL and MySQL 8. MariaDB 10.6+ takes the same claim path but is not
Expand Down
2 changes: 1 addition & 1 deletion docs/stability.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ process that shares a database before anything writes the new status. The
release notes name the value, say how it reads through `django.tasks`, and
give the upgrade and rollback steps.

Pin accordingly: `django-ox~=1.6.0` accepts patch releases only;
Pin accordingly: `django-ox~=1.7.0` accepts patch releases only;
`django-ox~=1.3` accepts the current major line.

## Deprecation policy
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "django-ox"
version = "1.6.0"
version = "1.7.0"
description = "Django tasks in your database, with retries and automatic recovery when a worker dies."
readme = "README.md"
license = "BSD-3-Clause"
Expand Down
2 changes: 1 addition & 1 deletion src/django_ox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .tasks import BackoffCallback, PolicyTask

__all__ = ["BackoffCallback", "PolicyTask", "__version__", "deadline", "remaining"]
__version__ = "1.6.0"
__version__ = "1.7.0"


def __getattr__(name: str) -> Any:
Expand Down
Loading