Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A broker agnostic implementation of outbox and other message resilience patterns for Django apps.

License

NotificationsYou must be signed in to change notification settings

loadsmart/django-jaiminho

Repository files navigation

CircleCICode style: black

A broker agnostic implementation of the outbox and other message resilience patterns for Django apps.

Jaiminho

Getting Started

To use jaiminho with your project, you just need to do 6 steps:

1 - Install it

python -m pip install jaiminho

2 - Add jaiminho to the INSTALLED_APPS

INSTALLED_APPS= [    ..."jaiminho"]

3 - Run migrations

python manage.py migrate

4 - Configure jaiminho options in Django settings.py:

JAIMINHO_CONFIG= {"PERSIST_ALL_EVENTS":False,"DELETE_AFTER_SEND":True,"DEFAULT_ENCODER":DjangoJSONEncoder,"PUBLISH_STRATEGY":"publish-on-commit",}

5 - Decorate your functions with @save_to_outbox

fromjaiminho.sendimportsave_to_outbox@save_to_outboxdefany_external_call(**kwargs):# do somethingreturn

6 - Run the relay events command

python manage.py events_relay --run-in-loop --loop-interval 1

If you don't use--run-in-loop option, the relay command will run only 1 time. This is useful in case you want to configure it as a cronjob.

Details

Jaiminho@save_to_outbox decorator willintercept decorated function andpersist it in adatabase table in the sametransaction that is active in the decorated function context. The event relaycommand, is aseparated process that fetches the rows from this table and execute the functions. When an outage happens, the event relay command willkeep retrying until it succeeds. This way,eventual consistency is ensured by design.

Configuration options

  • PUBLISH_STRATEGY - Strategy used to publish events (publish-on-commit, keep-order)
  • PERSIST_ALL_EVENTS - Saves all events and not only the ones that fail, default isFalse. Only applicable for{ "PUBLISH_STRATEGY": "publish-on-commit" } since all events needs to be stored on keep-order strategy.
  • DELETE_AFTER_SEND - Delete the event from the outbox table immediately, after a successful send
  • DEFAULT_ENCODER - Default Encoder for the payload (overwritable in the function call)

Strategies

Keep Order

This strategy is similar to transactional outboxdescribed by Chris Richardson. The decorated function intercepts the function call and saves it on the local DB to be executed later. A separate command relayer will keep polling local DB and executing those functions in the same order it was stored.Be carefully with this approach,if any execution fails, the relayer will get stuck as it would not be possible to guarantee delivery order.

Publish on commit

This strategy will always execute the decorated function after current transaction commit. With this approach, we don't depend on a relayer (separate process / cronjob) to execute the decorated function and deliver the message. Failed items will only be retriedthrough relayer. Although this solution has a better performance as only failed items is delivered by the relay command,we cannot guarantee delivery order.

Relay Command

We already provide a command to relay items from DB,EventRelayCommand. The way you should configure depends on the strategy you choose.For example, onPublish on Commit Strategy you can configure a cronjob to run every a couple of minutes since only failed items are published by the command relay. If you are usingKeep Order Strategy, you should run relay command in loop mode as all items will be published by the command, e.gcall_command(events_relay.Command(), run_in_loop=True, loop_interval=0.1).

How to clean older events

You can use Jaiminho'sEventCleanerCommand in order to do that. It will query for all events that were sent before a given time interval (e.g. last 7 days) and will delete them from the outbox table.

The default time interval is7 days. You can use theTIME_TO_DELETE setting to change it. It should be added toJAIMINHO_CONFIG and must be a validtimedelta.

Running as cron jobs

You can run those commands in a cron job. Here are some config examples:

  -name:relay-failed-outbox-eventsschedule:"*/15 * * * *"suspend:falseargs:      -ddtrace-run      -python      -manage.py      -events_relayresources:requests:cpu:1limits:memory:384Mi  -name:delete-old-outbox-eventsschedule:"0 5 * * *"suspend:falseargs:      -ddtrace-run      -python      -manage.py      -event_cleanerresources:requests:cpu:1limits:memory:384Mi

Relay per stream and Overwrite publish strategy

Different streams can have different requirements. You can save separate events per streams by using the@save_to_outbox_stream decorator:

@save_to_outbox_stream("my-stream")defany_external_call(payload,**kwargs):# do somethingpass

you can also overwrite publish strategy configure on settings:

@save_to_outbox_stream("my-stream",PublishStrategyType.KEEP_ORDER)defany_external_call(payload,**kwargs):# do somethingpass

And then, run relay command with stream filter option

python manage.py relay_event True 0.1 my-stream

In the example above,True is the option for run_in_loop;0.1 for loop_interval; andmy_stream is the name of the stream.

Signals

Jaiminho triggers the following Django signals:

SignalDescription
event_publishedTriggered when an event is sent successfully
event_failed_to_publishTriggered when an event is not sent, being added to the Outbox table queue

How to collect metrics from Jaiminho?

You could use the Django signals triggered by Jaiminho to collect metrics.Consider the following code as example:

fromdjango.dispatchimportreceiver@receiver(event_published)defon_event_sent(sender,event_payload,**kwargs):metrics.count(f"event_sent_successfully{event_payload.get('type')}")@receiver(event_failed_to_publish)defon_event_send_error(sender,event_payload,**kwargs):metrics.count(f"event_failed{event_payload.get('type')}")

Jaiminho with Celery

Jaiminho can be very useful for adding reliability to Celery workflows. Writing to the database and enqueuing Celery tasks in the same workflow is very common in many applications, and this pattern can benefit greatly from the outbox pattern to ensure message delivery reliability.

Instead of configuring the@save_to_outbox decorator for every individual Celery task, you can integrate it at the Celery class level by overriding thesend_task method, which is used by Celery to enqueue new tasks. This way, all tasks automatically benefit from the outbox pattern without requiring individual configuration.

Here's how to implement this:

fromceleryimportCeleryfromjaiminhoimportsave_to_outboxclassCeleryWithJaiminho(Celery):"""    Custom Celery class that inherits from Celery base class    and adds Jaiminho functionality    """@save_to_outboxdefsend_task(self,*args,**kwargs):"""Send task with outbox pattern for reliability"""returnsuper().send_task(*args,**kwargs)app=CeleryWithJaiminho("tasks")

With this approach, all tasks sent through your Celery app will automatically use the outbox pattern, ensuring that task enqueuing is resilient to transient failures and network issues.

Development

Create a virtualenv

virtualenv venvpip install -r requirements-dev.txttox -e py39

Collaboration

If you want to improve or suggest improvements, check ourCONTRIBUTING.md file.

License

This project is licensed under MIT License.

Security

If you have any security concern or report feel free to reach out tosecurity@loadsmart.com;

About

A broker agnostic implementation of outbox and other message resilience patterns for Django apps.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors15


[8]ページ先頭

©2009-2025 Movatter.jp