Skip to content
This repository was archived by the owner on Mar 27, 2023. It is now read-only.

Commit 6b5241d

Browse files
committed
Merge branch '35-add-flower-for-celery-monitoring' into 'develop'
Resolve "Add flower service" Closes #35 See merge request verbose-equals-true/django-postgres-vue-gitlab-ecs!83
2 parents 1f84226 + 5001e21 commit 6b5241d

File tree

32 files changed

+302
-366
lines changed

32 files changed

+302
-366
lines changed

.env.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ GOOGLE_OAUTH2_SECRET=abcde-fghij
1818
SOCIAL_AUTH_FACEBOOK_KEY = ''
1919
SOCIAL_AUTH_FACEBOOK_SECRET = ''
2020

21-
CELERY_BROKER_URL=redis://redis:6379
22-
CELERY_RESULT_BACKEND=redis://redis:6379
21+
CELERY_BROKER_URL=redis://redis:6379/0
22+
CELERY_RESULT_BACKEND=redis://redis:6379/1
2323

2424
DJANGO_EMAIL_HOST=mailhog
2525
DJANGO_EMAIL_PORT=1025

awscdk/awscdk/backend.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ def __init__(self, scope: core.Construct, id: str, **kwargs,) -> None:
5757
"BackendTarget",
5858
port=80,
5959
targets=[self.backend_service],
60-
priority=1,
60+
priority=2,
6161
path_patterns=["*"],
6262
health_check=elbv2.HealthCheck(
63-
healthy_http_codes="200-299", path="/api/hello-world",
63+
healthy_http_codes="200-299", path="/api/health-check/",
6464
),
6565
)

awscdk/awscdk/cdk_app_root.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from ecs import EcsStack
1414
from env_vars import Variables
1515
from static_site_bucket import StaticSiteStack
16+
from flower import FlowerServiceStack
1617

1718
from backend import BackendServiceStack
1819
from backend_tasks import BackendTasksStack
@@ -55,6 +56,11 @@ def __init__(
5556
self.static_site_stack = StaticSiteStack(self, "StaticSiteStack")
5657
self.static_site_bucket = self.static_site_stack.static_site_bucket
5758

59+
self.backend_assets = BackendAssetsStack(self, "BackendAssetsStack")
60+
self.backend_assets_bucket = self.backend_assets.assets_bucket
61+
62+
self.cloudfront = CloudFrontStack(self, "CloudFrontStack")
63+
5864
if os.path.isdir("./quasar/dist/pwa"):
5965
s3_deployment.BucketDeployment(
6066
self,
@@ -64,11 +70,6 @@ def __init__(
6470
distribution=self.cloudfront.distribution,
6571
)
6672

67-
self.backend_assets = BackendAssetsStack(self, "BackendAssetsStack")
68-
self.backend_assets_bucket = self.backend_assets.assets_bucket
69-
70-
self.cloudfront = CloudFrontStack(self, "CloudFrontStack")
71-
7273
self.ecs = EcsStack(self, "EcsStack")
7374

7475
self.rds = RdsStack(self, "RdsStack")
@@ -93,6 +94,7 @@ def __init__(
9394
)
9495

9596
self.backend_service = BackendServiceStack(self, "BackendServiceStack")
97+
self.flower_service = FlowerServiceStack(self, "FlowerServiceStack")
9698

9799
self.celery_default_service = CeleryDefaultServiceStack(
98100
self, "CeleryDefaultServiceStack"

awscdk/awscdk/celery_default.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
aws_ecs as ecs,
55
aws_logs as logs,
66
aws_cloudformation as cloudformation,
7-
aws_sqs as sqs,
87
)
98

109

awscdk/awscdk/cloudfront.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,11 @@ def __init__(self, scope: core.Construct, id: str, **kwargs,) -> None:
6565
behaviors=[
6666
cloudfront.Behavior(
6767
allowed_methods=ALL_METHODS,
68+
forwarded_values={"query_string": True},
6869
path_pattern=path_pattern,
69-
max_ttl=core.Duration.seconds(0),
7070
min_ttl=core.Duration.seconds(0),
71-
forwarded_values={"query_string": True},
71+
default_ttl=core.Duration.seconds(0),
72+
max_ttl=core.Duration.seconds(0),
7273
)
7374
for path_pattern in ["/static/*", "/media/*"]
7475
],

awscdk/awscdk/flower.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import os
2+
3+
from aws_cdk import (
4+
core,
5+
aws_ec2 as ec2,
6+
aws_ecs as ecs,
7+
aws_logs as logs,
8+
aws_cloudformation as cloudformation,
9+
aws_elasticloadbalancingv2 as elbv2,
10+
)
11+
12+
13+
class FlowerServiceStack(cloudformation.NestedStack):
14+
def __init__(self, scope: core.Construct, id: str, **kwargs,) -> None:
15+
super().__init__(
16+
scope, id, **kwargs,
17+
)
18+
19+
self.flower_task = ecs.FargateTaskDefinition(self, "FlowerTask")
20+
21+
FLOWER_PASSWORD = os.environ.get("FLOWER_PASSWORD", "flowerpassword")
22+
REDIS_SERVICE_HOST = (
23+
scope.elasticache.elasticache.attr_redis_endpoint_address
24+
)
25+
CELERY_BROKER_URL = f"redis://{REDIS_SERVICE_HOST}:6379/0"
26+
self.flower_task.add_container(
27+
"FlowerContainer",
28+
image=ecs.ContainerImage.from_registry("mher/flower"),
29+
logging=ecs.LogDrivers.aws_logs(
30+
stream_prefix="FlowerContainer",
31+
log_retention=logs.RetentionDays.ONE_DAY,
32+
),
33+
command=[
34+
"--url_prefix=flower",
35+
f"--broker={CELERY_BROKER_URL}",
36+
f"--basic_auth=flower:{FLOWER_PASSWORD}",
37+
],
38+
)
39+
40+
port_mapping = ecs.PortMapping(
41+
container_port=5555, protocol=ecs.Protocol.TCP
42+
)
43+
self.flower_task.default_container.add_port_mappings(port_mapping)
44+
45+
self.flower_service = ecs.FargateService(
46+
self,
47+
"FlowerService",
48+
task_definition=self.flower_task,
49+
assign_public_ip=True,
50+
cluster=scope.ecs.cluster,
51+
security_group=ec2.SecurityGroup.from_security_group_id(
52+
self,
53+
"FlowerServiceSecurityGroup",
54+
security_group_id=scope.vpc.vpc_default_security_group,
55+
),
56+
)
57+
58+
scope.https_listener.add_targets(
59+
"FlowerTarget",
60+
port=80,
61+
targets=[self.flower_service],
62+
priority=1,
63+
path_patterns=["/flower/*", "flower/*"],
64+
health_check=elbv2.HealthCheck(
65+
healthy_http_codes="200-401", path="/flower/"
66+
),
67+
)

backend/apps/core/management/commands/__init__.py

Whitespace-only changes.

backend/apps/core/management/commands/watch_celery.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,32 @@
66
https://avilpage.com/2017/05/how-to-auto-reload-celery-workers-in-development.html
77
"""
88

9+
import os
910
import shlex
1011
import subprocess
1112

1213
from django.core.management.base import BaseCommand
1314
from django.utils import autoreload
1415

1516

16-
def restart_celery():
17-
cmd = "pkill -9 celery"
17+
def restart_celery(queue=None, concurrency=None):
18+
cmd = 'pkill -9 celery'
1819
subprocess.call(shlex.split(cmd))
19-
cmd = "celery worker --app=backend.celery_app:app --loglevel=info --concurrency=2 --max-memory-per-child=150000" # noqa
20+
cmd = f"celery worker --app=backend.celery_app:app --loglevel=info -Q {queue} -n worker-{queue}@%h --concurrency={os.environ.get('CONCURRENT_WORKERS', 2)} --max-memory-per-child=150000" # noqa
2021
subprocess.call(shlex.split(cmd))
2122

2223

2324
class Command(BaseCommand):
25+
def add_arguments(self, parser):
26+
parser.add_argument(
27+
'-q', '--queue', nargs=1, default='celery', type=str
28+
)
29+
parser.add_argument('-c', '--concurrency', type=str)
30+
2431
def handle(self, *args, **options):
25-
print("Starting celery worker with autoreload...")
26-
autoreload.run_with_reloader(restart_celery)
32+
queue = options['queue'][0]
33+
concurrency = options['concurrency'] or 1
34+
print('Starting celery worker with autoreload...')
35+
autoreload.run_with_reloader(
36+
restart_celery, queue=queue, concurrency=concurrency
37+
)

backend/apps/core/tasks.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ class BaseTask(celery.Task):
1515
@task(bind=True, base=BaseTask)
1616
def debug_task(self):
1717
time.sleep(10)
18-
print("Task is done")
1918

2019

2120
@periodic_task(
@@ -30,9 +29,15 @@ def debug_periodic_task():
3029
@task(bind=True, base=BaseTask)
3130
def send_test_email_task(self):
3231
send_mail(
33-
"Subject here",
34-
"Here is the message.",
32+
"Email subject",
33+
"Email message.",
3534
"from@example.com",
3635
["to@example.com"],
3736
fail_silently=False,
3837
)
38+
39+
40+
@task(bind=True, base=BaseTask)
41+
def sleep_task(self, seconds):
42+
time.sleep(int(seconds))
43+
return f"Slept {seconds} seconds"

backend/apps/core/urls.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
from . import views
44

55
urlpatterns = [
6-
path("", views.home, name="home"),
7-
path("hello-world", views.hello_world, name="hello-world"),
8-
path("debug-task/", views.debug_task_view, name="debug-task",),
6+
path("health-check/", views.health_check, name="health-check"),
7+
path("celery/sleep-task/", views.sleep_task_view, name="sleep-task"),
98
path(
109
"debug/send-test-email/",
1110
views.send_test_email,

0 commit comments

Comments
 (0)