django-database-task 0.2.3__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {django_database_task-0.2.3/django_database_task.egg-info → django_database_task-0.2.4}/PKG-INFO +23 -4
  2. {django_database_task-0.2.3 → django_database_task-0.2.4}/README.md +22 -3
  3. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/__init__.py +1 -1
  4. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/views.py +68 -17
  5. {django_database_task-0.2.3 → django_database_task-0.2.4/django_database_task.egg-info}/PKG-INFO +23 -4
  6. {django_database_task-0.2.3 → django_database_task-0.2.4}/pyproject.toml +1 -1
  7. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_views.py +59 -3
  8. {django_database_task-0.2.3 → django_database_task-0.2.4}/LICENSE +0 -0
  9. {django_database_task-0.2.3 → django_database_task-0.2.4}/MANIFEST.in +0 -0
  10. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/admin.py +0 -0
  11. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/apps.py +0 -0
  12. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/backends.py +0 -0
  13. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/cloudtasks/__init__.py +0 -0
  14. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/cloudtasks/auth.py +0 -0
  15. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/cloudtasks/backend.py +0 -0
  16. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/cloudtasks/detection.py +0 -0
  17. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/executor.py +0 -0
  18. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/locale/ja/LC_MESSAGES/django.mo +0 -0
  19. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/locale/ja/LC_MESSAGES/django.po +0 -0
  20. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/management/__init__.py +0 -0
  21. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/management/commands/__init__.py +0 -0
  22. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/management/commands/purge_completed_database_tasks.py +0 -0
  23. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/management/commands/run_database_tasks.py +0 -0
  24. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/migrations/0001_initial.py +0 -0
  25. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/migrations/__init__.py +0 -0
  26. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/models.py +0 -0
  27. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task/urls.py +0 -0
  28. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task.egg-info/SOURCES.txt +0 -0
  29. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task.egg-info/dependency_links.txt +0 -0
  30. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task.egg-info/requires.txt +0 -0
  31. {django_database_task-0.2.3 → django_database_task-0.2.4}/django_database_task.egg-info/top_level.txt +0 -0
  32. {django_database_task-0.2.3 → django_database_task-0.2.4}/setup.cfg +0 -0
  33. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_admin.py +0 -0
  34. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_backend.py +0 -0
  35. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_commands.py +0 -0
  36. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_executor.py +0 -0
  37. {django_database_task-0.2.3 → django_database_task-0.2.4}/tests/test_models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-database-task
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: A database-backed task queue backend for Django 6.0's built-in task framework
5
5
  Author-email: Shinya Okano <tokibito@gmail.com>
6
6
  Maintainer-email: Shinya Okano <tokibito@gmail.com>
@@ -358,7 +358,7 @@ urlpatterns = [
358
358
  | `/tasks/run-one/` | POST | Process a single pending task |
359
359
  | `/tasks/status/` | GET | Get pending task count |
360
360
  | `/tasks/execute/<uuid>/` | POST | Execute a specific task by ID |
361
- | `/tasks/purge/` | POST | Delete completed tasks |
361
+ | `/tasks/purge/` | GET, POST | Delete completed tasks |
362
362
 
363
363
  ### Request Parameters
364
364
 
@@ -434,10 +434,14 @@ Response (task not found):
434
434
  {"error": "Task not found"} // HTTP 404
435
435
  ```
436
436
 
437
- #### POST `/tasks/purge/`
437
+ #### GET/POST `/tasks/purge/`
438
438
 
439
439
  Delete completed tasks from the database. Useful for cron-based cleanup.
440
440
 
441
+ **Note:** GET method is supported for GAE cron compatibility (GAE cron only supports GET requests).
442
+
443
+ **POST parameters (JSON body):**
444
+
441
445
  | Parameter | Type | Default | Description |
442
446
  |-----------|------|---------|-------------|
443
447
  | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
@@ -445,6 +449,15 @@ Delete completed tasks from the database. Useful for cron-based cleanup.
445
449
  | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
446
450
  | `dry_run` | bool | false | If true, return count without deleting |
447
451
 
452
+ **GET query parameters:**
453
+
454
+ | Parameter | Type | Default | Description |
455
+ |-----------|------|---------|-------------|
456
+ | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
457
+ | `status` | string | "SUCCESSFUL,FAILED" | Target statuses, comma-separated |
458
+ | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
459
+ | `dry_run` | string | "false" | If "true", return count without deleting |
460
+
448
461
  Response:
449
462
  ```json
450
463
  {"deleted": 150, "dry_run": false}
@@ -471,15 +484,21 @@ curl -X POST http://localhost:8000/tasks/run/ \
471
484
  # Get pending task count
472
485
  curl http://localhost:8000/tasks/status/
473
486
 
474
- # Delete tasks completed more than 7 days ago
487
+ # Delete tasks completed more than 7 days ago (POST)
475
488
  curl -X POST http://localhost:8000/tasks/purge/ \
476
489
  -H "Content-Type: application/json" \
477
490
  -d '{"days": 7}'
478
491
 
492
+ # Delete tasks completed more than 7 days ago (GET - for GAE cron)
493
+ curl "http://localhost:8000/tasks/purge/?days=7"
494
+
479
495
  # Dry run to check how many tasks would be deleted
480
496
  curl -X POST http://localhost:8000/tasks/purge/ \
481
497
  -H "Content-Type: application/json" \
482
498
  -d '{"days": 30, "dry_run": true}'
499
+
500
+ # Dry run via GET
501
+ curl "http://localhost:8000/tasks/purge/?days=30&dry_run=true"
483
502
  ```
484
503
 
485
504
  ### Use Cases
@@ -322,7 +322,7 @@ urlpatterns = [
322
322
  | `/tasks/run-one/` | POST | Process a single pending task |
323
323
  | `/tasks/status/` | GET | Get pending task count |
324
324
  | `/tasks/execute/<uuid>/` | POST | Execute a specific task by ID |
325
- | `/tasks/purge/` | POST | Delete completed tasks |
325
+ | `/tasks/purge/` | GET, POST | Delete completed tasks |
326
326
 
327
327
  ### Request Parameters
328
328
 
@@ -398,10 +398,14 @@ Response (task not found):
398
398
  {"error": "Task not found"} // HTTP 404
399
399
  ```
400
400
 
401
- #### POST `/tasks/purge/`
401
+ #### GET/POST `/tasks/purge/`
402
402
 
403
403
  Delete completed tasks from the database. Useful for cron-based cleanup.
404
404
 
405
+ **Note:** GET method is supported for GAE cron compatibility (GAE cron only supports GET requests).
406
+
407
+ **POST parameters (JSON body):**
408
+
405
409
  | Parameter | Type | Default | Description |
406
410
  |-----------|------|---------|-------------|
407
411
  | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
@@ -409,6 +413,15 @@ Delete completed tasks from the database. Useful for cron-based cleanup.
409
413
  | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
410
414
  | `dry_run` | bool | false | If true, return count without deleting |
411
415
 
416
+ **GET query parameters:**
417
+
418
+ | Parameter | Type | Default | Description |
419
+ |-----------|------|---------|-------------|
420
+ | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
421
+ | `status` | string | "SUCCESSFUL,FAILED" | Target statuses, comma-separated |
422
+ | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
423
+ | `dry_run` | string | "false" | If "true", return count without deleting |
424
+
412
425
  Response:
413
426
  ```json
414
427
  {"deleted": 150, "dry_run": false}
@@ -435,15 +448,21 @@ curl -X POST http://localhost:8000/tasks/run/ \
435
448
  # Get pending task count
436
449
  curl http://localhost:8000/tasks/status/
437
450
 
438
- # Delete tasks completed more than 7 days ago
451
+ # Delete tasks completed more than 7 days ago (POST)
439
452
  curl -X POST http://localhost:8000/tasks/purge/ \
440
453
  -H "Content-Type: application/json" \
441
454
  -d '{"days": 7}'
442
455
 
456
+ # Delete tasks completed more than 7 days ago (GET - for GAE cron)
457
+ curl "http://localhost:8000/tasks/purge/?days=7"
458
+
443
459
  # Dry run to check how many tasks would be deleted
444
460
  curl -X POST http://localhost:8000/tasks/purge/ \
445
461
  -H "Content-Type: application/json" \
446
462
  -d '{"days": 30, "dry_run": true}'
463
+
464
+ # Dry run via GET
465
+ curl "http://localhost:8000/tasks/purge/?days=30&dry_run=true"
447
466
  ```
448
467
 
449
468
  ### Use Cases
@@ -2,7 +2,7 @@
2
2
  django-database-task: A database-backed task queue backend for Django 6.0's task framework.
3
3
  """
4
4
 
5
- __version__ = "0.2.3"
5
+ __version__ = "0.2.4"
6
6
 
7
7
 
8
8
  def __getattr__(name):
@@ -366,11 +366,17 @@ class ExecuteTaskView(View):
366
366
  @method_decorator(csrf_exempt, name="dispatch")
367
367
  class PurgeCompletedTasksView(View):
368
368
  """
369
- Delete completed tasks via HTTP POST.
369
+ Delete completed tasks via HTTP GET or POST.
370
370
 
371
371
  This endpoint is useful for cron-based cleanup of completed tasks
372
372
  when management commands cannot be executed directly.
373
373
 
374
+ GET query parameters:
375
+ days: Delete tasks completed more than N days ago (0=all, default: 0)
376
+ status: Target statuses, comma-separated (default: "SUCCESSFUL,FAILED")
377
+ batch_size: Number of tasks to delete at once (default: 1000, max: 10000)
378
+ dry_run: If "true", return count without deleting (default: "false")
379
+
374
380
  POST parameters (JSON body):
375
381
  days: Delete tasks completed more than N days ago (0=all, default: 0)
376
382
  status: Target statuses, comma-separated (default: "SUCCESSFUL,FAILED")
@@ -395,14 +401,57 @@ class PurgeCompletedTasksView(View):
395
401
  }
396
402
 
397
403
  Security:
398
- - Only accepts POST requests
404
+ - Accepts GET and POST requests
399
405
  - CSRF exempt (intended for API/cron use)
400
406
  - Consider adding authentication in your URL configuration
401
- """
402
407
 
403
- http_method_names = ["post"]
408
+ GAE Cron:
409
+ GAE cron only supports GET requests. Use query parameters:
410
+ GET /tasks/purge/?days=7&status=SUCCESSFUL,FAILED
411
+ """
404
412
 
405
- def post(self, request):
413
+ http_method_names = ["get", "post"]
414
+
415
+ def _get_params(self, request):
416
+ """Extract parameters from GET query string or POST JSON body."""
417
+ if request.method == "GET":
418
+ days_str = request.GET.get("days", "0")
419
+ try:
420
+ days = int(days_str)
421
+ except ValueError:
422
+ return None, {"error": "days must be an integer"}
423
+
424
+ batch_size_str = request.GET.get("batch_size", "1000")
425
+ try:
426
+ batch_size = int(batch_size_str)
427
+ except ValueError:
428
+ return None, {"error": "batch_size must be an integer"}
429
+
430
+ return {
431
+ "days": days,
432
+ "status": request.GET.get("status", "SUCCESSFUL,FAILED"),
433
+ "batch_size": batch_size,
434
+ "dry_run": request.GET.get("dry_run", "").lower() == "true",
435
+ }, None
436
+ else:
437
+ # POST - parse JSON body
438
+ try:
439
+ if request.body:
440
+ data = json.loads(request.body)
441
+ else:
442
+ data = {}
443
+ except json.JSONDecodeError:
444
+ return None, {"error": "Invalid JSON"}
445
+
446
+ return {
447
+ "days": data.get("days", 0),
448
+ "status": data.get("status", "SUCCESSFUL,FAILED"),
449
+ "batch_size": data.get("batch_size", 1000),
450
+ "dry_run": data.get("dry_run", False),
451
+ }, None
452
+
453
+ def _purge(self, request):
454
+ """Common purge logic for GET and POST."""
406
455
  backend_name = request.GET.get("backend_name", "default")
407
456
 
408
457
  # Get backend and check for auth handler
@@ -414,19 +463,15 @@ class PurgeCompletedTasksView(View):
414
463
  if error_response:
415
464
  return error_response
416
465
 
417
- # Parse JSON body if present
418
- try:
419
- if request.body:
420
- data = json.loads(request.body)
421
- else:
422
- data = {}
423
- except json.JSONDecodeError:
424
- return JsonResponse({"error": "Invalid JSON"}, status=400)
466
+ # Get parameters
467
+ params, error = self._get_params(request)
468
+ if error:
469
+ return JsonResponse(error, status=400)
425
470
 
426
- days = data.get("days", 0)
427
- status_str = data.get("status", "SUCCESSFUL,FAILED")
428
- batch_size = data.get("batch_size", 1000)
429
- dry_run = data.get("dry_run", False)
471
+ days = params["days"]
472
+ status_str = params["status"]
473
+ batch_size = params["batch_size"]
474
+ dry_run = params["dry_run"]
430
475
 
431
476
  # Validate parameters
432
477
  if not isinstance(days, int) or days < 0:
@@ -475,3 +520,9 @@ class PurgeCompletedTasksView(View):
475
520
  deleted_total += deleted_count
476
521
 
477
522
  return JsonResponse({"deleted": deleted_total, "dry_run": False})
523
+
524
+ def get(self, request):
525
+ return self._purge(request)
526
+
527
+ def post(self, request):
528
+ return self._purge(request)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-database-task
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: A database-backed task queue backend for Django 6.0's built-in task framework
5
5
  Author-email: Shinya Okano <tokibito@gmail.com>
6
6
  Maintainer-email: Shinya Okano <tokibito@gmail.com>
@@ -358,7 +358,7 @@ urlpatterns = [
358
358
  | `/tasks/run-one/` | POST | Process a single pending task |
359
359
  | `/tasks/status/` | GET | Get pending task count |
360
360
  | `/tasks/execute/<uuid>/` | POST | Execute a specific task by ID |
361
- | `/tasks/purge/` | POST | Delete completed tasks |
361
+ | `/tasks/purge/` | GET, POST | Delete completed tasks |
362
362
 
363
363
  ### Request Parameters
364
364
 
@@ -434,10 +434,14 @@ Response (task not found):
434
434
  {"error": "Task not found"} // HTTP 404
435
435
  ```
436
436
 
437
- #### POST `/tasks/purge/`
437
+ #### GET/POST `/tasks/purge/`
438
438
 
439
439
  Delete completed tasks from the database. Useful for cron-based cleanup.
440
440
 
441
+ **Note:** GET method is supported for GAE cron compatibility (GAE cron only supports GET requests).
442
+
443
+ **POST parameters (JSON body):**
444
+
441
445
  | Parameter | Type | Default | Description |
442
446
  |-----------|------|---------|-------------|
443
447
  | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
@@ -445,6 +449,15 @@ Delete completed tasks from the database. Useful for cron-based cleanup.
445
449
  | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
446
450
  | `dry_run` | bool | false | If true, return count without deleting |
447
451
 
452
+ **GET query parameters:**
453
+
454
+ | Parameter | Type | Default | Description |
455
+ |-----------|------|---------|-------------|
456
+ | `days` | int | 0 | Delete tasks completed more than N days ago (0=all) |
457
+ | `status` | string | "SUCCESSFUL,FAILED" | Target statuses, comma-separated |
458
+ | `batch_size` | int | 1000 | Number of tasks to delete at once (max: 10000) |
459
+ | `dry_run` | string | "false" | If "true", return count without deleting |
460
+
448
461
  Response:
449
462
  ```json
450
463
  {"deleted": 150, "dry_run": false}
@@ -471,15 +484,21 @@ curl -X POST http://localhost:8000/tasks/run/ \
471
484
  # Get pending task count
472
485
  curl http://localhost:8000/tasks/status/
473
486
 
474
- # Delete tasks completed more than 7 days ago
487
+ # Delete tasks completed more than 7 days ago (POST)
475
488
  curl -X POST http://localhost:8000/tasks/purge/ \
476
489
  -H "Content-Type: application/json" \
477
490
  -d '{"days": 7}'
478
491
 
492
+ # Delete tasks completed more than 7 days ago (GET - for GAE cron)
493
+ curl "http://localhost:8000/tasks/purge/?days=7"
494
+
479
495
  # Dry run to check how many tasks would be deleted
480
496
  curl -X POST http://localhost:8000/tasks/purge/ \
481
497
  -H "Content-Type: application/json" \
482
498
  -d '{"days": 30, "dry_run": true}'
499
+
500
+ # Dry run via GET
501
+ curl "http://localhost:8000/tasks/purge/?days=30&dry_run=true"
483
502
  ```
484
503
 
485
504
  ### Use Cases
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "django-database-task"
7
- version = "0.2.3"
7
+ version = "0.2.4"
8
8
  description = "A database-backed task queue backend for Django 6.0's built-in task framework"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -738,10 +738,66 @@ class TestPurgeCompletedTasksView:
738
738
  data = response.json()
739
739
  assert data["deleted"] == 0
740
740
 
741
- def test_purge_rejects_get(self, client):
742
- """Test that GET method is not allowed."""
741
+ def test_purge_via_get(self, client):
742
+ """Test that GET method works for GAE cron compatibility."""
743
+ # Create a completed task
744
+ DatabaseTask.objects.create(
745
+ task_path="tests.test_executor.sample_task",
746
+ queue_name="default",
747
+ priority=0,
748
+ args_json=[1, 2],
749
+ kwargs_json={},
750
+ status=TaskResultStatus.SUCCESSFUL,
751
+ enqueued_at=timezone.now(),
752
+ finished_at=timezone.now(),
753
+ backend_name="default",
754
+ )
743
755
  response = client.get(reverse("django_database_task:purge_completed_tasks"))
744
- assert response.status_code == 405
756
+ assert response.status_code == 200
757
+ data = response.json()
758
+ assert data["deleted"] == 1
759
+ assert data["dry_run"] is False
760
+
761
+ def test_purge_via_get_with_params(self, client):
762
+ """Test GET method with query parameters."""
763
+ # Create a completed task
764
+ DatabaseTask.objects.create(
765
+ task_path="tests.test_executor.sample_task",
766
+ queue_name="default",
767
+ priority=0,
768
+ args_json=[1, 2],
769
+ kwargs_json={},
770
+ status=TaskResultStatus.SUCCESSFUL,
771
+ enqueued_at=timezone.now(),
772
+ finished_at=timezone.now(),
773
+ backend_name="default",
774
+ )
775
+ response = client.get(
776
+ reverse("django_database_task:purge_completed_tasks"),
777
+ {"days": "0", "status": "SUCCESSFUL", "dry_run": "true"},
778
+ )
779
+ assert response.status_code == 200
780
+ data = response.json()
781
+ assert data["count"] == 1
782
+ assert data["dry_run"] is True
783
+
784
+ def test_purge_via_get_invalid_days(self, client):
785
+ """Test GET method with invalid days parameter."""
786
+ response = client.get(
787
+ reverse("django_database_task:purge_completed_tasks"),
788
+ {"days": "abc"},
789
+ )
790
+ assert response.status_code == 400
791
+ assert "days must be an integer" in response.json()["error"]
792
+
793
+ def test_purge_via_get_invalid_batch_size(self, client):
794
+ """Test GET method with invalid batch_size parameter."""
795
+ response = client.get(
796
+ reverse("django_database_task:purge_completed_tasks"),
797
+ {"batch_size": "abc"},
798
+ )
799
+ assert response.status_code == 400
800
+ assert "batch_size must be an integer" in response.json()["error"]
745
801
 
746
802
  def test_purge_rejects_invalid_json(self, client):
747
803
  """Test that invalid JSON returns 400."""