Skip to content

Commit

Permalink
Merge pull request #68 from dev-lymar/chore/dev-integrate-celery-rabb…
Browse files Browse the repository at this point in the history
…itmq

Chore/dev integrate celery rabbitmq
  • Loading branch information
dev-lymar committed Jun 16, 2024
2 parents 4cea665 + f70b870 commit 10c2838
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = http://...

# Domain name
DOMAIN_NAME=https://your_domain_name.com

# Allowed hosts
ALLOWED_HOSTS = *

Expand All @@ -16,6 +19,10 @@ DATABASE_PASSWORD = db_password
DATABASE_HOST = db
DATABASE_PORT = 5432

# RabbitMQ
RABBITMQ_DEFAULT_USER=username
RABBITMQ_DEFAULT_PASS=password

# Redis

REDIS_HOST = localhost
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,15 @@ jobs:
CORS_ORIGIN_ALLOW_ALL=${{ secrets.CORS_ORIGIN_ALLOW_ALL }}
CORS_ALLOW_CREDENTIALS=${{ secrets.CORS_ALLOW_CREDENTIALS }}
CORS_ALLOWED_ORIGINS=${{ secrets.CORS_ALLOWED_ORIGINS }}
DOMAIN_NAME=${{ secrets.DOMAIN_NAME }}
ALLOWED_HOSTS=${{ secrets.ALLOWED_HOSTS }}
DATABASE_NAME=${{ secrets.DATABASE_NAME }}
DATABASE_USER=${{ secrets.DATABASE_USER }}
DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }}
DATABASE_HOST=${{ secrets.DATABASE_HOST }}
DATABASE_PORT=${{ secrets.DATABASE_PORT }}
RABBITMQ_DEFAULT_USER=${{ secrets.RABBITMQ_DEFAULT_USER }}
RABBITMQ_DEFAULT_PASS=${{ secrets.RABBITMQ_DEFAULT_PASS }}
REDIS_HOST=${{ secrets.REDIS_HOST }}
REDIS_PORT=${{ secrets.REDIS_PORT }}
SECRET_KEY=${{ secrets.SECRET_KEY }}
Expand Down
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
[![Python](https://img.shields.io/badge/-Python-3776AB?style=flat&logo=Python&logoColor=yellow)](https://www.python.org/)
[![Django REST Framework](https://img.shields.io/badge/-Django%20REST%20Framework-092E20?style=flat&logo=django&logoColor=white)](https://www.django-rest-framework.org/)
[![PostgreSQL](https://img.shields.io/badge/-PostgreSQL-336791?style=flat&logo=PostgreSQL&logoColor=white)](https://www.postgresql.org/)
[![Redis](https://img.shields.io/badge/Redis-DC382D?style=flat&logo=Redis&logoColor=white)](https://redis.io/)
[![Docker](https://img.shields.io/badge/-Docker-2496ED?style=flat&logo=Docker&logoColor=white)](https://www.docker.com/)
[![Nginx](https://img.shields.io/badge/-Nginx-269539?style=flat&logo=Nginx&logoColor=white)](https://www.nginx.com/)
[![Psycopg2-binary](https://img.shields.io/badge/-Psycopg2--binary-4169E1?style=flat)](https://pypi.org/project/psycopg2-binary/)
[![Gunicorn](https://img.shields.io/badge/-Gunicorn-FFD700?style=flat&logo=Gunicorn&logoColor=white)](https://gunicorn.org/)
[![pytest](https://img.shields.io/badge/-pytest-0A9EDC?style=flat&logo=pytest&logoColor=white)](https://docs.pytest.org/)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![SimpleJWT](https://img.shields.io/badge/SimpleJWT-orange?style=flat&logo=jwt&logoColor=white)](https://github.com/jazzband/djangorestframework-simplejwt)
[![Python](https://img.shields.io/badge/Python-3.12.2-3776AB?style=flat&logo=Python&logoColor=yellow)](https://www.python.org/)
[![Django REST Framework](https://img.shields.io/badge/Django%20REST%20Framework-3.15.1-092E20?style=flat&logo=django&logoColor=white)](https://www.django-rest-framework.org/)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16.3-336791?style=flat&logo=PostgreSQL&logoColor=white)](https://www.postgresql.org/)
[![Redis](https://img.shields.io/badge/Redis-7.2.5-DC382D?style=flat&logo=Redis&logoColor=white)](https://redis.io/)
[![Celery](https://img.shields.io/badge/Celery-5.4-37814A?style=flat&logo=Celery&logoColor=white)](https://docs.celeryq.dev/)
[![RabbitMQ](https://img.shields.io/badge/RabbitMQ-3.13.3-FF6600?style=flat&logo=RabbitMQ&logoColor=white)](https://www.rabbitmq.com/)
[![Docker](https://img.shields.io/badge/Docker--2496ED?style=flat&logo=Docker&logoColor=white)](https://www.docker.com/)
[![Nginx](https://img.shields.io/badge/Nginx-3.17-269539?style=flat&logo=Nginx&logoColor=white)](https://www.nginx.com/)
[![Psycopg2-binary](https://img.shields.io/badge/Psycopg2--binary-2.9.9-4169E1?style=flat)](https://pypi.org/project/psycopg2-binary/)
[![Gunicorn](https://img.shields.io/badge/Gunicorn-21.2-FFD700?style=flat&logo=Gunicorn&logoColor=white)](https://gunicorn.org/)
[![pytest](https://img.shields.io/badge/pytest-8.0.2-0A9EDC?style=flat&logo=pytest&logoColor=white)](https://docs.pytest.org/)
[![Ruff](https://img.shields.io/badge/Ruff-0.3-FCC21B?style=flat&logo=ruff&logoColor=white"/)](https://github.com/astral-sh/ruff)
[![SimpleJWT](https://img.shields.io/badge/SimpleJWT-5.3.1-orange?style=flat&logo=jwt&logoColor=white)](https://github.com/jazzband/djangorestframework-simplejwt)

# Melnichanka

Expand Down
33 changes: 33 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,38 @@ services:
db:
condition: service_healthy

rabbitmq:
image: rabbitmq:3.13.3-alpine
restart: on-failure
env_file:
- .env
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS}
volumes:
- "rabbitmq_data:/var/lib/rabbitmq"
networks:
- melnichanka

worker:
build: .
command: celery -A melnichanka worker -l info
restart: on-failure
env_file:
- .env
environment:
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
depends_on:
- db
- rabbitmq
networks:
- melnichanka

redis:
image: redis:7.2.5-alpine
hostname: redis
Expand All @@ -64,3 +96,4 @@ networks:
volumes:
static_volume:
postgres_data:
rabbitmq_data:
3 changes: 1 addition & 2 deletions makedoc/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
get_formatted_date_agreement,
get_formatted_date_shipment,
)

from .data_service import DataService


Expand All @@ -22,7 +21,7 @@ def __init__(self, validated_data):

def update_documents(self):
delivery_type = DataService.get_delivery_type(self.validated_data)
if delivery_type == "auto":
if delivery_type in ["auto", "self-delivery"]:
self.auto = 1
if delivery_type == "rw":
self.rw = 1
Expand Down
5 changes: 5 additions & 0 deletions melnichanka/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ("celery_app",)
26 changes: 26 additions & 0 deletions melnichanka/celery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import absolute_import, unicode_literals

import os

from celery import Celery
from dotenv import load_dotenv

load_dotenv()

# Set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "melnichanka.settings")

broker_user = os.getenv("RABBITMQ_DEFAULT_USER")
broker_pass = os.getenv("RABBITMQ_DEFAULT_PASS")
broker_url = f"amqp://{broker_user}:{broker_pass}@rabbitmq:5672//"

app = Celery("melnichanka", broker=broker_url)

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object("django.conf:settings", namespace="CELERY")

# Load task modules from all registered Django apps.
app.autodiscover_tasks()
3 changes: 3 additions & 0 deletions melnichanka/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
CORS_ALLOWED_ORIGINS_RAW = os.getenv("CORS_ALLOWED_ORIGINS")
CORS_ALLOWED_ORIGINS = CORS_ALLOWED_ORIGINS_RAW.split(",") if CORS_ALLOWED_ORIGINS_RAW else []

# Domain name
DOMAIN_NAME = os.getenv("DOMAIN_NAME")

# Allowed hosts
ALLOWED_HOSTS_RAW = os.getenv("ALLOWED_HOSTS")
ALLOWED_HOSTS = ALLOWED_HOSTS_RAW.split(",") if ALLOWED_HOSTS_RAW else []
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
asgiref==3.7.2
attrs==23.2.0
Babel==2.14.0
celery==5.4.0
certifi==2024.2.2
cfgv==3.4.0
charset-normalizer==3.3.2
Expand Down
24 changes: 24 additions & 0 deletions users/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from celery import shared_task
from django.conf import settings
from django.core.mail import send_mail
from django.urls import reverse

domain = settings.DOMAIN_NAME


@shared_task
def send_reset_email(email, token):
email_plaintext_message = "Для сброса пароля перейдите по ссылке: {}{}?token={}".format(
domain, reverse("password_reset:reset-password-confirm"), token
)

send_mail(
# title:
"Сброс пароля для: {title}".format(title="EDO website"),
# message:
email_plaintext_message,
# from:
settings.EMAIL_HOST_USER,
# to:
[email],
)
22 changes: 2 additions & 20 deletions users/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from django.core.mail import send_mail
from django.dispatch import receiver
from django.urls import reverse
from django_rest_passwordreset.signals import reset_password_token_created
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
Expand All @@ -9,8 +7,6 @@
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import TokenObtainPairView

from melnichanka.settings import EMAIL_HOST_USER

from .models import CustomUser, Department, Position
from .serializers import (
CustomUserSerializer,
Expand All @@ -21,6 +17,7 @@
LogoutSerializer,
)
from .services import UserRelatedView
from .tasks import send_reset_email


class LoginView(TokenObtainPairView):
Expand Down Expand Up @@ -76,22 +73,7 @@ class UserUpdatePasswordView(UserRelatedView):
# Сброс пароля
@receiver(reset_password_token_created)
def password_reset_token_created(sender, instance, reset_password_token, *args, **kwargs):
email_plaintext_message = (
"Для сброса пароля перейдите по ссылке: http://127.0.0.1:8000{}?token={}".format(
reverse("password_reset:reset-password-confirm"), reset_password_token.key
)
)

send_mail(
# title:
"Сброс пароля для: {title}".format(title="EDO website"),
# message:
email_plaintext_message,
# from:
EMAIL_HOST_USER,
# to:
[reset_password_token.user.email],
)
send_reset_email.delay(reset_password_token.user.email, reset_password_token.key)


# Передача списка департаментов для фронтенда
Expand Down

0 comments on commit 10c2838

Please sign in to comment.