Skip to content

Commit 1c398be

Browse files
authored
Merge pull request #43 from codeguru42/35-worker-queue
35 worker queue
2 parents 5986983 + 23ddcb8 commit 1c398be

12 files changed

+383
-19
lines changed

docker-compose-dev.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
services:
2+
api:
3+
build: .
4+
command: "poetry run python3 /api/manage.py runserver 0.0.0.0:8000"
5+
env_file:
6+
- .env
7+
environment:
8+
- CELERY_BROKER_URL=amqp://guest:guest@broker:5672
9+
ports:
10+
- 8000:8000
11+
volumes:
12+
- .:/api
13+
worker:
14+
build: .
15+
command: "poetry run celery -A go_capture.tasks worker"
16+
depends_on:
17+
- broker
18+
environment:
19+
- CELERY_BROKER_URL=amqp://guest:guest@broker:5672
20+
- CELERY_RESULT_BACKEND=rpc
21+
env_file:
22+
- .env
23+
volumes:
24+
- .:/api
25+
broker:
26+
image: rabbitmq:3-management
27+
ports:
28+
- 5672:5672
29+
- 15672:15672

docker-compose-prod.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
services:
2+
api:
3+
image: ${account_id}.dkr.ecr.us-west-1.amazonaws.com/go-capture:${image_hash}
4+
env_file:
5+
- .env
6+
environment:
7+
- CELERY_BROKER_URL=amqp://guest:guest@broker:5672
8+
ports:
9+
- 8000:8000
10+
worker:
11+
image: ${account_id}.dkr.ecr.us-west-1.amazonaws.com/go-capture:${image_hash}
12+
command: "poetry run celery -A go_capture.tasks worker"
13+
depends_on:
14+
- broker
15+
environment:
16+
- CELERY_BROKER_URL=amqp://guest:guest@broker:5672
17+
- CELERY_RESULT_BACKEND=rpc
18+
env_file:
19+
- .env
20+
broker:
21+
image: rabbitmq:3-management
22+
ports:
23+
- 5672:5672
24+
- 15672:15672

docker-compose.yml

Lines changed: 0 additions & 7 deletions
This file was deleted.

go_capture/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .tasks import app as celery_app
2+
3+
__all__ = ('celery_app',)

go_capture/settings.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,9 @@
123123
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
124124

125125
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
126+
127+
IMAGES_DIR = BASE_DIR / 'images'
128+
IMAGES_DIR.mkdir(exist_ok=True)
129+
130+
SGF_DIR = BASE_DIR / 'sgf'
131+
SGF_DIR.mkdir(exist_ok=True)

go_capture/sgf/process_image.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import cv2
2+
import numpy as np
3+
4+
from go_capture.sgf import perspective, find_stones
5+
from go_capture.sgf.make_sgf import make_sgf
6+
7+
8+
def process_image(image_file, output_file):
9+
image_data = np.asarray(bytearray(image_file.read()), dtype="uint8")
10+
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
11+
board = perspective.get_grid(image)
12+
black, white = find_stones.find_stones(board)
13+
make_sgf(output_file, black, white)

go_capture/tasks.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import os
2+
from pathlib import Path
3+
4+
from celery import Celery
5+
from django.conf import settings
6+
7+
from go_capture.sgf.process_image import process_image
8+
9+
# Set the default Django settings module for the 'celery' program.
10+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'go_capture.settings')
11+
12+
app = Celery('go_capture')
13+
14+
# Using a string here means the worker doesn't have to serialize
15+
# the configuration object to child processes.
16+
# - namespace='CELERY' means all celery-related configuration keys
17+
# should have a `CELERY_` prefix.
18+
app.config_from_object('django.conf:settings', namespace='CELERY')
19+
20+
# Load task modules from all registered Django apps.
21+
app.autodiscover_tasks()
22+
23+
24+
@app.task(bind=True)
25+
def debug_task(self):
26+
print(f'Request: {self.request!r}')
27+
28+
29+
@app.task
30+
def process_image_task(image_filename):
31+
sgf_filename = f'{Path(image_filename).stem}.sgf'
32+
sgf_path = settings.SGF_DIR / sgf_filename
33+
with open(image_filename, 'rb') as image_file:
34+
with open(sgf_path, 'w') as sgf_file:
35+
process_image(image_file, sgf_file)

go_capture/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@
2121
urlpatterns = [
2222
path('admin/', admin.site.urls),
2323
path('capture/', views.capture),
24+
path('capture_async/', views.capture_async),
2425
path('health_check/', views.health_check),
2526
]

go_capture/views.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
import io
22
from pathlib import Path
33

4-
import cv2
5-
import numpy as np
6-
from django.http import FileResponse, JsonResponse
4+
from django.conf import settings
5+
from django.http import JsonResponse, HttpResponse, FileResponse
76
from django.views.decorators.http import require_POST, require_GET
87

9-
from go_capture.sgf import perspective, find_stones
10-
from go_capture.sgf.make_sgf import make_sgf
8+
from go_capture.sgf.process_image import process_image
9+
from go_capture.tasks import process_image_task
1110

1211

1312
@require_POST
1413
def capture(request):
1514
image_file = request.FILES['image']
16-
image_data = np.asarray(bytearray(image_file.read()), dtype="uint8")
17-
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
18-
board = perspective.get_grid(image)
19-
black, white = find_stones.find_stones(board)
2015
output_file = io.StringIO()
21-
make_sgf(output_file, black, white)
16+
process_image(image_file, output_file)
2217
output_file.seek(0)
2318
filename = Path(image_file.name).stem
2419
return FileResponse(
@@ -30,6 +25,17 @@ def capture(request):
3025
)
3126

3227

28+
@require_POST
29+
def capture_async(request):
30+
image_file = request.FILES['image']
31+
filename = Path(image_file.name)
32+
output_path = settings.IMAGES_DIR / filename
33+
with output_path.open('wb') as output_file:
34+
output_file.write(image_file.read())
35+
process_image_task.delay(str(output_path.absolute()))
36+
return HttpResponse(status=201)
37+
38+
3339
@require_GET
3440
def health_check(request):
3541
body = {

0 commit comments

Comments
 (0)