2

我有一个用 django 编写的后端,它使用 neo4j 螺栓驱动程序与 neo4j 图形数据库进行通信。

我使用单例来处理连接,并且螺栓驱动器关闭连接,每当我从最初建立连接的位置以外的其他位置访问它时(例如,我在视图中打开连接,在信号中访问它以及当我尝试保存在视图中连接丢失)。

我试图提取我提出的主要问题并将其分解为下面的一小段示例代码。

我将不胜感激对行为的任何解释,甚至更好的解决方案;)

from neo4j.v1 import Driver, GraphDatabase, basic_auth, Session, Transaction


def main():
    gm = GraphMapper()
    gm.begin_atomic_transaction()

    print(f"graph connection closed before method? {gm.is_connection_closed()}") # -> false

    fill_transaction() #the context switch

    print(f"graph connection closed after method? {gm.is_connection_closed()}") # -> true

    if not gm.is_connection_closed():
        print(f"graph connection open - try to commit") # -> is never called
        gm.commit_atomic_transaction_and_close_session()


def fill_transaction():
    gm = GraphMapper()

    print(f"graph connection closed in method? {gm.is_connection_closed()}") # -> true

    gm.create_update_node("TestNode")


class GraphMapper:
    __instance = None
    __transaction = None  # type: Transaction
    __session = None  # type: Session
    __connection = None # type: Connection
    __driver = None  # type: Driver

    def __new__(cls, *args, **kwargs):
        if not isinstance(cls.__instance, cls):
            cls.__instance = object.__new__(cls, *args, **kwargs)
        return cls.__instance

    def __init__(self):
        self.__driver = GraphDatabase.driver("bolt://localhost:7687", auth=basic_auth("neo4j", "password"))

    def is_connection_closed(self):
        return self.__transaction.session._connection._closed

    def begin_atomic_transaction(self):
        self.__session = self.__driver.session()
        self.__transaction = self.__session.begin_transaction()
        self.__connection = self.__transaction.session._connection
        return self.__transaction

    def commit_atomic_transaction_and_close_session(self):
        result = self.__transaction.commit()

        self.__transaction = None
        return result

    def create_update_node(self, label):
        # Add Cypher statement to transaction

实现细节:我有一个包装器对象“GraphMapper”,它封装了驱动程序的连接、会话和事务。并被设计为单例实例。事务在某个点(A,例如视图)建立,但我无法在此处完成事务。我需要从位置添加其他值(B,例如post-save信号)。但是,我不能将对“GraphMapper”A 的引用传递给 B。因此,我想出了上面解释的单例实现。我已确保单例在所有位置(在一个请求中)都是完全相同的实例。但是当我通过方法调用退出上下文(包、类或方法)并在下一个位置检索“GraphMapper”实例时,连接已关闭。我什至检查了对“GraphMapper”的引用计数及其连接,垃圾收集器不应该删除它。很少有人说连接没有关闭。但是写入图表会导致连接被拒绝错误。

PS:我知道有一些无用和不必要的代码,这仅用于说明目的,我想确保垃圾收集器没有杀死某些对象。

4

0 回答 0