예제 #1
0
파일: tasks.py 프로젝트: viraatdas/cardshop
def add_log(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()

    task_cls.update_logs(
        task_id,
        worker_log=request_json.get("worker_log"),
        installer_log=request_json.get("installer_log"),
        uploader_log=request_json.get("uploader_log"),
        downloader_log=request_json.get("downloader_log"),
        wipe_log=request_json.get("wipe_log"),
        writer_log=request_json.get("writer_log"),
    )

    # update ACK
    Acknowlegments.busy_update(
        username=user["username"],
        worker_type=task_type,
        slot=request.args.get("slot"),
        task_id=task_id,
    )

    return jsonify({"_id": task_id})
예제 #2
0
파일: tasks.py 프로젝트: viraatdas/cardshop
def typed_collection(task_type: str, user: dict):
    if request.method == "GET":
        Acknowlegments.idle_update(
            username=user["username"],
            worker_type=task_type,
            slot=request.args.get("slot"),
        )
        tasks = tasks_cls_for(task_type).find_availables(
            channel=user.get("channel"))

        return jsonify(tasks)
예제 #3
0
파일: workers.py 프로젝트: kiwix/cardshop
def sos(user: dict):

    request_json = request.get_json()

    try:
        request_json = request.get_json()
        if "type" not in request_json:
            raise ValidationError("missing worker type")
    except ValidationError as error:
        raise errors.BadRequest(str(error))

    # update ACK
    aid, status_changed = Acknowlegments.sos_update(
        username=user["username"],
        worker_type=request_json.get("type"),
        slot=request.args.get("slot"),
        error=request_json.get("error"),
    )

    print("aid", aid, "changed", status_changed)

    # only email operator once
    if status_changed:
        send_worker_sos_email(aid)

    return jsonify({"_id": aid})
예제 #4
0
파일: tasks.py 프로젝트: viraatdas/cardshop
def register_task(task_id: ObjectId, task_type: str, user: dict):
    task_cls = tasks_cls_for(task_type)
    task = task_cls().find({"_id": task_id, "status": task_cls.pending})
    if task is None:
        raise errors.NotFound()

    task_cls.register(task_id, user)

    # update ACK
    Acknowlegments.busy_update(
        username=user["username"],
        worker_type=task_type,
        slot=request.args.get("slot"),
        task_id=task_id,
    )

    return jsonify({"_id": task_id})
예제 #5
0
def send_worker_sos_email(ack_id):
    # client: image writing successful.
    ack = Acknowlegments.get(ack_id)
    context = {"ack": ack}
    subject = jinja_env.get_template("subject_worker_sos.txt").render(**context)
    content = jinja_env.get_template("operator_worker_sos.html").render(**context)
    send_email(
        to=Users().by_username(ack["username"])["email"],
        subject=subject,
        contents=content,
    )
예제 #6
0
def collection(user: dict):

    skip = request.args.get("skip", default=0, type=int)
    limit = request.args.get("limit", default=20, type=int)
    skip = 0 if skip < 0 else skip
    limit = 20 if limit <= 0 else limit

    cursor = Acknowlegments().find({})
    workers = [user for user in cursor]

    return jsonify({"meta": {"skip": skip, "limit": limit}, "items": workers})
예제 #7
0
def collection(user: dict):

    skip = request.args.get("skip", default=0, type=int)
    limit = request.args.get("limit", default=20, type=int)
    skip = 0 if skip < 0 else skip
    limit = 20 if limit <= 0 else limit

    query = {}
    projection = None
    cursor = (
        Acknowlegments()
        .find(query, projection)
        .sort([("$natural", pymongo.ASCENDING)])
        .skip(skip)
        .limit(limit)
    )
    count = Acknowlegments().count_documents(query)
    workers = [worker for worker in cursor]

    return jsonify(
        {"meta": {"skip": skip, "limit": limit, "count": count}, "items": workers}
    )
예제 #8
0
파일: workers.py 프로젝트: kiwix/cardshop
def calculate_load(user: dict):

    now = datetime.datetime.now()

    def is_connected(worker):
        """whether a worker is considered connected (ping 15mn ago)"""
        try:
            return (now - worker["on"]).total_seconds() <= 900  # 15mn
        except Exception:
            raise
            return False

    def get_remaining_minutes(task):
        """estimated remaining duration of task based on units and when/if started"""
        # physical card units are 10 times download ones but creator impact is identical
        units = task["units"] / 10 if task["units"] > 512 else task["units"]

        # small images are done in about an hour
        # larger one increase duration with size ; especially due to upload
        duration = max(int(units * 1.875), 90) if units >= 32 else 60
        if task["status"] in ["pending", "received"]:
            # task has not started
            return duration

        # already started, remove spent time from received
        for event in task.get("statuses", []):
            if event["status"] == "received":
                passed = datetime.datetime.now() - event["on"]
                return duration - (passed.total_seconds() // 60)

        # couldn't find received ; returning full duration
        return duration

    # get number of online workers
    cursor = Acknowlegments().find({}, None).sort([("$natural",
                                                    pymongo.ASCENDING)])
    nb_connected_workers = len([
        worker for worker in cursor
        if worker.get("worker_type") == "creator" and is_connected(worker)
    ])

    # get list of pending task and calculate remaining durations for those
    tasks = []
    for task in CreatorTasks().find(
        {
            "status": {
                "$in":
                ["pending", "received", "building", "built", "uploading"]
            }
        },
        {
            "status": 1,
            "statuses": 1,
            "order": 1,
            "worker": 1
        },
    ):
        task["units"] = Orders().find_one({"_id": task["order"]},
                                          {"units": 1})["units"]
        task["duration"] = get_remaining_minutes(task)
        tasks.append(task)
    nb_pending_taks = len(tasks)

    cumulative_duration = sum([task["duration"] for task in tasks])
    try:
        remaining_minutes = cumulative_duration // nb_connected_workers
    except ZeroDivisionError:
        remaining_minutes = None  # no worker
    estimated_completion = (now +
                            datetime.timedelta(seconds=remaining_minutes * 60)
                            if remaining_minutes else now)

    return jsonify({
        "connected_workers": nb_connected_workers,
        "pending_tasks": nb_pending_taks,
        "cumulative_duration": cumulative_duration,
        "remaining_minutes": remaining_minutes,
        "estimated_completion": estimated_completion.isoformat(),
    })