django-lambda-tasks 0.6.2__tar.gz → 0.6.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 (103) hide show
  1. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/PKG-INFO +1 -1
  2. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/local_executor.py +20 -1
  3. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/pyproject.toml +1 -1
  4. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_local_executor.py +19 -0
  5. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.github/workflows/ci.yml +0 -0
  6. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.github/workflows/release.yml +0 -0
  7. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.gitignore +0 -0
  8. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/async-local-execution/.config.kiro +0 -0
  9. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/async-local-execution/design.md +0 -0
  10. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/async-local-execution/requirements.md +0 -0
  11. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/async-local-execution/tasks.md +0 -0
  12. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/deferred-task-enqueue/.config.kiro +0 -0
  13. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/deferred-task-enqueue/design.md +0 -0
  14. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/deferred-task-enqueue/requirements.md +0 -0
  15. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/deferred-task-enqueue/tasks.md +0 -0
  16. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/eager-mode-example-app/.config.kiro +0 -0
  17. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/eager-mode-example-app/design.md +0 -0
  18. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/eager-mode-example-app/requirements.md +0 -0
  19. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/eager-mode-example-app/tasks.md +0 -0
  20. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ignore-errors-decorator-option/.config.kiro +0 -0
  21. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ignore-errors-decorator-option/design.md +0 -0
  22. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ignore-errors-decorator-option/requirements.md +0 -0
  23. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ignore-errors-decorator-option/tasks.md +0 -0
  24. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/import-string-task-resolution/.config.kiro +0 -0
  25. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/import-string-task-resolution/design.md +0 -0
  26. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/import-string-task-resolution/requirements.md +0 -0
  27. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/import-string-task-resolution/tasks.md +0 -0
  28. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/retry-delay/.config.kiro +0 -0
  29. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/retry-delay/design.md +0 -0
  30. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/retry-delay/requirements.md +0 -0
  31. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/retry-delay/tasks.md +0 -0
  32. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks/.config.kiro +0 -0
  33. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks/design.md +0 -0
  34. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks/requirements.md +0 -0
  35. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks/tasks.md +0 -0
  36. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks-bugfix/.config.kiro +0 -0
  37. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks-bugfix/bugfix.md +0 -0
  38. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks-bugfix/design.md +0 -0
  39. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/rse-background-tasks-bugfix/tasks.md +0 -0
  40. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/singleton-task/.config.kiro +0 -0
  41. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/singleton-task/design.md +0 -0
  42. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/singleton-task/requirements.md +0 -0
  43. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/singleton-task/tasks.md +0 -0
  44. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ssm-environment-loader/.config.kiro +0 -0
  45. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ssm-environment-loader/design.md +0 -0
  46. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ssm-environment-loader/requirements.md +0 -0
  47. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/ssm-environment-loader/tasks.md +0 -0
  48. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/task-retry/.config.kiro +0 -0
  49. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/task-retry/design.md +0 -0
  50. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/task-retry/requirements.md +0 -0
  51. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/specs/task-retry/tasks.md +0 -0
  52. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/steering/product.md +0 -0
  53. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/steering/structure.md +0 -0
  54. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.kiro/steering/tech.md +0 -0
  55. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.pre-commit-config.yaml +0 -0
  56. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/.vscode/settings.json +0 -0
  57. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/README.md +0 -0
  58. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/README.md +0 -0
  59. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_app/__init__.py +0 -0
  60. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_app/apps.py +0 -0
  61. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_app/tasks.py +0 -0
  62. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_app/urls.py +0 -0
  63. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_app/views.py +0 -0
  64. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_project/__init__.py +0 -0
  65. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_project/settings.py +0 -0
  66. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_project/urls.py +0 -0
  67. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/example_project/wsgi.py +0 -0
  68. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/example/manage.py +0 -0
  69. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/__init__.py +0 -0
  70. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/admin.py +0 -0
  71. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/apps.py +0 -0
  72. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/decorators.py +0 -0
  73. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/environment_loader.py +0 -0
  74. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/handler.py +0 -0
  75. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/logging.py +0 -0
  76. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/migrations/0001_initial.py +0 -0
  77. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/migrations/0002_alter_taskrecord_status.py +0 -0
  78. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/migrations/__init__.py +0 -0
  79. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/models.py +0 -0
  80. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/secret_loader.py +0 -0
  81. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/settings.py +0 -0
  82. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/tasks.py +0 -0
  83. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/lambda_tasks/timeouts.py +0 -0
  84. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/conftest.py +0 -0
  85. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/settings.py +0 -0
  86. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_admin.py +0 -0
  87. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_batch.py +0 -0
  88. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_batch_worker.py +0 -0
  89. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_decorator.py +0 -0
  90. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_decorators.py +0 -0
  91. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_deferred_enqueue.py +0 -0
  92. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_environment_loader.py +0 -0
  93. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_handler.py +0 -0
  94. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_kwargs_only.py +0 -0
  95. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_logging.py +0 -0
  96. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_memory_limit.py +0 -0
  97. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_models.py +0 -0
  98. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_secret_loader.py +0 -0
  99. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_serializer.py +0 -0
  100. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_settings.py +0 -0
  101. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_tasks.py +0 -0
  102. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_timeout_validation.py +0 -0
  103. {django_lambda_tasks-0.6.2 → django_lambda_tasks-0.6.4}/tests/test_timeouts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-lambda-tasks
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Run async tasks in a lambda function
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: awslambdaric
@@ -2,6 +2,7 @@
2
2
 
3
3
  import atexit
4
4
  import logging
5
+ import multiprocessing
5
6
  import signal
6
7
  import threading
7
8
  import uuid
@@ -23,14 +24,22 @@ def _pool_initializer() -> None:
23
24
  atexit as a fallback). This prevents workers from being killed
24
25
  mid-operation and leaking semaphores.
25
26
 
27
+ Closes all database connections before setting up Django. With the
28
+ forkserver context, workers don't inherit the parent's connections,
29
+ but AppConfig.ready() hooks may open connections during django.setup()
30
+ that should be closed before task execution begins.
31
+
26
32
  Then sets up Django for task execution.
27
33
  """
28
34
  signal.signal(signal.SIGINT, signal.SIG_IGN)
29
35
 
30
36
  import django
37
+ from django.db import connections
31
38
 
32
39
  django.setup()
33
40
 
41
+ connections.close_all()
42
+
34
43
 
35
44
  def _shutdown_pool() -> None:
36
45
  """Shut down the pool, releasing its POSIX semaphores promptly.
@@ -111,12 +120,22 @@ def _install_shutdown_handlers() -> None:
111
120
 
112
121
 
113
122
  def get_pool() -> ProcessPoolExecutor:
114
- """Return the shared ProcessPoolExecutor, creating it on first call."""
123
+ """Return the shared ProcessPoolExecutor, creating it on first call.
124
+
125
+ Uses the "forkserver" multiprocessing context so that worker processes
126
+ are forked from a clean server process rather than from the Django parent.
127
+ This prevents workers from inheriting the parent's open database
128
+ connections (and other file descriptors), which would otherwise cause
129
+ "server closed the connection unexpectedly" errors in containerized
130
+ environments where close() in the child tears down the shared socket.
131
+ """
115
132
  global _pool
116
133
  if _pool is None:
117
134
  conf = LambdaTasksSettings()
135
+ mp_context = multiprocessing.get_context("forkserver")
118
136
  _pool = ProcessPoolExecutor(
119
137
  max_workers=conf.LOCAL_WORKERS,
138
+ mp_context=mp_context,
120
139
  initializer=_pool_initializer,
121
140
  )
122
141
  atexit.register(_shutdown_pool)
@@ -7,7 +7,7 @@ packages = ["lambda_tasks"]
7
7
 
8
8
  [project]
9
9
  name = "django-lambda-tasks"
10
- version = "0.6.2"
10
+ version = "0.6.4"
11
11
  description = "Run async tasks in a lambda function"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"
@@ -189,6 +189,25 @@ class TestGetPool:
189
189
 
190
190
  assert lambda_tasks.local_executor._pool is pool
191
191
 
192
+ @pytest.mark.usefixtures("_reset_pool")
193
+ def test_get_pool_uses_forkserver_context(self, settings):
194
+ """get_pool() uses the forkserver multiprocessing context.
195
+
196
+ This prevents workers from inheriting the parent's open database
197
+ connections, which would cause connection errors in containerized
198
+ environments.
199
+ """
200
+ import lambda_tasks.local_executor
201
+
202
+ settings.LAMBDA_TASKS_LOCAL_WORKERS = 2
203
+ settings.LAMBDA_TASKS_EAGER = False
204
+
205
+ pool = lambda_tasks.local_executor.get_pool()
206
+
207
+ # ProcessPoolExecutor stores the context; forkserver processes
208
+ # use the ForkServerProcess type
209
+ assert pool._mp_context.get_start_method() == "forkserver"
210
+
192
211
 
193
212
  # ---------------------------------------------------------------------------
194
213
  # Property-based tests: get_pool() (Requirement 2)