Django Marathon
===============
Django Marathon helps manage single runner tasks that need to avoid concurrency issues,
ensuring that tasks are executed without overlapping.
Requirements
------------
- Python 3.6+
- Django 3.1+
Installation
------------
You can install Django Marathon via pip:
::
pip install django-marathon
Add `marathon` to your Django project's `INSTALLED_APPS`:
::
INSTALLED_APPS = [
...
'marathon',
]
Features
--------
- Ensures single execution of tasks to avoid concurrency.
- Easy integration with Django management commands.
How Django Marathon Works
-------------------------
Under the hood, Django Marathon uses a simple locking mechanism to prevent concurrent
execution of tasks.
1. **Lock Model**: Single runner tasks will create a lock in the database,
using the `Lock` model. A lock has unique name representing the tasks.
It also has a timestamp indicating when the lock was created.
Each task that needs to avoid concurrency will first have to check the lock
table before running.
2. **SingleRunnerCommand**: This is a helper class that is designed to be used in
Django management commands.
3. **Lock Acquisition and Release**: When a command using `SingleRunnerCommand` is executed,
it first checks if a lock with the specified name exists. If it does, the command does not run.
If no lock exists, the command proceeds, and a lock is created.
Once the command completes, the lock is released, allowing future executions.
Usage With Django Management Commands
-------------------------------------
Define a tasks that should be run without concurrency.
`SingleRunnerCommand` is a base command class provided by Django Marathon to
ensure that a management command does not run concurrently.
::
from marathon.commands import SingleRunnerCommand
from django.core.management.base import BaseCommand
class Command(SingleRunnerCommand, BaseCommand):
help = 'Your command description here'
def handle(self, *args, **options):
self.stdout.write('Starting task...')
# Your task logic here
self.stdout.write('Task completed.')
Using the Locking Mechanism Outside Management Commands
-------------------------------------------------------
Django Marathon's locking mechanism can also be utilized outside of management commands.
Here's a general approach:
- Check if the lock exists
- Create a new lock if not
- Implement you task logic
- Release the lock
In practice, we would typically do the first 2 steps together.
Example Implementation:
::
from marathon.models import Lock
def my_task():
lock_name = "my-unique-task-lock"
# Get the existing lock or create a new one
lock, created = Lock.objects.get_or_create(name=lock_name)
if not created:
print("Task is already running, please try again later.")
return
try:
# Your task logic here
print("Task is running...")
except Exception as e:
print(f"An error occurred: {str(e)}")
finally:
# Release the lock
lock.delete()
print("Task completed successfully.")
Raw data
{
"_id": null,
"home_page": "https://github.com/lazybird/django-marathon/",
"name": "django-marathon",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "Django single runner tasks concurrency concurrency-avoidance",
"author": null,
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/c1/7c/f72bff0a1c18b77b4ba48bb3b8fdefb1249249e516c28f3fc5b56ce2926c/django_marathon-0.1.tar.gz",
"platform": null,
"description": "Django Marathon\n===============\n\nDjango Marathon helps manage single runner tasks that need to avoid concurrency issues,\nensuring that tasks are executed without overlapping.\n\nRequirements\n------------\n\n- Python 3.6+\n- Django 3.1+\n\nInstallation\n------------\n\nYou can install Django Marathon via pip:\n\n::\n\n pip install django-marathon\n\n\nAdd `marathon` to your Django project's `INSTALLED_APPS`:\n\n::\n\n INSTALLED_APPS = [\n ...\n 'marathon',\n ]\n\n\nFeatures\n--------\n\n- Ensures single execution of tasks to avoid concurrency.\n- Easy integration with Django management commands.\n\nHow Django Marathon Works\n-------------------------\n\nUnder the hood, Django Marathon uses a simple locking mechanism to prevent concurrent\nexecution of tasks.\n\n1. **Lock Model**: Single runner tasks will create a lock in the database,\nusing the `Lock` model. A lock has unique name representing the tasks.\nIt also has a timestamp indicating when the lock was created.\nEach task that needs to avoid concurrency will first have to check the lock\ntable before running.\n\n2. **SingleRunnerCommand**: This is a helper class that is designed to be used in\nDjango management commands.\n\n3. **Lock Acquisition and Release**: When a command using `SingleRunnerCommand` is executed,\nit first checks if a lock with the specified name exists. If it does, the command does not run.\nIf no lock exists, the command proceeds, and a lock is created.\nOnce the command completes, the lock is released, allowing future executions.\n\n\nUsage With Django Management Commands\n-------------------------------------\n\nDefine a tasks that should be run without concurrency.\n\n\n`SingleRunnerCommand` is a base command class provided by Django Marathon to\nensure that a management command does not run concurrently.\n\n::\n\n from marathon.commands import SingleRunnerCommand\n from django.core.management.base import BaseCommand\n\n class Command(SingleRunnerCommand, BaseCommand):\n help = 'Your command description here'\n\n def handle(self, *args, **options):\n self.stdout.write('Starting task...')\n # Your task logic here\n self.stdout.write('Task completed.')\n\n\nUsing the Locking Mechanism Outside Management Commands\n-------------------------------------------------------\n\nDjango Marathon's locking mechanism can also be utilized outside of management commands.\n\n\n\n\nHere's a general approach:\n- Check if the lock exists\n- Create a new lock if not\n- Implement you task logic\n- Release the lock\n\nIn practice, we would typically do the first 2 steps together.\n\nExample Implementation:\n\n::\n\n from marathon.models import Lock\n\n def my_task():\n lock_name = \"my-unique-task-lock\"\n # Get the existing lock or create a new one\n lock, created = Lock.objects.get_or_create(name=lock_name)\n if not created:\n print(\"Task is already running, please try again later.\")\n return\n try:\n # Your task logic here\n print(\"Task is running...\")\n except Exception as e:\n print(f\"An error occurred: {str(e)}\")\n finally:\n # Release the lock\n lock.delete()\n print(\"Task completed successfully.\")\n",
"bugtrack_url": null,
"license": null,
"summary": "Helps manage single runner tasks that need to avoid concurrency issues.",
"version": "0.1",
"project_urls": {
"Homepage": "https://github.com/lazybird/django-marathon/"
},
"split_keywords": [
"django",
"single",
"runner",
"tasks",
"concurrency",
"concurrency-avoidance"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c9cec3083b84472906429dec1cb4a9cbbc749aa61083a11e46cd4d8a126bf7d8",
"md5": "ceebba3fb2cc800796d20bfbe9018a66",
"sha256": "2069b9726ee7b7f6cd0643ca0e8bdbea5fb79c4ec5a3167c19225ce14acb5625"
},
"downloads": -1,
"filename": "django_marathon-0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ceebba3fb2cc800796d20bfbe9018a66",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 13234,
"upload_time": "2024-11-18T18:39:24",
"upload_time_iso_8601": "2024-11-18T18:39:24.783545Z",
"url": "https://files.pythonhosted.org/packages/c9/ce/c3083b84472906429dec1cb4a9cbbc749aa61083a11e46cd4d8a126bf7d8/django_marathon-0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c17cf72bff0a1c18b77b4ba48bb3b8fdefb1249249e516c28f3fc5b56ce2926c",
"md5": "5aed0f84757159edee176ddc663d3e04",
"sha256": "a9267ba6c18c86f606b210bd66b680499993b11c4ef853e1ed29433ed3ba4fc8"
},
"downloads": -1,
"filename": "django_marathon-0.1.tar.gz",
"has_sig": false,
"md5_digest": "5aed0f84757159edee176ddc663d3e04",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 7669,
"upload_time": "2024-11-18T18:39:26",
"upload_time_iso_8601": "2024-11-18T18:39:26.104069Z",
"url": "https://files.pythonhosted.org/packages/c1/7c/f72bff0a1c18b77b4ba48bb3b8fdefb1249249e516c28f3fc5b56ce2926c/django_marathon-0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-18 18:39:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lazybird",
"github_project": "django-marathon",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "django-marathon"
}