Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
commit 26e3ba807e6bb807dd0f06c4a6b821ba8bb91fb3 Author: Adam Samalik asamalik@redhat.com Date: Mon Jul 21 12:46:20 2014 +0200
FrontendCallback prettified
backend/backend/actions.py | 2 +- backend/backend/callback.py | 93 ++++++++++++-------- backend/backend/dispatcher.py | 58 ++++++------- .../coprs/views/backend_ns/backend_general.py | 6 +- 4 files changed, 86 insertions(+), 73 deletions(-)
diff --git a/backend/backend/actions.py b/backend/backend/actions.py index 0600723..19e0270 100644 --- a/backend/backend/actions.py +++ b/backend/backend/actions.py @@ -118,4 +118,4 @@ class Action(object): self.event("Action legal-flag: ignoring")
if "result" in result: - self.frontend_callback.post_to_frontend({"actions": [result]}) + self.frontend_callback.update({"actions": [result]}) diff --git a/backend/backend/callback.py b/backend/backend/callback.py index d2312fe..937cd3e 100644 --- a/backend/backend/callback.py +++ b/backend/backend/callback.py @@ -1,62 +1,81 @@ import json import requests +from functools import wraps +import time
class FrontendCallback(object): + """ + Object to send data back to fronted + """
- """ Object to send data back to fronted """ - - def __init__(self, opts): + def __init__(self, opts, log=None): super(FrontendCallback, self).__init__() self.frontend_url = opts.frontend_url self.frontend_auth = opts.frontend_auth + self.log = log self.msg = None
- def post_to_frontend(self, data): - """ Send data to frontend """ - - headers = {"content-type": "application/json"} - url = "{0}/update/".format(self.frontend_url) - auth = ("user", self.frontend_auth) - - self.msg = None - try: - r = requests.post(url, data=json.dumps(data), auth=auth, - headers=headers) - if r.status_code != 200: - self.msg = "Failed to submit to frontend: {0}: {1}".format( - r.status_code, r.text) - - except requests.RequestException, e: - self.msg = "Post request failed: {0}".format(e) - - if self.msg: - return False - else: - return True -
- def build_starting(self, data): + def _post_to_frontend(self, data, url_path): + """ + Make a request to the frontend + """ headers = {"content-type": "application/json"} - url = "{0}/starting_build/".format(self.frontend_url) + url = "{0}/{1}/".format(self.frontend_url, url_path) auth = ("user", self.frontend_auth)
self.msg = None - r = None + response = None try: - r = requests.post(url, data=json.dumps(data), auth=auth, + response = requests.post(url, data=json.dumps(data), auth=auth, headers=headers) - if r.status_code != 200 or "canceled" not in r.json(): + if response.status_code != 200: self.msg = "Failed to submit to frontend: {0}: {1}".format( - r.status_code, r.text) + response.status_code, response.text) raise requests.RequestException(self.msg) - except requests.RequestException, e: self.msg = "Post request failed: {0}".format(e) raise - - return r.json()["canceled"] - - + return response + + + def _post_to_frontend_repeatedly(self, data, url_path, max_repeats=10): + """ + Make a request max_repeats-time to the frontend + """ + repeats = 0 + while repeats <= max_repeats: + try: + response = self._post_to_frontend(data, url_path) + break + except requests.RequestException: + if self.log: + self.log(self.msg) + if repeats == max_repeats: + raise + repeats += 1 + time.sleep(5) + return response + + + def update(self, data): + """ + Send data to be updated in the frontend + """ + self._post_to_frontend_repeatedly(data, "update") + + + def starting_build(self, build_id, chroot_name): + """ + Announce to the frontend that a build is starting. + Return: True if the build can start + False if the build can not start (can be cancelled or deleted) + """ + data = {"build_id": build_id, "chroot": chroot_name} + response = self._post_to_frontend_repeatedly(data, "starting_build") + if "can_start" not in response.json(): + raise requests.RequestException("Bad respond from the frontend") + return response.json()["can_start"]
diff --git a/backend/backend/dispatcher.py b/backend/backend/dispatcher.py index 310070b..04082d2 100644 --- a/backend/backend/dispatcher.py +++ b/backend/backend/dispatcher.py @@ -7,7 +7,6 @@ import Queue import json import subprocess import multiprocessing -import requests
import ansible import ansible.utils @@ -364,23 +363,11 @@ class Worker(multiprocessing.Process):
return jobdata
- # maybe we move this to the callback? - def post_to_frontend(self, data): - """send data to frontend""" - i = 10 - while i > 0: - result = self.frontend_callback.post_to_frontend(data) - if not result: - self.callback.log(self.frontend_callback.msg) - i -= 1 - time.sleep(5) - else: - i = 0 - return result
- # maybe we move this to the callback? def mark_started(self, job): - + """ + Send data about started build to the frontend + """ build = {"id": job.build_id, "started_on": job.started_on, "results": job.results, @@ -389,13 +376,17 @@ class Worker(multiprocessing.Process): } data = {"builds": [build]}
- if not self.post_to_frontend(data): + try: + self.frontend_callback.update(data) + except: raise errors.CoprWorkerError( "Could not communicate to front end to submit status info")
- # maybe we move this to the callback? - def return_results(self, job):
+ def return_results(self, job): + """ + Send the build results to the frontend + """ self.callback.log( "{0} status {1}. Took {2} seconds".format( job.build_id, job.status, job.ended_on - job.started_on)) @@ -411,28 +402,31 @@ class Worker(multiprocessing.Process):
data = {"builds": [build]}
- if not self.post_to_frontend(data): + try: + self.frontend_callback.update(data) + except: raise errors.CoprWorkerError( "Could not communicate to front end to submit results")
os.unlink(job.jobfile)
- # maybe we move this to the callback? - def build_starting(self, job): - # FIXME very bad name.... - """ Is the build canceled? If not, set it as Starting and return True - """ - data = {"build_id": job.build_id, - "chroot": job.chroot}
- result = None + def starting_build(self, job): + """ + Announce to the frontend that a build is starting. + Return: True if the build can start + False if the build can not start (build is cancelled) + """ + response = None try: - result = self.frontend_callback.build_starting(data) - except requests.RequestException, e: + response = self.frontend_callback.starting_build( + job.build_id, + job.chroot) + except: raise errors.CoprWorkerError( "Could not communicate to front end to submit results")
- return result + return response
def pkg_built_before(self, pkgs, chroot, destdir): @@ -480,7 +474,7 @@ class Worker(multiprocessing.Process):
# Checking whether the build is not cancelled - if self.build_starting(job): + if not self.starting_build(job): continue
diff --git a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py index dd7e8c1..3c1b723 100644 --- a/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py +++ b/frontend/coprs_frontend/coprs/views/backend_ns/backend_general.py @@ -97,17 +97,17 @@ def starting_build(): Check if the build is not cancelled and set it to running state """
- result = {"canceled": True} + result = {"can_start": False}
if "build_id" in flask.request.json and "chroot" in flask.request.json: build = builds_logic.BuildsLogic.get_by_id(flask.request.json["build_id"])
- if build and not build.cancelled: + if build and not build.canceled: builds_logic.BuildsLogic.update_state_from_dict(build, { "chroot": flask.request.json["chroot"], "status": 6}) # starting db.session.commit() - result["canceled"] = False + result["can_start"] = True
return flask.jsonify(result)
copr-commits@lists.fedorahosted.org