"""Neo4j connector Client.""" from contextlib import contextmanager from flask import g from neo4j import GraphDatabase from participant import config from participant.api import app from participant.utils import exception if config.ENVIRONMENT != config.TEST_ENVIRONMENT: try: neo4j_driver = GraphDatabase.driver( config.NEO4J_URL, auth=(config.NEO4J_USERNAME, config.NEO4J_PASSWORD), ) except Exception as err: if config.NEO4J_SETUP_READY: exception.reraise_exception(err) else: print('ERROR: Neo4j connection failed due to: {}'.format(err)) @app.teardown_appcontext def close_db(exc_info): """Close session on request teardown. So there is no need to do that throughout the code. This gets called once per request, so a session lives for a each request instead of each query scope. Args: exc_info(exception): exception instance, if it was not handled. """ if hasattr(g, 'neo4j_db'): g.neo4j_db.close() @contextmanager def db_session(): """Provide a session for series of operations. Session will closed once the whole flask request is done. Commit and rollbacks has to be managed by caller. Usage: # Default usage with db_session() as session: session.run("MATCH (a:Person {name: $name}) RETURN a", name=name) # Auto-commit transaction with db_session() as session: session.run("CREATE (a:Person {name: $name})", name=name) # explicit with db_session() as session: tx = session.begin_transaction() try: result = tx.run("CREATE (n:Person{lastname:'test'})") tx.commit() except CypherError as e: tx.rollback() """ if not hasattr(g, 'neo4j_db'): if neo4j_driver: g.neo4j_db = neo4j_driver.session(database=config.NEO4J_DATABASE_NAME) yield g.neo4j_db