Compare commits

...

40 Commits

Author SHA1 Message Date
b6b04ed37a Update .deploy/deploy-prod.yaml
All checks were successful
Deploy Dev / Build (pull_request) Successful in 36s
Deploy Dev / Push (pull_request) Successful in 19s
Deploy Dev / Deploy dev (pull_request) Successful in 8s
2025-09-14 10:22:19 +03:00
b2857d68c1 Update .deploy/deploy-dev.yaml 2025-09-14 10:22:03 +03:00
Egor Matveev
047223ec31 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 11s
Deploy Dev / Push (pull_request) Successful in 31s
Deploy Dev / Deploy dev (pull_request) Successful in 12s
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-29 13:28:36 +03:00
Egor Matveev
d4dc42451b fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 6s
2024-12-29 13:20:14 +03:00
Egor Matveev
afeb1e2dcd fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 7s
Deploy Prod / Push (pull_request) Successful in 8s
Deploy Prod / Deploy prod (pull_request) Successful in 8s
2024-12-29 10:09:42 +03:00
Egor Matveev
a3c438af80 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 32s
Deploy Prod / Push (pull_request) Successful in 17s
Deploy Prod / Deploy prod (pull_request) Successful in 8s
2024-12-29 01:56:10 +03:00
Egor Matveev
c3a982fbd8 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 8s
2024-12-29 01:45:48 +03:00
Egor Matveev
1d85544321 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-29 01:20:51 +03:00
Egor Matveev
581350d633 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-29 01:18:48 +03:00
Egor Matveev
a9f09c953d fix 2024-12-29 00:54:22 +03:00
Egor Matveev
47c5257eef fix 2024-12-29 00:52:49 +03:00
Egor Matveev
be8a5d5ad1 fix 2024-12-28 22:56:35 +03:00
Egor Matveev
6c6a549aff fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 9s
Deploy Prod / Push (pull_request) Successful in 12s
Deploy Prod / Deploy prod (pull_request) Successful in 10s
2024-12-28 22:48:16 +03:00
Egor Matveev
c1249bfcd0 fix 2024-12-28 22:47:13 +03:00
Egor Matveev
30b587e564 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 10s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-28 15:53:27 +03:00
Egor Matveev
2ddd88337e fix
All checks were successful
Deploy Prod / Push (pull_request) Successful in 8s
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-28 15:41:23 +03:00
Egor Matveev
4236d3a7cf fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 15s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 27s
2024-12-28 15:33:18 +03:00
Egor Matveev
789a3298e5 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 16s
Deploy Prod / Deploy prod (pull_request) Successful in 8s
2024-12-28 14:37:11 +03:00
Egor Matveev
60e13b11ec remote
All checks were successful
Deploy Prod / Build (pull_request) Successful in 8s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 8s
2024-12-28 14:26:44 +03:00
Egor Matveev
104ac7377c fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 23s
Deploy Prod / Deploy prod (pull_request) Successful in 23s
2024-12-28 14:08:40 +03:00
Egor Matveev
8c238e7023 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 7s
Deploy Prod / Push (pull_request) Successful in 9s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-12-28 13:56:42 +03:00
Egor Matveev
2da584cca9 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 9s
Deploy Prod / Push (pull_request) Successful in 8s
Deploy Prod / Deploy prod (pull_request) Successful in 11s
2024-12-28 13:46:01 +03:00
Egor Matveev
8ee3573d9a fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 18s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 20s
2024-12-28 13:37:07 +03:00
Egor Matveev
9dfc115224 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 34s
Deploy Dev / Push (pull_request) Successful in 13s
Deploy Dev / Deploy dev (pull_request) Successful in 11s
2024-12-28 13:19:46 +03:00
68ded8537a fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 44s
Deploy Dev / Push (pull_request) Successful in 13s
Deploy Dev / Deploy dev (pull_request) Successful in 7s
2024-12-01 02:05:52 +03:00
739d2366e5 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 5s
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 5s
2024-11-27 02:51:31 +03:00
a55baa613c fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 6s
2024-11-27 02:48:30 +03:00
acfbb98e31 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 7s
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-11-27 02:11:24 +03:00
f35115d2f2 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 7s
2024-11-27 02:08:05 +03:00
2ff6c22e0b fix 2024-11-25 01:00:51 +03:00
11c3026738 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 6s
2024-11-25 00:49:29 +03:00
5efc884f12 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 6s
2024-11-25 00:33:13 +03:00
a328d6feb2 redis
All checks were successful
Deploy Dev / Build (pull_request) Successful in 6s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 5s
2024-11-25 00:27:40 +03:00
be7bc1ef2c update
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 11s
Deploy Dev / Deploy dev (pull_request) Successful in 9s
2024-11-23 22:20:12 +03:00
2dd497c8e2 fix
All checks were successful
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-11-22 01:56:40 +03:00
4fb1043a63 fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 7s
Deploy Prod / Build (pull_request) Successful in 5s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 9s
2024-11-22 01:00:40 +03:00
6d6622b825 net 2024-11-22 00:43:00 +03:00
b19f4532ff fix
All checks were successful
Deploy Dev / Build (pull_request) Successful in 1m15s
Deploy Dev / Push (pull_request) Successful in 13s
Deploy Dev / Deploy dev (pull_request) Successful in 7s
Deploy Prod / Build (pull_request) Successful in 6s
Deploy Prod / Push (pull_request) Successful in 7s
Deploy Prod / Deploy prod (pull_request) Successful in 7s
2024-11-17 12:08:53 +03:00
2bd7f7ea81 up
All checks were successful
Deploy Dev / Build (pull_request) Successful in 4s
Deploy Dev / Push (pull_request) Successful in 7s
Deploy Dev / Deploy dev (pull_request) Successful in 6s
2024-11-17 02:36:46 +03:00
2adedd9e6f up
All checks were successful
Deploy Dev / Build (pull_request) Successful in 5s
Deploy Dev / Push (pull_request) Successful in 8s
Deploy Dev / Deploy dev (pull_request) Successful in 6s
2024-11-17 02:35:13 +03:00
10 changed files with 61 additions and 38 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -2,14 +2,14 @@ version: "3.4"
services: services:
queues-nginx: queues:
image: mathwave/sprint-repo:queues image: mathwave/sprint-repo:queues
networks: networks:
- common-infra-nginx - queues-development
environment: environment:
MONGO_HOST: "mongo.develop.sprinthub.ru" MONGO_HOST: "mongo.dev.chocomarsh.com"
MONGO_PASSWORD: $MONGO_PASSWORD_DEV MONGO_PASSWORD: $MONGO_PASSWORD_DEV
QUEUES_TOKEN: $QUEUES_TOKEN_DEV STAGE: "development"
deploy: deploy:
mode: replicated mode: replicated
restart_policy: restart_policy:
@@ -19,5 +19,5 @@ services:
order: start-first order: start-first
networks: networks:
common-infra-nginx: queues-development:
external: true external: true

View File

@@ -2,14 +2,14 @@ version: "3.4"
services: services:
queues-nginx: queues:
image: mathwave/sprint-repo:queues image: mathwave/sprint-repo:queues
networks: networks:
- common-infra-nginx - queues
environment: environment:
MONGO_HOST: "mongo.sprinthub.ru" MONGO_HOST: "mongo.chocomarsh.com"
MONGO_PASSWORD: $MONGO_PASSWORD_PROD MONGO_PASSWORD: $MONGO_PASSWORD_PROD
QUEUES_TOKEN: $QUEUES_TOKEN_PROD STAGE: "production"
deploy: deploy:
mode: replicated mode: replicated
restart_policy: restart_policy:
@@ -19,5 +19,5 @@ services:
order: start-first order: start-first
networks: networks:
common-infra-nginx: queues:
external: true external: true

View File

@@ -28,7 +28,7 @@ jobs:
run: docker push mathwave/sprint-repo:queues run: docker push mathwave/sprint-repo:queues
deploy-dev: deploy-dev:
name: Deploy dev name: Deploy dev
runs-on: [dev] runs-on: [prod]
needs: push needs: push
steps: steps:
- name: login - name: login
@@ -40,5 +40,4 @@ jobs:
- name: deploy - name: deploy
env: env:
MONGO_PASSWORD_DEV: ${{ secrets.MONGO_PASSWORD_DEV }} MONGO_PASSWORD_DEV: ${{ secrets.MONGO_PASSWORD_DEV }}
QUEUES_TOKEN_DEV: ${{ secrets.QUEUES_TOKEN_DEV }} run: docker stack deploy --with-registry-auth -c ./.deploy/deploy-dev.yaml infra-development
run: docker stack deploy --with-registry-auth -c ./.deploy/deploy-dev.yaml infra

View File

@@ -40,5 +40,4 @@ jobs:
- name: deploy - name: deploy
env: env:
MONGO_PASSWORD_PROD: ${{ secrets.MONGO_PASSWORD_PROD }} MONGO_PASSWORD_PROD: ${{ secrets.MONGO_PASSWORD_PROD }}
QUEUES_TOKEN_PROD: ${{ secrets.QUEUES_TOKEN_PROD }}
run: docker stack deploy --with-registry-auth -c ./.deploy/deploy-prod.yaml infra run: docker stack deploy --with-registry-auth -c ./.deploy/deploy-prod.yaml infra

View File

@@ -1,4 +1,4 @@
FROM python:3.10 FROM python:3.12
RUN mkdir /usr/src/app RUN mkdir /usr/src/app
WORKDIR /usr/src/app WORKDIR /usr/src/app
@@ -8,4 +8,6 @@ RUN pip install -r requirements.txt
COPY . . COPY . .
ENV PYTHONUNBUFFERED=1
ENTRYPOINT ["python", "main.py"] ENTRYPOINT ["python", "main.py"]

View File

@@ -1,3 +1,5 @@
import asyncio
import collections
import fastapi import fastapi
import pydantic import pydantic
import typing import typing
@@ -5,18 +7,24 @@ import typing
from app.storage.mongo import tasks from app.storage.mongo import tasks
locks = collections.defaultdict(asyncio.Lock)
router = fastapi.APIRouter() router = fastapi.APIRouter()
class Response(pydantic.BaseModel): class Task(pydantic.BaseModel):
id: str id: str
attempt: int attempt: int
payload: dict payload: dict
class Response(pydantic.BaseModel):
task: Task|None
@router.get('/api/v1/take', responses={404: {'description': 'Not found'}}) @router.get('/api/v1/take', responses={404: {'description': 'Not found'}})
async def execute(queue: typing.Annotated[str, fastapi.Header()]) -> Response: async def execute(queue: typing.Annotated[str, fastapi.Header()]) -> Response:
async with locks[queue]:
task = await tasks.take_task(queue) task = await tasks.take_task(queue)
if not task: if not task:
raise fastapi.HTTPException(404) return Response(task=None)
return Response(id=str(task._id), attempt=task.attempts, payload=task.payload) return Response(task=Task(id=str(task._id), attempt=task.attempts, payload=task.payload))

View File

@@ -1,8 +1,6 @@
import asyncio
import bson import bson
import datetime import datetime
import pydantic import pydantic
import typing
from app.storage.mongo import database from app.storage.mongo import database
from app.utils import time from app.utils import time
@@ -28,7 +26,7 @@ async def add_task(task: Task) -> str:
return result.inserted_id return result.inserted_id
async def take_task(queue: str) -> typing.Optional[Task]: async def take_task(queue: str) -> Task|None:
now = time.now() now = time.now()
async for raw_task in collection.find({'queue': queue, 'available_from': {'$lte': now}}): async for raw_task in collection.find({'queue': queue, 'available_from': {'$lte': now}}):
task = Task.model_validate(raw_task) task = Task.model_validate(raw_task)

25
main.py
View File

@@ -1,6 +1,5 @@
import fastapi import fastapi
import uvicorn import uvicorn
import os
from app.routers import take from app.routers import take
from app.routers import put from app.routers import put
@@ -9,26 +8,20 @@ from app.routers import finish
from app.storage import mongo from app.storage import mongo
QUEUES_TOKEN = os.getenv('QUEUES_TOKEN') app = fastapi.FastAPI(debug=True)
app = fastapi.FastAPI()
@app.middleware('http')
async def check_token(request: fastapi.Request, call_next):
if QUEUES_TOKEN:
token = request.headers.get('X-Queues-Token')
if not token or token != QUEUES_TOKEN:
raise fastapi.HTTPException(403)
return await call_next(request)
app.include_router(take.router) app.include_router(take.router)
app.include_router(put.router) app.include_router(put.router)
app.include_router(finish.router) app.include_router(finish.router)
@app.exception_handler(Exception)
async def unicorn_exception_handler(request: fastapi.Request, exc: Exception):
return fastapi.JSONResponse(
status_code=500,
content={"message": f"Oops! {exc.name} did something. There goes a rainbow... {exc}"},
)
mongo.create_indexes() mongo.create_indexes()
if __name__ == '__main__': if __name__ == '__main__':
uvicorn.run(app, host="0.0.0.0", port=1238) uvicorn.run(app, host="0.0.0.0", port=1239)

View File

@@ -1,20 +1,44 @@
annotated-types==0.7.0 annotated-types==0.7.0
anyio==4.6.2.post1 anyio==4.6.2.post1
APScheduler==3.10.4 APScheduler==3.10.4
certifi==2024.12.14
charset-normalizer==3.4.1
click==8.1.7 click==8.1.7
dnspython==2.7.0 dnspython==2.7.0
email_validator==2.2.0
fastapi==0.115.4 fastapi==0.115.4
fastapi-cli==0.0.7
h11==0.14.0 h11==0.14.0
httpcore==1.0.7
httptools==0.6.4
httpx==0.28.1
idna==3.10 idna==3.10
Jinja2==3.1.5
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mdurl==0.1.2
motor==3.6.0 motor==3.6.0
pydantic==2.9.2 pydantic==2.9.2
pydantic_core==2.23.4 pydantic_core==2.23.4
Pygments==2.18.0
pymongo==4.9.2 pymongo==4.9.2
python-dotenv==1.0.1
python-multipart==0.0.20
pytz==2024.2 pytz==2024.2
PyYAML==6.0.2
redis==5.2.0 redis==5.2.0
requests==2.32.3
rich==13.9.4
rich-toolkit==0.12.0
shellingham==1.5.4
six==1.16.0 six==1.16.0
sniffio==1.3.1 sniffio==1.3.1
starlette==0.41.2 starlette==0.41.2
typer==0.15.1
typing_extensions==4.12.2 typing_extensions==4.12.2
tzlocal==5.2 tzlocal==5.2
urllib3==2.3.0
uvicorn==0.32.0 uvicorn==0.32.0
uvloop==0.21.0
watchfiles==1.0.3
websockets==14.1