Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 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
3 changes: 3 additions & 0 deletions backend/account_v2/organization.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

from django.db import IntegrityError
from utils.db_retry import db_retry

from account_v2.models import Organization

Expand All @@ -12,13 +13,15 @@ def __init__(self): # type: ignore
pass

@staticmethod
@db_retry() # Add retry for connection drops during organization lookup
def get_organization_by_org_id(org_id: str) -> Organization | None:
try:
return Organization.objects.get(organization_id=org_id) # type: ignore
except Organization.DoesNotExist:
return None

@staticmethod
@db_retry() # Add retry for connection drops during organization creation
def create_organization(
name: str, display_name: str, organization_id: str
) -> Organization:
Expand Down
37 changes: 36 additions & 1 deletion backend/backend/celery_config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import os
from urllib.parse import quote_plus

from django.conf import settings

from backend.celery_db_retry import get_celery_db_engine_options, should_use_builtin_retry

Comment on lines +7 to +8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix import path for retry helpers.

File resides under backend/backend/, so the import should reference backend.backend.celery_db_retry. Current path will fail at runtime.

Apply this diff:

-from backend.celery_db_retry import get_celery_db_engine_options, should_use_builtin_retry
+from backend.backend.celery_db_retry import (
+    get_celery_db_engine_options,
+    should_use_builtin_retry,
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from backend.celery_db_retry import get_celery_db_engine_options, should_use_builtin_retry
from backend.backend.celery_db_retry import (
get_celery_db_engine_options,
should_use_builtin_retry,
)
🤖 Prompt for AI Agents
In backend/backend/celery_config.py around lines 6 to 7, the import path for the
retry helpers is incorrect; update the import to reference the actual module
location by changing the import to use backend.backend.celery_db_retry and
import get_celery_db_engine_options and should_use_builtin_retry from that
module so the runtime can resolve the symbols.


class CeleryConfig:
"""Specifies celery configuration
"""Specifies celery configuration with hybrid retry support.

Supports both custom retry (via patching) and Celery's built-in retry
based on CELERY_USE_BUILTIN_RETRY environment variable.

Refer https://docs.celeryq.dev/en/stable/userguide/configuration.html
"""
Expand All @@ -31,3 +37,32 @@ class CeleryConfig:
beat_scheduler = "django_celery_beat.schedulers:DatabaseScheduler"

task_acks_late = True

# Database backend engine options for PgBouncer compatibility
result_backend_transport_options = get_celery_db_engine_options()

Comment on lines +44 to +46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm Celery picks up engine options for SQLAlchemy backend.

result_backend_transport_options is correct for Celery’s SQLAlchemy backend; please verify on your Celery version that these are passed to create_engine.

Run:

If your version differs, we may need to adjust the config key or option names.


🏁 Script executed:

#!/bin/bash
# Inspect Celery DatabaseBackend to confirm it uses `result_backend_transport_options`
python - <<'PY'
import inspect
from celery.backends import database
print("DatabaseBackend.create_backend method:\n")
print(inspect.getsource(database.DatabaseBackend.__init__))
PY

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Locate Celery dependency and its pinned version in the repository
grep -R "celery" -n requirements*.txt pyproject.toml setup.py

Length of output: 255


🏁 Script executed:

#!/bin/bash
# Install the pinned Celery version and inspect DatabaseBackend for transport options handling
pip install celery==5.3.4 >/dev/null 2>&1
python - <<'PY'
import inspect
from celery.backends.database import DatabaseBackend

print("Signature of DatabaseBackend.__init__:\n")
print(inspect.signature(DatabaseBackend.__init__), "\n")
print("Source snippet around engine creation in DatabaseBackend:\n")
src = inspect.getsource(DatabaseBackend)
for line in src.splitlines():
    if "create_engine" in line or "transport_options" in line:
        print(line)
PY

Length of output: 437


🏁 Script executed:

#!/bin/bash
# Install Celery and SQLAlchemy to enable DatabaseBackend inspection
pip install celery==5.3.4 sqlalchemy >/dev/null 2>&1
python - <<'PY'
import inspect
from celery.backends.database import DatabaseBackend

print("Signature of DatabaseBackend.__init__:\n", inspect.signature(DatabaseBackend.__init__), "\n")
source = inspect.getsource(DatabaseBackend)
print("Lines containing engine creation or transport options:\n")
for line in source.splitlines():
    if "create_engine" in line or "transport_options" in line:
        print(line)
PY

Length of output: 157


🏁 Script executed:

#!/bin/bash
# Print the source of DatabaseBackend.__init__ to inspect engine_options usage
python - <<'PY'
import inspect
from celery.backends.database import DatabaseBackend
print(inspect.getsource(DatabaseBackend.__init__))
PY

Length of output: 1243


Use database_engine_options instead of result_backend_transport_options in backend/backend/celery_config.py
Celery’s SQLAlchemy result backend reads engine options from conf.database_engine_options (not result_backend_transport_options) and passes them into create_engine via SessionManager.session_factory (docs.celeryq.dev)

🤖 Prompt for AI Agents
In backend/backend/celery_config.py around lines 41 to 43, the code sets Celery
SQLAlchemy engine options using result_backend_transport_options, but Celery
expects these under database_engine_options; change the assignment to set
conf.database_engine_options (i.e., assign get_celery_db_engine_options() to
database_engine_options) so the SQLAlchemy result backend receives the engine
options passed into create_engine via SessionManager.session_factory.

# Hybrid retry configuration - built-in vs custom
if should_use_builtin_retry():
# Use Celery's built-in database backend retry
result_backend_always_retry = (
os.environ.get("CELERY_RESULT_BACKEND_ALWAYS_RETRY", "true").lower() == "true"
)
result_backend_max_retries = int(
os.environ.get("CELERY_RESULT_BACKEND_MAX_RETRIES", "3")
)
result_backend_base_sleep_between_retries_ms = int(
os.environ.get("CELERY_RESULT_BACKEND_BASE_SLEEP_BETWEEN_RETRIES_MS", "1000")
)
result_backend_max_sleep_between_retries_ms = int(
os.environ.get("CELERY_RESULT_BACKEND_MAX_SLEEP_BETWEEN_RETRIES_MS", "30000")
)

print(
f"[Celery Config] Using built-in retry: max_retries={result_backend_max_retries}, "
)
print(
f"base_sleep={result_backend_base_sleep_between_retries_ms}ms, max_sleep={result_backend_max_sleep_between_retries_ms}ms"
)
else:
# Custom retry is handled by patch_celery_database_backend()
print("[Celery Config] Using custom retry system (patching enabled)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ali-e use a logger instead of print statements

Loading