私は、neo4jボルトドライバーを使用してneo4jグラフdbと通信するdjangoで書かれたバックエンドを持っています。
シングルトンを使用して接続を処理し、接続が最初に確立された場所とは別の場所からアクセスするたびに、ボルトドライバーが接続を閉じます (たとえば、ビューで接続を開き、シグナルでアクセスし、ビューに保存すると、接続が失われます)。
私が思いついた主な問題を抽出して、以下の小さなコード例に分解しようとしました。
動作の説明、またはより良い解決策をいただければ幸いです;)
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、たとえば apost-save
信号)。ただし、「GraphMapper」A から B への参照を渡すことはできません。したがって、上記で説明したシングルトン実装を思いつきました。シングルトンがすべての場所で (1 つの要求内で) まったく同じインスタンスであることを確認しました。しかし、メソッド呼び出しを介してコンテキスト (パッケージ、クラス、またはメソッド) を終了し、次の場所で「GraphMapper」インスタンスを取得すると、接続が閉じられます。「GraphMapper」への参照カウントとその接続も確認しましたが、ガベージコレクターはそれを削除しないでください。接続が閉じられていないと言うことはめったにありません。ただし、グラフに書き込むと、接続拒否エラーが発生します。
PS: 役に立たない不要なコードがあることはわかっています。これは説明のみを目的としており、ガベージ コレクターが一部のオブジェクトを強制終了しないようにしたかったのです。