Skip to content

Django yubin celery bypass backend and management commands#69

Open
Coperh wants to merge 7 commits intomainfrom
feature/yubin-celery-bypass
Open

Django yubin celery bypass backend and management commands#69
Coperh wants to merge 7 commits intomainfrom
feature/yubin-celery-bypass

Conversation

@Coperh
Copy link
Copy Markdown

@Coperh Coperh commented Mar 6, 2026

  • adds the ability to use django yubin without using celery tasks after version >2
  • Copies Message.enqueue, Message.retry_messages methods and django_yubin.queue_email_message and replaces the celery tasks
  • Copies django_yubin.backends.QueuedEmailBackend and replaces with modified queue_email_message
  • add maykin_common.yubin.engine.send_all to manually send yubin Messages

@Coperh Coperh changed the title ✨ add django yubin celery bypass backend and management comm… Django yubin celery bypass backend and management commands Mar 6, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.27%. Comparing base (c5f8985) to head (4771f6b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #69      +/-   ##
==========================================
+ Coverage   99.18%   99.27%   +0.08%     
==========================================
  Files          27       34       +7     
  Lines         736      826      +90     
  Branches       87       92       +5     
==========================================
+ Hits          730      820      +90     
  Misses          4        4              
  Partials        2        2              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from 579d925 to cc2712f Compare March 6, 2026 11:33
Comment thread maykin_common/yubin/management/commands/send_all_mail.py Outdated
Comment thread maykin_common/yubin/management/commands/send_all_mail.py Outdated
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch 3 times, most recently from f11847d to 98a32f5 Compare March 10, 2026 13:49
@Coperh Coperh marked this pull request as ready for review March 10, 2026 14:15
@alextreme
Copy link
Copy Markdown
Member

@Coperh squash your commits and reference in your commit message the github issue in order to describe what you're doing

@Coperh Coperh requested a review from CharString March 11, 2026 10:49
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from e3f055b to ba5c1f6 Compare March 11, 2026 15:16
Copy link
Copy Markdown
Contributor

@CharString CharString left a comment

Choose a reason for hiding this comment

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

I'm not sure I understand the locking tests fully.

My underbelly would reach for a stateful property based test of the behaviour of the whole system. Generate actions and (failure) events, and have a simple model of what we expect (could be a few list[Message] as queues) and then if there is no sequential order for these actions that we did in parallel, than something is wrong with the system.

Or alternatively. Unittest the lock parts more tightly instead of trying to get the whole call_command chain testable. There are many moving parts there.

Comment thread maykin_common/yubin/backends.py Outdated
Comment thread tests/yubin/test_engine.py Outdated
Comment thread tests/yubin/test_management_commands.py Outdated
Comment thread tests/yubin/test_management_commands.py Outdated
Comment thread tests/yubin/test_management_commands.py Outdated
Comment thread tests/yubin/test_management_commands.py Outdated
Comment thread maykin_common/yubin/engine.py Outdated
Comment thread maykin_common/yubin/engine.py Outdated
Comment thread maykin_common/yubin/utils.py Outdated
Comment thread maykin_common/yubin/backends.py Outdated
@CharString
Copy link
Copy Markdown
Contributor

BTW, assert True + True == 2 and False + False == 0 so you can sum booleans.

@Coperh Coperh requested a review from CharString March 18, 2026 09:31
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch 2 times, most recently from d237d51 to 02e2513 Compare March 18, 2026 09:33
Copy link
Copy Markdown
Contributor

@CharString CharString left a comment

Choose a reason for hiding this comment

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

Nice. Looking forward to replace my implementation with this. Just had an insight (I think) for some simplification.

Comment thread maykin_common/yubin/backends.py Outdated
Comment thread maykin_common/yubin/utils.py
Comment thread maykin_common/yubin/engine.py Outdated
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from b2966e1 to af84718 Compare March 20, 2026 14:01
@Coperh
Copy link
Copy Markdown
Author

Coperh commented Mar 20, 2026

Removed YUBIN_LOCK_WAIT_TIMEOUT and tests/yubin/test_engine.py testing it

TBD: squash commits

@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from e44e536 to ba43f61 Compare March 20, 2026 15:17
@Coperh Coperh requested a review from CharString March 20, 2026 15:23
@alextreme
Copy link
Copy Markdown
Member

@sergei-maertens wil jij deze als hoeder van django-common mergen?

@sergei-maertens sergei-maertens self-assigned this Mar 31, 2026
@sergei-maertens
Copy link
Copy Markdown
Member

@sergei-maertens wil jij deze als hoeder van django-common mergen?

I see I have some pending review comments, I'll set aside some time this week hopefully. Please remind me if I forget.

Copy link
Copy Markdown
Member

@sergei-maertens sergei-maertens left a comment

Choose a reason for hiding this comment

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

My main concern here is that django-yubin will still pull in the celery dependency, and there is code here and there that detects availability of Celery based on the import succeeding or not. I'm afraid that there will still be situations where errors pop up because some thing is trying to dispatch a celery task while it's not configured. Is that addressed in any way?

Comment thread pyproject.toml Outdated
"django-stubs",
"decouple-types",
"redis",
"freezegun",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you try https://github.com/adamchainz/time-machine instead? There's a blog post describing why it's better and should replace freezegun usage.

Comment thread pyproject.toml
]
yubin = [
"django-yubin>=2.0.0",
"filelock",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we need to take containerized applications into account that may not have a shared file system where the lock file is created?

Comment thread maykin_common/settings.py Outdated
Comment on lines +107 to +108
YUBIN_LOCK_PATH: Path = Path("/tmp") / "send_mail"
YUBIN_LOCK_WAIT_TIMEOUT: int = 0
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you properly prefix the settings with MKN_ so that it's clear these are our own settings and not to be confused with the actual django-yubin?

Comment thread testapp/settings.py Outdated
Comment on lines +18 to +21
try:
import django_yubin
except ImportError:
django_yubin = None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please use the importlib way of detecting installed libraries instead, it's the recommended approach.

Comment thread docs/index.rst Outdated
health_checks
otel
apis
yubin
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd argue that the settings documentation is going to be read more often than the Yubin workaround, so I'd move this down in the toc tree below settings.

Comment thread tests/yubin/test_utils.py
"""
Tests original Message.enqueue functionality
Should not mark the message as enqueued if not allowed
"""
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This confuses me. To me, the original is Message.enqueue, but that's not being called here, instead the separate function is being called. Is the intent to replace/monkeypatch the model method? If not, what happens if some code calls the model method instead of going through the custom function?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I really also want to see test docstrings in the form of:

Assert that X happens when Y...

this also applies to the test name itself. Now if you read the test name, it implies that enqueue can never actually queue the message, but clearly there are some conditions to take into account.

Comment thread tests/yubin/test_utils.py Outdated
Comment thread tests/yubin/test_utils.py Outdated
Comment thread tests/yubin/test_utils.py Outdated
Comment thread tests/yubin/test_utils.py
Comment on lines +89 to +93
# yubin does not correctly use django settings
from django_yubin import settings

settings.MAILER_TEST_MODE = True
settings.MAILER_TEST_EMAIL = "test_mailer@example.com,test_mailer2@example.com"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

does this correctly reset the settings after the test exits? This looks like a broken test isolation problem for future tests being added.

Copy link
Copy Markdown
Member

@sergei-maertens sergei-maertens left a comment

Choose a reason for hiding this comment

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

My main concern here is that django-yubin will still pull in the celery dependency, and there is code here and there that detects availability of Celery based on the import succeeding or not. I'm afraid that there will still be situations where errors pop up because some thing is trying to dispatch a celery task while it's not configured. Is that addressed in any way?

Coperh and others added 5 commits April 23, 2026 11:05
Co-authored-by: Chris Wesseling <chris.wesseling@protonmail.com>
Co-authored-by: Sergei Maertens <sergei-maertens@users.noreply.github.com>
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from fdb5c4f to deff661 Compare April 23, 2026 09:05
@Coperh Coperh force-pushed the feature/yubin-celery-bypass branch from deff661 to 4771f6b Compare April 23, 2026 13:14
@Coperh
Copy link
Copy Markdown
Author

Coperh commented Apr 23, 2026

I think I addressed all of the comments

@Coperh Coperh requested a review from sergei-maertens April 23, 2026 13:27
@Coperh
Copy link
Copy Markdown
Author

Coperh commented Apr 23, 2026

An issue I found with the non-monkeypatched way is that yubin does run django_yubin.tasks.sent_email.delay(pk) in migration 0007 and that will not work if rabbitmq is not runnning

My bypass is to patch like here:

from django_yubin import tasks
tasks.send_email.delay = lambda *args, **kwargs: None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants