Example #1
0
    def __init__(
        self,
        domain: Optional[Domain] = None,
        dialect: Text = "sqlite",
        url: Text = None,
        db: Text = "rasa.db",
        username: Text = None,
        password: Text = None,
        event_broker: Optional[EventChannel] = None,
    ) -> None:
        from sqlalchemy.orm import sessionmaker
        from sqlalchemy.engine.url import URL
        from sqlalchemy import create_engine

        engine_url = URL(dialect, username, password, url, database=db)

        logger.debug("Attempting to connect to database "
                     'via "{}"'.format(engine_url.__to_string__()))

        self.engine = create_engine(engine_url)
        self.session = sessionmaker(bind=self.engine)()

        self.Base.metadata.create_all(self.engine)

        logger.debug("Connection to SQL database '{}' successful".format(db))

        super(SQLTrackerStore, self).__init__(domain, event_broker)
Example #2
0
def check_connection(db_uri: URL,
                     *,
                     retry_attempts: int = 10,
                     retry_interval: int = 2) -> None:
    db_uri_str = db_uri.__to_string__()
    logging.info('Establishing connection ' f'with "{db_uri_str}".')
    with get_engine(db_uri) as engine:
        for attempt_num in range(retry_attempts):
            try:
                with engine.connect():
                    pass
                break
            except OperationalError:
                err_msg = ('Connection attempt ' f'#{attempt_num + 1} failed.')
                logging.error(err_msg)
                time.sleep(retry_interval)
        else:
            err_message = ('Failed to establish connection '
                           f'with "{db_uri_str}" '
                           f'after {retry_attempts} attempts '
                           f'with {retry_interval} s. interval.')
            raise ConnectionError(err_message)

    logging.info(f'Connection established with "{db_uri_str}".')
Example #3
0
    def __init__(
        self,
        domain: Optional[Domain] = None,
        dialect: Text = "sqlite",
        host: Optional[Text] = None,
        port: Optional[int] = None,
        db: Text = "rasa.db",
        username: Text = None,
        password: Text = None,
        event_broker: Optional[EventChannel] = None,
        login_db: Optional[Text] = None,
    ) -> None:
        import sqlalchemy
        from sqlalchemy.orm import sessionmaker
        from sqlalchemy.engine.url import URL
        from sqlalchemy import create_engine

        engine_url = URL(
            dialect,
            username,
            password,
            host,
            port,
            database=login_db if login_db else db,
        )

        logger.debug("Attempting to connect to database "
                     'via "{}"'.format(engine_url.__to_string__()))

        # Database might take a while to come up
        while True:
            try:
                self.engine = create_engine(engine_url)

                # if `login_db` has been provided, use current connection with
                # that database to create working database `db`
                if login_db:
                    self._create_database_and_update_engine(db, engine_url)

                try:
                    self.Base.metadata.create_all(self.engine)
                except (
                        sqlalchemy.exc.OperationalError,
                        sqlalchemy.exc.ProgrammingError,
                ) as e:
                    # Several Rasa services started in parallel may attempt to
                    # create tables at the same time. That is okay so long as
                    # the first services finishes the table creation.
                    logger.error("Could not create tables: {}".format(e))

                self.session = sessionmaker(bind=self.engine)()
                break
            except (
                    sqlalchemy.exc.OperationalError,
                    sqlalchemy.exc.IntegrityError,
            ) as e:

                logger.warning(e)
                sleep(5)

        logger.debug("Connection to SQL database '{}' successful".format(db))

        super(SQLTrackerStore, self).__init__(domain, event_broker)
Example #4
0
    def do_run(self):
        # R0914: Too many local variables.
        # pylint: disable=R0914

        import sqlalchemy
        from sqlalchemy import exc
        from sqlalchemy.event import listen
        from sqlalchemy.engine.url import URL

        def start_query(conn, *dummy):
            ''' Save time the query starts. '''
            conn.info['wh_time'] = timeit.default_timer()

        def end_query(conn, *dummy):
            ''' Save time the query's finished. '''
            conn.info['wh_time'] = timeit.default_timer() - conn.info['wh_time']

        config = {
            k: v for k, v in self.config.iteritems()
            if k in self.config_raw['properties'].keys()
        }
        config['drivername'] = config.pop('dbtype')

        if config['drivername'] == 'sqlite':
            config['database'] = config.pop('host')

        query = config.pop('query')

        url = URL(**config)

        try:
            engine = sqlalchemy.create_engine(url)
        except ImportError as err:
            return ((
                'error',
                '{}. Sensor checking sql requires it. Please install it.'
                .format(err)
            ),)

        error_msg = (
            '(database {})\nError: {{}}\n Message from database: "{{}}"'
            .format(url.__to_string__())
        )
        try:
            connection = engine.connect()
        except exc.TimeoutError:
            return (
                ('error', error_msg.format('Timeout getting connection', None)),
            )
        except exc.SQLAlchemyError as err:
            return (
                ('error', error_msg.format('Could not connect to database', err)),
            )

        listen(connection, 'before_cursor_execute', start_query)
        listen(connection, 'after_cursor_execute', end_query)
        try:
            result = connection.execute(query).fetchall()
            time = connection.info['wh_time']
        except exc.StatementError as err:
            return ((
                'error', error_msg.format(
                    'Error executing statement {}'.format(err.statement), err)
            ),)
        except exc.SQLAlchemyError as err:
            return ((
                'error', error_msg.format(
                    'Error executing statement, your query: {}'.format(
                        self.config['query']),
                    err.message)
            ),)
        finally:
            connection.close()

        try:
            if len(result) == 1 and len(result[0]) == 1:
                result = ('result_num', float(result[0][0]))
            else:
                raise ValueError
        except ValueError:
            result = ('result', str(result)[1:-1])

        return (result, ('query_time', time))
Example #5
0
    def do_run(self):
        # R0914: Too many local variables.
        # pylint: disable=R0914

        import sqlalchemy
        from sqlalchemy import exc
        from sqlalchemy.event import listen
        from sqlalchemy.engine.url import URL

        def start_query(conn, *dummy):
            ''' Save time the query starts. '''
            conn.info['wh_time'] = timeit.default_timer()

        def end_query(conn, *dummy):
            ''' Save time the query's finished. '''
            conn.info['wh_time'] = timeit.default_timer(
            ) - conn.info['wh_time']

        config = {
            k: v
            for k, v in self.config.iteritems()
            if k in self.config_raw['properties'].keys()
        }
        config['drivername'] = config.pop('dbtype')

        if config['drivername'] == 'sqlite':
            config['database'] = config.pop('host')

        query = config.pop('query')

        url = URL(**config)

        try:
            engine = sqlalchemy.create_engine(url)
        except ImportError as err:
            return (('error',
                     '{}. Sensor checking sql requires it. Please install it.'.
                     format(err)), )

        error_msg = (
            '(database {})\nError: {{}}\n Message from database: "{{}}"'.
            format(url.__to_string__()))
        try:
            connection = engine.connect()
        except exc.TimeoutError:
            return (('error',
                     error_msg.format('Timeout getting connection', None)), )
        except exc.SQLAlchemyError as err:
            return (('error',
                     error_msg.format('Could not connect to database', err)), )

        listen(connection, 'before_cursor_execute', start_query)
        listen(connection, 'after_cursor_execute', end_query)
        try:
            result = connection.execute(query).fetchall()
            time = connection.info['wh_time']
        except exc.StatementError as err:
            return (('error',
                     error_msg.format(
                         'Error executing statement {}'.format(err.statement),
                         err)), )
        except exc.SQLAlchemyError as err:
            return (('error',
                     error_msg.format(
                         'Error executing statement, your query: {}'.format(
                             self.config['query']), err.message)), )
        finally:
            connection.close()

        try:
            if len(result) == 1 and len(result[0]) == 1:
                result = ('result_num', float(result[0][0]))
            else:
                raise ValueError
        except ValueError:
            result = ('result', str(result)[1:-1])

        return (result, ('query_time', time))