def cancel(order_id: ObjectId, user: dict): order = Orders.get(order_id) if order is None: raise errors.NotFound() Orders().cancel(order_id) send_order_failed_email(order_id) return jsonify({"_id": order_id})
def run_periodic_tasks(): logger.info("running periodic tasks !!") # manage auto-images logger.info("managing auto-images") check_autoimages() # timeout orders based on status # orders cant stay in creation for more than 12h # orders in downloading/writing cant be slower than 4Mb/s # now = datetime.datetime.now() # min_bps = int(humanfriendly.parse_size("4MiB") / 8) # for morder in Orders().find( # {"status": {"$in": [Orders().creating, Orders.downloading, Orders.writing]}}, # {"_id": 1}, # ): # order = Orders().get_with_tasks(morder["_id"]) # ls = order["statuses"][-1] # # prepare expired dt based on status # if ls["status"] == Orders().creating: # task = CreatorTasks().get(order["tasks"]["create"]) # elif ls["status"] in (Orders.downloading, Orders.writing): # size = humanfriendly.parse_size(order["config"]["size"]) # expired = now - datetime.timedelta(seconds=int(size / min_bps)) # if ls["status"] == Orders.downloading: # task_cls, task_id = DownloaderTasks, order["tasks"]["download"] # else: # task_cls, task_id = WriterTasks, order["tasks"]["write"] # else: # # last status not in-progress # continue # # compare last update with expiry datetime # if ls["on"] > expired: # continue # # timeout task # task_cls().update_status(task_id=task_id, status=task_cls.timedout) # # timeout order # task_cls().cascade_status(task_id=task_id, status=task_cls.timedout) # # notify failure # send_order_failed_email(order["_id"]) # TODO: forward to task/order mgmt logger.info("timing out expired orders") for task_cls, task in Tasks.all_inprogress(): task_id = task["_id"] ls = task["statuses"][-1] if not is_expired(ls["status"], ls["on"], task_cls.get_size(task_id)): logger.info("skipping non-expired task #{}".format(task_id)) continue logger.info("timing out task #{}".format(task_id)) order = Orders().get_with_tasks(task["order"]) # timeout task task_cls.update_status(task_id=task_id, status=Tasks.timedout) # if write, cancel peers if ls["status"] in (Tasks.wiping_sdcard, Tasks.writing): for peer in order["tasks"]["write"]: if peer["_id"] == task_id: continue task_cls.update_status(task_id=peer["_id"], status=Tasks.canceled) # cascade task_cls.cascade_status(task_id=task_id, task_status=task_cls.timedout) # notify send_order_failed_email(order["_id"]) # TODO: forward to task/order mgmt logger.info("removing expired donwload files") now = datetime.datetime.now() for order in Orders.all_pending_expiry(): ls = order["statuses"][-1] if not ls["status"] == Orders.pending_expiry: continue # wrong timing if not order["sd_card"]["expiration"] < now: continue # expiration not reached logger.info("Order #{} has reach expiration.".format(order["_id"])) Orders().update_status(order["_id"], Orders.expired)
def update_status(task_id: ObjectId, task_type: str, user: dict): task_cls = tasks_cls_for(task_type) task = task_cls().get(task_id) if task is None: raise errors.NotFound() request_json = request.get_json() # try: # request_json = request.get_json() # validate(request_json, Orders().schema) # except ValidationError as error: # raise errors.BadRequest(error.message) # update task status status = request_json.get("status") task_cls.update_status( task_id, status=request_json.get("status"), payload=request_json.get("log"), extra_update=request_json.get("extra"), ) # update order status based on this task task_cls.cascade_status(task_id, request_json.get("status")) # send email if appropriate order_id = task["order"] # create task uploaded image if status == Tasks.uploaded_public: order = Orders().get(order_id) # set expiration date expiration = datetime.datetime.now() + datetime.timedelta( days=order["sd_card"]["duration"]) Orders().update(order_id, {"sd_card.expiration": expiration}) send_image_uploaded_public_email(order_id) elif status == Tasks.uploaded: send_image_uploaded_email(order_id) # create DownloadTask Orders().create_downloader_task( order_id, { "fname": task.get("image", {}).get("fname"), "size": task.get("image", {}).get("size"), "checksum": task.get("image", {}).get("checksum"), }, ) # download task downloaded image elif status == Tasks.downloaded: # create WriterTask(s) Orders().create_writer_tasks(order_id) # write task was registered elif status == Tasks.waiting_for_card: # send email to insert card send_insert_card_email(order_id, task_id) # write task started writing elif status == Tasks.writing: send_image_writing_email(order_id, task_id) # write task completed elif status == Tasks.written: send_image_written_email(order_id, task_id) order = Orders().get_with_tasks(order_id) # all write tasks are marked as written if not [ 1 for wt in order["tasks"]["write"] if wt["status"] != Tasks.written ]: Orders().update_status(order_id, Orders.pending_shipment) send_order_pending_shipment_email(order_id) # find matching download task and mark it for file removal DownloaderTasks().update_status( task_id=order["tasks"]["download"]["_id"], status=Tasks.pending_image_removal, ) elif status in Tasks.FAILED_STATUSES: send_order_failed_email(order_id) return jsonify({"_id": task_id})