Ejemplo n.º 1
0
    def run(cls, db_name):
        transaction = Transaction()
        logger.info('cron started for "%s"', db_name)
        now = datetime.datetime.now()
        retry = config.getint('database', 'retry')
        with transaction.start(db_name, 0, context={'_skip_warnings': True}):
            transaction.database.lock(transaction.connection, cls._table)
            crons = cls.search(['OR',
                    ('next_call', '<=', now),
                    ('next_call', '=', None),
                    ])

            for cron in crons:
                name = '<Cron %s@%s %s>' % (cron.id, db_name, cron.method)
                logger.info("%s started", name)
                for count in range(retry, -1, -1):
                    if count != retry:
                        time.sleep(0.02 * (retry - count))
                    try:
                        with processing(name):
                            cron.run_once()
                            cron.next_call = cron.compute_next_call(now)
                            cron.save()
                            transaction.commit()
                    except Exception as e:
                        transaction.rollback()
                        if (isinstance(e, backend.DatabaseOperationalError)
                                and count):
                            continue
                        logger.error('%s failed', name, exc_info=True)
                    break
        while transaction.tasks:
            task_id = transaction.tasks.pop()
            run_task(db_name, task_id)
        logger.info('cron finished for "%s"', db_name)
Ejemplo n.º 2
0
def run_task(pool, task_id):
    if not isinstance(pool, Pool):
        database_list = Pool.database_list()
        pool = Pool(pool)
        if pool.database_name not in database_list:
            with Transaction().start(pool.database_name, 0, readonly=True):
                pool.init()
    Queue = pool.get('ir.queue')
    Error = pool.get('ir.error')
    name = '<Task %s@%s>' % (task_id, pool.database_name)
    logger.info('%s started', name)
    retry = config.getint('database', 'retry')
    try:
        for count in range(retry, -1, -1):
            if count != retry:
                time.sleep(0.02 * (retry - count))
            with Transaction().start(pool.database_name, 0) as transaction:
                try:
                    try:
                        task, = Queue.search([('id', '=', task_id)])
                    except ValueError:
                        # the task was rollbacked, nothing to do
                        break
                    with processing(name):
                        task.run()
                    break
                except backend.DatabaseOperationalError:
                    if count:
                        transaction.rollback()
                        continue
                    raise
                except (UserError, UserWarning) as e:
                    Error.log(task, e)
                    raise
        logger.info('%s done', name)
    except backend.DatabaseOperationalError:
        logger.info('%s failed, retrying', name, exc_info=True)
        if not config.getboolean('queue', 'worker', default=False):
            time.sleep(0.02 * retry)
        try:
            with Transaction().start(pool.database_name, 0) as transaction:
                if not transaction.database.has_channel():
                    logger.critical('%s failed', name, exc_info=True)
                    return
                task = Queue(task_id)
                if task.scheduled_at and task.enqueued_at < task.scheduled_at:
                    duration = (task.scheduled_at - task.enqueued_at) * 2
                else:
                    duration = dt.timedelta(seconds=2 * retry)
                duration = max(duration, dt.timedelta(hours=1))
                scheduled_at = dt.datetime.now() + duration * random.random()
                Queue.push(task.name, task.data, scheduled_at=scheduled_at)
        except Exception:
            logger.critical(
                'rescheduling %s failed', name, exc_info=True)
    except (UserError, UserWarning):
        logger.info('%s failed', name)
    except Exception:
        logger.critical('%s failed', name, exc_info=True)
Ejemplo n.º 3
0
    def wsgi_app(self, environ, start_response):
        for cls in self.protocols:
            if cls.content_type in environ.get('CONTENT_TYPE', ''):
                request = cls.request(environ)
                break
        else:
            request = Request(environ)
        logger.info('%s', request)

        origin = request.headers.get('Origin')
        origin_host = urllib.parse.urlparse(origin).netloc if origin else ''
        host = request.headers.get('Host')
        if origin and origin != 'null' and origin_host != host:
            cors = filter(
                None, config.get('web', 'cors', default='').splitlines())
            if origin not in cors:
                abort(HTTPStatus.FORBIDDEN)
        if origin == 'null':
            adapter = self.url_map.bind_to_environ(request.environ)
            endpoint = adapter.match()[0]
            if not getattr(endpoint, 'allow_null_origin', False):
                abort(HTTPStatus.FORBIDDEN)

        with processing(request):
            data = self.dispatch_request(request)
            if not isinstance(data, (Response, HTTPException)):
                response = self.make_response(request, data)
            else:
                response = data

        if origin and isinstance(response, Response):
            response.headers['Access-Control-Allow-Origin'] = origin
            response.headers['Vary'] = 'Origin'
            method = request.headers.get('Access-Control-Request-Method')
            if method:
                response.headers['Access-Control-Allow-Methods'] = method
            headers = request.headers.get('Access-Control-Request-Headers')
            if headers:
                response.headers['Access-Control-Allow-Headers'] = headers
            response.headers['Access-Control-Max-Age'] = config.getint(
                'web', 'cache_timeout')
        return response(environ, start_response)
Ejemplo n.º 4
0
def run_task(pool, task_id):
    if not isinstance(pool, Pool):
        pool = Pool(pool)
    Queue = pool.get('ir.queue')
    name = '<Task %s@%s>' % (task_id, pool.database_name)
    logger.info('%s started', name)
    retry = config.getint('database', 'retry')
    try:
        for count in range(retry, -1, -1):
            if count != retry:
                time.sleep(0.02 * (retry - count))
            with Transaction().start(pool.database_name, 0) as transaction:
                try:
                    try:
                        task, = Queue.search([('id', '=', task_id)])
                    except ValueError:
                        # the task was rollbacked, nothing to do
                        break
                    with processing(name):
                        task.run()
                    break
                except backend.DatabaseOperationalError:
                    if count:
                        transaction.rollback()
                        continue
                    raise
        logger.info('%s done', name)
    except backend.DatabaseOperationalError:
        logger.info('%s failed, retrying', name, exc_info=True)
        if not config.getboolean('queue', 'worker', default=False):
            time.sleep(0.02 * retry)
        try:
            with Transaction().start(pool.database_name, 0) as transaction:
                task = Queue(task_id)
                scheduled_at = dt.datetime.now()
                scheduled_at += dt.timedelta(
                    seconds=random.randint(0, 2 * retry))
                Queue.push(task.name, task.data, scheduled_at=scheduled_at)
        except Exception:
            logger.critical('rescheduling %s failed', name, exc_info=True)
    except Exception:
        logger.critical('%s failed', name, exc_info=True)