рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА, рднрд╛рдЧ 6: рдлреНрд▓рд╛рд╕реНрдХ рдФрд░ рдЕрдЬрд╡рд╛рдЗрди / рдЦрд░рдЧреЛрд╢

рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА: рд╕рд╛рдордЧреНрд░реА рдЪрдХреНрд░

рдЖрдЗрдП Celery / RabbitMQ рдХреЛ рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдлреНрд▓рд╛рд╕реНрдХ рдХреЗ рд╕рд╛рде рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд▓реЗрдВред рдЕрдЬрд╡рд╛рдЗрди рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдЧрдгрдирд╛ рдХрд░реЗрдЧрд╛ред


рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реНрдерд╛рдкрдирд╛

рд╣рдо рдЖрдкрдХреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреНрд▓реЛрди рдХрд░рддреЗ рд╣реИрдВ:


git clone https://github.com/nomhoi/tic-tac-toe-part6.git 

рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ:


 cd tic-tac-toe-part6 docker-compose up -d 

рд╣рдо рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рд╣реИрдВ:


 cd front npm install npm run-script build 

рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ http: // localhost рдкрд░ рдЦреЛрд▓реЗрдВред


рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░

рдиреЗрдЧрдиреЗрдХреНрд╕ рд╕реЗрд╡рд╛ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдмрдиреА рд╣реБрдИ рд╣реИред рдлреНрд▓рд╛рд╕реНрдХ рд╕реЗрд╡рд╛ рдореЗрдВ, рдЙрдиреНрд╣реЛрдВрдиреЗ рд╕реЗрд▓реЗрд░реА рдкреИрдХреЗрдЬ рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝рд╛ред рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕реЗрд▓реЗрд░реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реНрд░реЛрдд рдХреЗ рд╕рд╛рде рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд░рдЦрд╛:


  volumes: - ./flask:/code - ./celery/app/proj:/code/proj 

рдирдИ рдЕрдЬрд╡рд╛рдЗрди рдФрд░ рдЦрд░рдЧреЛрд╢ рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИ ред


  celery: container_name: celery build: context: celery/ dockerfile: Dockerfile volumes: - ./celery/app:/app depends_on: - rabbit networks: - backend rabbit: container_name: rabbit hostname: rabbit image: rabbitmq:3.7.15-alpine environment: - RABBITMQ_DEFAULT_USER=admin - RABBITMQ_DEFAULT_PASS=CT2gNABH8eJ9yVh ports: - "5672:5672" networks: - backend 

рдЕрдЬрд╡рд╛рдЗрди рдХреА рд╕реЗрд╡рд╛

рдЕрдЬрд╡рд╛рдЗрди рд╕реЗрд╡рд╛ рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рдЬреЛ рд▓реЛрдЧ рдЕрдЬрд╡рд╛рдЗрди рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рдпрд╣ рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдпрд╣рд╛рдБ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ:


 $ docker exec -it celery python Python 3.7.3 (default, May 11 2019, 02:00:41) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from proj.tasks import add >>> add.delay(2, 2) <AsyncResult: 43662174-657f-4dd3-ab1a-22f5950c8794> >>> 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╕реЗрд▓реЗрд░реА рдореЗрдВ рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдПрдХ рдкреНрд░реЛрдЬ рдкреИрдХреЗрдЬ рдХреЗ рд░реВрдк рдореЗрдВ рддреИрдпрд╛рд░ рдХреА рдЧрдИ рд╣реИред рд╕реЗрд▓реЗрд░реА рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ, рд╣рдорд╛рд░реЗ getnumber рдХрд╛рд░реНрдп рдХреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ :


 @app.task def getnumber(): return randrange(9) 

рдлреНрд▓рд╛рд╕реНрдХ рд╕реЗрд╡рд╛

рдореБрдЭреЗ рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рдирд╛ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдЗрд╕ рд╕реЗрд╡рд╛ рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдкреИрдХреЗрдЬ рдЬреЛрдбрд╝рд╛ рдФрд░ рдкреНрд░реЙрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдорд╛рдЙрдВрдЯ рдХрд┐рдпрд╛ред рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЕрдм рджреЛ рд╕реЗрд╡рд╛рдУрдВ, рдлреНрд▓рд╛рд╕реНрдХ рдФрд░ рдЕрдЬрд╡рд╛рдЗрди рдореЗрдВ рдореМрдЬреВрдж рд╣реИ ред


 from flask import Flask, jsonify from proj.tasks import getnumber from proj.celery import app as celery app = Flask(__name__) @app.route('/number') def number(): task = getnumber.delay() return task.id @app.route('/result/<task_id>') def result(task_id): task = getnumber.AsyncResult(task_id) result = task.get(timeout = 3) response = { 'state': task.state, 'number': result, } return jsonify(response) 

рдирдВрдмрд░ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ, рд╣рдо рдЧреЗрдЯрдирд░реА рдХрд╛рд░реНрдп рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИ , рдФрд░ рдХрд╛рд░реНрдп рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдореА рд╣реИрдВрдбрд▓рд░ рдореЗрдВ, рд╣рдо рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдкреВрд░реНрдг рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдп рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдлреНрд░рдВрдЯ рдПрдВрдб JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред


рджреГрд╢реНрдпрдкрдЯрд▓

рд╣рдорд╛рд░реЗ рдЧреЗрдо рдХреЗ рдкреНрд░рдмрдВрдзрдХ рдореЗрдВ, рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ, рд╣рдо рдкрд╣рд▓реЗ рдкрддреЗ / рдирдВрдмрд░ рдкрд░ рдмреИрдХрдПрдВрдб рдкрд░ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдореЗрдВ рд╕реЗрд▓реЗрд░реА рдЯрд╛рд╕реНрдХ рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, getResult рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдо рд╕рдордп-рд╕рдордп рдкрд░ рдкрддреЗ / рдкрд░рд┐рдгрд╛рдо / <task_id> рдкрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмреИрдХрдПрдВрдб рдкрд░ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреЗ рд╣реИрдВред


 async function getResult(task_id) { var i = 1; var timerId = setTimeout(async function go() { console.log("Result request: " + i); console.log("Task Id: " + task_id) const res = await fetch(`result/` + task_id); const response = await res.text(); if (res.ok) { let result = JSON.parse(response); console.log(result) if (result.state === 'SUCCESS') { let i = parseInt(result.number); if ($status === 1 || $history.state.squares[i]) { promise_number = result.number + ' - busy'; return; } promise_number = i; history.push(new Command($history.state, i)); return; } } if (i < 5) setTimeout(go, 500); i++; }, 500); } 

рдмреИрдХрдПрдВрдб рдХреЗ рд▓рд┐рдП рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдкрд░рд┐рд╡рд░реНрддрди


 {#await promise} <p>...</p> {:then taskid} <p>Task Id: {taskid}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} {#await promise_number} <p>...</p> {:then number} <p>Number: {number}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} 

рдШрд░ рдХрд╛ рдкрд╛рда

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдм рдкрд░рд┐рдгрд╛рдо рдкрд╣рд▓реЗ рдЕрдиреБрд░реЛрдз рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдЖрддрд╛ рд╣реИред рдЕрдЬрд╡рд╛рдЗрди рдореЗрдВ рд░рд╣рдиреЗ рд╡рд╛рд▓реЗ рд╣рдорд╛рд░реЗ рдмреБрджреНрдзрд┐рдорд╛рди рдПрдЬреЗрдВрдЯ рдХреЛ рдереЛрдбрд╝рд╛ рд╡рд┐рдЪрд╛рд░рд╢реАрд▓ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ, рддрд╛рдХрд┐ рддреБрд░рдВрдд рдЬрд╡рд╛рдм рди рджреЗрдВред


рд╕рдордп-рд╕рдордп рдкрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреНрд▓рд╛рд╕реНрдХ 'рдП' 500 (рдЗрдВрдЯрд░рдирд▓ рд╕реАрд░рд┐рдпрд╕ рдПрд░рд░) рд╕реЗ рдЖрдиреЗ рд▓рдЧрддреА рд╣реИ, рдпрд╣ рдЕрдкрд╡рд╛рдж "celery.exception.TimeoutError: рдЙрдард╛рддрд╛ рд╣реИ: рдСрдкрд░реЗрд╢рди рд╕рдордп рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ред" рдЕрдЬрд╡рд╛рдЗрди рдореЗрдВ ред рдХреЗрд╡рд▓ рд░реАрдмреВрдЯрд┐рдВрдЧ рд╕реЗрд╡рд╛рдПрдБ рдорджрдж рдХрд░рддреА рд╣реИрдВред рдЦреБрджрд╛рдИ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реБрдП рдХреНрдпрд╛ рдмрд╛рдд рд╣реИ, рдХреГрдкрдпрд╛ рджреЗрдЦреЗрдВред


GetResult рдХреЗрд╡рд▓ SUCCESS рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдПрдХ рджреВрд╕рд░рд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк FAILURE рдФрд░ PENDING рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдо рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЧрдарди рдХрд╛рд░реНрдп рдХреА рд╕реНрдерд┐рддрд┐ рдкрд░ рднреА рдирд┐рд░реНрднрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред


RabbitMQ рд╕рдВрджреЗрд╢ рдмреНрд░реЛрдХрд░ рдХреЗ рдмрдЬрд╛рдп, рдЖрдк Redis рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдЖрдк рд╕рдВрджреЗрд╢ рджрд▓рд╛рд▓реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрд╡реЗрджрди рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдФрд░ рдЗрд╕реЗ Boost.Beast рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд░рдиреЗ рдХрд╛ рднреА рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред


рдЧрд┐рдЯрд╣рдм рднрдВрдбрд╛рд░

https://github.com/nomhoi/tic-tac-toe-part6

Source: https://habr.com/ru/post/hi461531/


All Articles