예제 #1
0
def inmem_queue():
    with connection() as conn:
        e = Worker(queues="pytest", connection=conn)
        c = Queue(queue="pytest", connection=conn)
        c.e = e
        c.storage.clear(force=True)
        yield c
        e.shutdown()
예제 #2
0
def inmem_queue():
    with tempfile.NamedTemporaryFile() as f:
        connection = create_engine(
            "sqlite:///{path}".format(path=f.name),
            connect_args={"check_same_thread": False},
            poolclass=NullPool,
        )
        e = Worker(queues="pytest", connection=connection)
        c = Queue(queue="pytest", connection=connection)
        c.e = e
        yield c
        e.shutdown()
예제 #3
0
    def __init__(self, queue=None, connection=None):
        if connection is None and not isinstance(queue, Queue):
            raise ValueError(
                "One of either connection or queue must be specified")
        elif isinstance(queue, Queue):
            self.queue = queue
            if connection is None:
                connection = self.queue.storage.engine
        elif connection:
            self.queue = Queue(connection=connection)

        self._schedule_checker = None

        super(Scheduler, self).__init__(connection, Base=Base)
예제 #4
0
def inmem_queue():
    fd, filepath = tempfile.mkstemp()
    connection = create_engine(
        "sqlite:///{path}".format(path=filepath),
        connect_args={"check_same_thread": False},
        poolclass=NullPool,
    )
    e = Worker(queues="pytest", connection=connection)
    c = Queue(queue="pytest", connection=connection)
    c.e = e
    yield c
    e.shutdown()
    os.close(fd)
    try:
        os.remove(filepath)
    except OSError:
        pass
예제 #5
0
def queue():
    with tempfile.NamedTemporaryFile() as f:
        connection = create_engine(
            "sqlite:///{path}".format(path=f.name),
            connect_args={"check_same_thread": False},
            poolclass=NullPool,
        )
        q = Queue("pytest", connection)
        yield q
예제 #6
0
def queue():
    fd, filepath = tempfile.mkstemp()
    connection = create_engine(
        "sqlite:///{path}".format(path=filepath),
        connect_args={"check_same_thread": False},
        poolclass=NullPool,
    )
    q = Queue("pytest", connection)
    yield q
    os.close(fd)
    os.remove(filepath)
예제 #7
0
파일: main.py 프로젝트: Techlete/kolibri
def __queue():
    return Queue(task_queue_name, connection=connection)
예제 #8
0
파일: main.py 프로젝트: Techlete/kolibri
def __priority_queue():
    return Queue(priority_queue_name, connection=connection)
예제 #9
0
def queue_no_worker():
    with connection() as conn:
        c = Queue(queue="pytest", connection=conn)
        c.storage.clear(force=True)
        yield c
예제 #10
0
파일: main.py 프로젝트: romilly/kolibri

# Add multiprocessing safeguards as recommended by
# https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing


@event.listens_for(connection, "connect")
def connect(dbapi_connection, connection_record):
    connection_record.info["pid"] = os.getpid()


@event.listens_for(connection, "checkout")
def checkout(dbapi_connection, connection_record, connection_proxy):
    pid = os.getpid()
    if connection_record.info["pid"] != pid:
        connection_record.connection = connection_proxy.connection = None
        raise exc.DisconnectionError(
            "Connection record belongs to pid %s, attempting to check out in pid %s"
            % (connection_record.info["pid"], pid)
        )


queue = Queue(app, connection=connection)

scheduler = Scheduler(queue=queue, connection=connection)


def initialize_worker():
    worker = Worker(app, connection=connection, num_workers=1)
    atexit.register(worker.shutdown)
예제 #11
0
파일: main.py 프로젝트: socketbox/kolibri
def __facility_queue():
    return Queue(facility_queue_name, connection=connection)
예제 #12
0
@event.listens_for(connection, "checkout")
def checkout(dbapi_connection, connection_record, connection_proxy):
    pid = os.getpid()
    if connection_record.info["pid"] != pid:
        connection_record.connection = connection_proxy.connection = None
        raise exc.DisconnectionError(
            "Connection record belongs to pid %s, attempting to check out in pid %s"
            % (connection_record.info["pid"], pid))


task_queue_name = "kolibri"

priority_queue_name = "no_waiting"

priority_queue = Queue(priority_queue_name, connection=connection)

queue = Queue(task_queue_name, connection=connection)

scheduler = Scheduler(queue=queue, connection=connection)


def initialize_workers():
    regular_worker = Worker(task_queue_name,
                            connection=connection,
                            num_workers=1)
    priority_worker = Worker(priority_queue_name,
                             connection=connection,
                             num_workers=3)
    return regular_worker, priority_worker
예제 #13
0
class Scheduler(StorageMixin):
    def __init__(self, queue=None, connection=None):
        if connection is None and not isinstance(queue, Queue):
            raise ValueError(
                "One of either connection or queue must be specified")
        elif isinstance(queue, Queue):
            self.queue = queue
            if connection is None:
                connection = self.queue.storage.engine
        elif connection:
            self.queue = Queue(connection=connection)

        self._schedule_checker = None

        super(Scheduler, self).__init__(connection, Base=Base)

    def __contains__(self, item):
        """
        Returns a boolean indicating whether the given job instance or job id
        is scheduled for execution.
        """
        job_id = item
        if isinstance(item, Job):
            job_id = item.job_id
        with self.session_scope() as session:
            return session.query(
                self._ns_query(session).filter_by(
                    id=job_id).exists()).scalar()

    def change_execution_time(self, job, date_time):
        """
        Change a job's execution time.
        """
        if date_time.tzinfo is None:
            raise ValueError(
                "Must use a timezone aware datetime object for scheduling tasks"
            )

        with self.session_scope() as session:
            scheduled_job = (session.query(ScheduledJob).filter_by(
                id=job.job_id).one_or_none())
            if scheduled_job:
                scheduled_job.scheduled_time = naive_utc_datetime(date_time)
                session.merge(scheduled_job)
            else:
                raise ValueError("Job not in scheduled jobs queue")

    def start_schedule_checker(self):
        """
        Starts up the job checker thread, that starts scheduled jobs when there are workers free,
        and checks for cancellation requests for jobs currently assigned to a worker.
        Returns: the Thread object.
        """
        t = InfiniteLoopThread(self.check_schedule,
                               thread_name="SCHEDULECHECKER",
                               wait_between_runs=0.5)
        t.start()
        return t

    def run(self):
        """
        Start the schedule checker in a blocking way to be parallel to the rq-scheduler method.
        """
        thread = self.start_schedule_checker()
        thread.join()

    def start_scheduler(self):
        if not (self._schedule_checker and self._schedule_checker.is_alive()):
            self._schedule_checker = self.start_schedule_checker()

    def shutdown_scheduler(self):
        if self._schedule_checker:
            self._schedule_checker.stop()

    def enqueue_at(self, dt, func, interval=0, repeat=0, *args, **kwargs):
        """
        Add the job to the scheduler for the specified time
        """
        return self.schedule(dt,
                             func,
                             interval=interval,
                             repeat=repeat,
                             *args,
                             **kwargs)

    def enqueue_in(self, delta_t, func, interval=0, repeat=0, *args, **kwargs):
        """
        Add the job to the scheduler in the specified time delta
        """
        if not isinstance(delta_t, timedelta):
            raise ValueError("Time argument must be a timedelta object.")
        dt = self._now() + delta_t
        return self.schedule(dt,
                             func,
                             interval=interval,
                             repeat=repeat,
                             *args,
                             **kwargs)

    def schedule(self, dt, func, interval=0, repeat=0, *args, **kwargs):
        """
        Add the job to the scheduler for the specified time, interval, and number of repeats.
        Repeat of None with a specified interval means the job will repeat forever at that
        interval.
        """
        if not isinstance(dt, datetime):
            raise ValueError("Time argument must be a datetime object.")
        if not interval and repeat != 0:
            raise ValueError(
                "Must specify an interval if the task is repeating")
        if dt.tzinfo is None:
            raise ValueError(
                "Must use a timezone aware datetime object for scheduling tasks"
            )
        if isinstance(func, Job):
            job = func
        # else, turn it into a job first.
        else:
            job = Job(func, *args, **kwargs)

        job.state = State.SCHEDULED

        with self.session_scope() as session:
            scheduled_job = ScheduledJob(
                id=job.job_id,
                queue=self.queue.name,
                interval=interval,
                repeat=repeat,
                scheduled_time=naive_utc_datetime(dt),
                obj=job,
            )
            session.merge(scheduled_job)

            return job.job_id

    def get_jobs(self):
        with self.session_scope() as s:
            scheduled_jobs = self._ns_query(s).all()
            return [o.obj for o in scheduled_jobs]

    def count(self):
        with self.session_scope() as s:
            return self._ns_query(s).count()

    def get_job(self, job_id):
        with self.session_scope() as session:
            scheduled_job = session.query(ScheduledJob).get(job_id)
            if scheduled_job is None:
                raise JobNotFound()
            return scheduled_job.obj

    def cancel(self, job_id):
        """
        Clear a scheduled job.
        :type job_id: NoneType or str
        :param job_id: the job_id to clear. If None, clear all jobs.
        """
        with self.session_scope() as s:
            q = self._ns_query(s)
            if job_id:
                q = q.filter_by(id=job_id)

            q.delete(synchronize_session=False)

    def clear_scheduler(self):
        """
        Clear all scheduled jobs
        """
        self.cancel(None)

    def check_schedule(self):
        start = time.time()
        naive_utc_now = datetime.utcnow()
        with self.session_scope() as s:
            scheduled_jobs = self._ns_query(s).filter(
                ScheduledJob.scheduled_time <= naive_utc_now)
            for scheduled_job in scheduled_jobs:
                new_repeat = 0
                repeat = False
                if scheduled_job.repeat is None:
                    new_repeat = None
                    repeat = True
                elif scheduled_job.repeat > 0:
                    new_repeat = scheduled_job.repeat - 1
                    repeat = True
                job_for_queue = scheduled_job.obj
                self.queue.enqueue(job_for_queue)
                if repeat:
                    # Update this scheduled job to repeat this
                    self.schedule(
                        self._now() +
                        timedelta(seconds=scheduled_job.interval),
                        job_for_queue,
                        interval=scheduled_job.interval,
                        repeat=new_repeat,
                    )
                else:
                    s.delete(scheduled_job)
            return time.time() - start

    def _ns_query(self, session):
        """
        Return a SQLAlchemy query that is already namespaced by the queue.
        Returns: a SQLAlchemy query object
        """
        return session.query(ScheduledJob).filter(
            ScheduledJob.queue == self.queue.name)

    def _now(self):
        return local_now()
예제 #14
0
def queue():
    with connection() as c:
        q = Queue("pytest", c)
        yield q