Beispiel #1
0
    def status_report(
        self, company_id: str, user_id: str, ip: str, report: StatusReportRequest
    ) -> None:
        """
        Write worker status report
        :param company_id: worker's company ID
        :param user_id: user_id ID under which this worker is running
        :raise bad_request.InvalidTaskId: the reported task was not found
        :return: worker entry instance
        """
        entry = self._get_worker(company_id, user_id, report.worker)

        try:
            entry.ip = ip
            now = datetime.utcnow()
            entry.last_activity_time = now

            if report.machine_stats:
                self._log_stats_to_es(
                    company_id=company_id,
                    company_name=entry.company.name,
                    worker=report.worker,
                    timestamp=report.timestamp,
                    task=report.task,
                    machine_stats=report.machine_stats,
                )

            entry.queue = report.queue

            if report.queues:
                entry.queues = report.queues

            if not report.task:
                entry.task = None
            else:
                with translate_errors_context():
                    query = dict(id=report.task, company=company_id)
                    update = dict(
                        last_worker=report.worker,
                        last_worker_report=now,
                        last_update=now,
                    )
                    # modify(new=True, ...) returns the modified object
                    task = Task.objects(**query).modify(new=True, **update)
                    if not task:
                        raise bad_request.InvalidTaskId(**query)
                    entry.task = IdNameEntry(id=task.id, name=task.name)

            entry.last_report_time = now
        except APIError:
            raise
        except Exception as e:
            msg = "Failed processing worker status report"
            log.exception(msg)
            raise server_error.DataError(msg, err=e.args[0])
        finally:
            self._save_worker(entry)
Beispiel #2
0
    def _get_worker(self, company_id: str, user_id: str, worker: str) -> WorkerEntry:
        """
        Get a worker entry for the provided worker ID. The entry is loaded from Redis
        if it exists (i.e. worker has already been registered), otherwise the worker
        is registered and its entry stored into Redis).
        :param company_id: worker's company ID
        :param user_id: user ID under which this worker is running
        :param worker: worker ID
        :raise bad_request.InvalidWorkerId: in case the worker id was not found
        :return: worker entry instance
        """
        key = self._get_worker_key(company_id, user_id, worker)

        with TimingContext("redis", "get_worker"):
            data = self.redis.get(key)

        if data:
            try:
                entry = WorkerEntry.from_json(data)
                if not entry.key:
                    entry.key = key
                    self._save_worker(entry)
                return entry
            except Exception as e:
                msg = "Failed parsing worker entry"
                log.exception(msg)
                raise server_error.DataError(msg, err=e.args[0])

        # Failed loading worker from Redis
        if config.get("apiserver.workers.auto_register", False):
            try:
                return self.register_worker(company_id, user_id, worker)
            except Exception:
                log.error(
                    "Failed auto registration of {} for company {}".format(
                        worker, company_id
                    )
                )

        raise bad_request.InvalidWorkerId(worker=worker)
Beispiel #3
0
    def get_all(
        self, company_id: str, last_seen: Optional[int] = None
    ) -> Sequence[WorkerEntry]:
        """
        Get all the company workers that were active during the last_seen period
        :param company_id: worker's company id
        :param last_seen: period in seconds to check. Min value is 1 second
        :return:
        """
        try:
            workers = self._get(company_id)
        except Exception as e:
            raise server_error.DataError("failed loading worker entries", err=e.args[0])

        if last_seen:
            ref_time = datetime.utcnow() - timedelta(seconds=max(1, last_seen))
            workers = [
                w
                for w in workers
                if w.last_activity_time.replace(tzinfo=None) >= ref_time
            ]

        return workers