Search code examples
javamultithreadingneo4jtransactionsneo4j-ogm

neo4j-ogm returns null bookmark when executed in transaction/concurrently


Scenario 1:
When I execute the following code without opening a transaction, it returns bookmark successfully.

    Session session2 = sessionFactory.openSession();
    session2.query("MATCH (n) RETURN count(n)", new HashMap<>());
    String lastBookmark = session2.getLastBookmark();
    System.out.println("WITHOUT" + " - " + lastBookmark);

Output:

WITHOUT - neo4j:bookmark:v1:tx6776

When I acquire a transaction explicitly, getLastBookmark() returns null.

    Session session = sessionFactory.openSession();
    session.beginTransaction(Transaction.Type.READ_ONLY);
    session.query("MATCH (n) RETURN count(n)", new HashMap<>());
    System.out.println("With" + " - " + session.getLastBookmark());
    session.getTransaction().close();

Output:

With - null

This always happens irrespective of single or multiple threads.

Scenario 2:
Even without transaction when I try to execute getLastBookmark() from multiple threads, it returns null intermittently.

      Thread t2 = new Thread(() -> {
        for (int i = 0; i < 100; i++) {
            Session session = sessionFactory.openSession();
            session.query("MATCH (n) RETURN count(n)", new HashMap<>());
            String lastBookmark = session.getLastBookmark();
            System.out.println("lastBookmark" + " - " + lastBookmark);
            if (lastBookmark == null) {
                throw new RuntimeException(" lastBookmark NULL");
            }
        }
    });

    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 100; i++) {
            Session session = sessionFactory.openSession();
            session.query("MATCH (n) RETURN count(n)", new HashMap<>());
            String lastBookmark = session.getLastBookmark();
            System.out.println("lastBookmark" + " - " + lastBookmark);
            if (lastBookmark == null) {
                throw new RuntimeException(" lastBookmark NULL");
            }
        }
    });

Output:

lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - null
Exception in thread "Thread-2" java.lang.RuntimeException:  lastBookmark NULL
    at MyTest.lambda$testSession$4(MyTest.java:173)
    at java.lang.Thread.run(Thread.java:745)
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776
lastBookmark - neo4j:bookmark:v1:tx6776

Any ideas?

I am using neo4j-ogm-core:2.1.5 & neo4j-ogm-bolt-driver:2.1.5 dependencies.


Solution

  • The bookmarks are tied to transactions. They are sent by the database at the end of transactions.

    When you use query without opening a transaction before, an autocommit transaction is managed by OGM (it is an implicit transaction). The bookmark is available right after executing the query method.

    When managing yourself the transaction (explicit transaction), you have to wait the end of the transaction for the bookmark to be available.

    Regarding your second point, try updating driver and/or OGM. If the problem is still there, share a sample project reproducing the issue (you can use some templates here), preferably in another question for clarity.