Python neo4j bolt driver loses connection after context switch











up vote
2
down vote

favorite












I have a backend written in django which uses the neo4j bolt driver to communicate with the neo4j graph db.



I use a Singleton to handle the connection and the bolt driver closes the connection, whenever I access it from another location than where the connection was initially established (e.g. I open the connection in a view, access it in a signal and when I try to save in the view the connection is lost).



I’ve tried to extract the main problem I have come up with and break it down to a small piece of example code below.



I would appreciate any explanation of behavior to or even better a solution ;)



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


Implementation details: I have a wrapper object "GraphMapper" which encapsulates the connection, session, and transaction of the driver. and is designed as a singleton instance. A transaction is established at a point (A, e.g. a view) but I cannot complete the transaction here. I need to add additional values from location (B, e.g. a post-save signal). However, I cannot pass a reference to the "GraphMapper" A to B. Thus, I came up with the singleton implementation as explained above.
I have ensured that the singleton is exact the same instance on all locations (within one request). But at the moment I exit the context (package, class or method) through a method call and retrieve the "GraphMapper" instance at the very next location, the connection is closed. I even checked the reference count to the "GraphMapper" and its connection and the garbage collector should not delete it. Seldom it says the connection is not closed. But writing to the graph results in a connection refused error.



P.S.: I know there is some useless and unnecessary code, this is for illustrative purposes only and I wanted to make sure that the garbage collector did not kill some objects.










share|improve this question


























    up vote
    2
    down vote

    favorite












    I have a backend written in django which uses the neo4j bolt driver to communicate with the neo4j graph db.



    I use a Singleton to handle the connection and the bolt driver closes the connection, whenever I access it from another location than where the connection was initially established (e.g. I open the connection in a view, access it in a signal and when I try to save in the view the connection is lost).



    I’ve tried to extract the main problem I have come up with and break it down to a small piece of example code below.



    I would appreciate any explanation of behavior to or even better a solution ;)



    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


    Implementation details: I have a wrapper object "GraphMapper" which encapsulates the connection, session, and transaction of the driver. and is designed as a singleton instance. A transaction is established at a point (A, e.g. a view) but I cannot complete the transaction here. I need to add additional values from location (B, e.g. a post-save signal). However, I cannot pass a reference to the "GraphMapper" A to B. Thus, I came up with the singleton implementation as explained above.
    I have ensured that the singleton is exact the same instance on all locations (within one request). But at the moment I exit the context (package, class or method) through a method call and retrieve the "GraphMapper" instance at the very next location, the connection is closed. I even checked the reference count to the "GraphMapper" and its connection and the garbage collector should not delete it. Seldom it says the connection is not closed. But writing to the graph results in a connection refused error.



    P.S.: I know there is some useless and unnecessary code, this is for illustrative purposes only and I wanted to make sure that the garbage collector did not kill some objects.










    share|improve this question
























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I have a backend written in django which uses the neo4j bolt driver to communicate with the neo4j graph db.



      I use a Singleton to handle the connection and the bolt driver closes the connection, whenever I access it from another location than where the connection was initially established (e.g. I open the connection in a view, access it in a signal and when I try to save in the view the connection is lost).



      I’ve tried to extract the main problem I have come up with and break it down to a small piece of example code below.



      I would appreciate any explanation of behavior to or even better a solution ;)



      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


      Implementation details: I have a wrapper object "GraphMapper" which encapsulates the connection, session, and transaction of the driver. and is designed as a singleton instance. A transaction is established at a point (A, e.g. a view) but I cannot complete the transaction here. I need to add additional values from location (B, e.g. a post-save signal). However, I cannot pass a reference to the "GraphMapper" A to B. Thus, I came up with the singleton implementation as explained above.
      I have ensured that the singleton is exact the same instance on all locations (within one request). But at the moment I exit the context (package, class or method) through a method call and retrieve the "GraphMapper" instance at the very next location, the connection is closed. I even checked the reference count to the "GraphMapper" and its connection and the garbage collector should not delete it. Seldom it says the connection is not closed. But writing to the graph results in a connection refused error.



      P.S.: I know there is some useless and unnecessary code, this is for illustrative purposes only and I wanted to make sure that the garbage collector did not kill some objects.










      share|improve this question













      I have a backend written in django which uses the neo4j bolt driver to communicate with the neo4j graph db.



      I use a Singleton to handle the connection and the bolt driver closes the connection, whenever I access it from another location than where the connection was initially established (e.g. I open the connection in a view, access it in a signal and when I try to save in the view the connection is lost).



      I’ve tried to extract the main problem I have come up with and break it down to a small piece of example code below.



      I would appreciate any explanation of behavior to or even better a solution ;)



      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


      Implementation details: I have a wrapper object "GraphMapper" which encapsulates the connection, session, and transaction of the driver. and is designed as a singleton instance. A transaction is established at a point (A, e.g. a view) but I cannot complete the transaction here. I need to add additional values from location (B, e.g. a post-save signal). However, I cannot pass a reference to the "GraphMapper" A to B. Thus, I came up with the singleton implementation as explained above.
      I have ensured that the singleton is exact the same instance on all locations (within one request). But at the moment I exit the context (package, class or method) through a method call and retrieve the "GraphMapper" instance at the very next location, the connection is closed. I even checked the reference count to the "GraphMapper" and its connection and the garbage collector should not delete it. Seldom it says the connection is not closed. But writing to the graph results in a connection refused error.



      P.S.: I know there is some useless and unnecessary code, this is for illustrative purposes only and I wanted to make sure that the garbage collector did not kill some objects.







      python-3.x neo4j connection neo4j-bolt






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 7 at 13:43









      Sasorien

      112




      112





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53190676%2fpython-neo4j-bolt-driver-loses-connection-after-context-switch%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53190676%2fpython-neo4j-bolt-driver-loses-connection-after-context-switch%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Tangent Lines Diagram Along Smooth Curve

          Yusuf al-Mu'taman ibn Hud

          Zucchini