liberation-data / drivine

Best and fastest graph database client (Neo4j, AgensGraph, Apache AGE, FalkorDB) for Node.js & TypeScript.
https://drivine.org
Apache License 2.0
152 stars 33 forks source link

Could not perform discovery errors #111

Open tgod009 opened 1 year ago

tgod009 commented 1 year ago

Code that's throwing error:

clients.map(async (client) => {
      let tenant = client.tenant;
      let clientId = client.client_id;
      let clientName = client.name;

      const query = new QuerySpecification()
        .withStatement(
          "MERGE(c:Client {client_id: '$clientId', app_name: '$clientName'})-[r:CLIENT_OF]->(t:Tenant {name: '$tenant'})'RETURN c, r, t'",
        )
        .bind([clientId, clientName, tenant]);
      await this.persistenceManager.execute(query);
  Full error

  Error: Cannot run query in this transaction, because it has already been committed.
at Function.withRootCause (/home/taylor/modsquad/cubeless-backend/app/node_modules/@liberation-data/src/DrivineError.ts:8:16)
at Transaction.query (/home/taylor/modsquad/cubeless-backend/app/node_modules/@liberation-data/src/transaction/Transaction.ts:51:32)
at TransactionalPersistenceManager.execute (/home/taylor/modsquad/cubeless-backend/app/node_modules/@liberation-data/src/manager/TransactionalPersistenceManager.ts:28:9)
at /home/taylor/modsquad/cubeless-backend/app/src/clients/clients.service.ts:54:7
jasperblues commented 1 year ago

@tgod009 I have seen this error on recent Neo4j JS driver. Can you please try using the Neo4j driver directly? Does it work?

tgod009 commented 1 year ago

@jasperblues finally got around to trying with the neo4j driver directly and it worked. Any ideas why that is?

jasperblues commented 1 year ago

@tgod009 are you able to share a sample where it works directly but not with drivine? That would be much appreciated and should certainly lead to a solution.

tgod009 commented 1 year ago

I just initalized the driver in my service file and called the session like so

const session = this.driver.session();
    session
      .run('Merge (a:Application {name: $appName})', {
        appName: createUserApplications.app_name,
      })
      .then((result) => {
        return result.records.map((record) => {
          return record.get('a');
        });
      })
      .catch((error) => {
        console.log(error);
      })
      .then(() => {
        session.close();
      });
jasperblues commented 1 year ago

And the same thing does not work for you drivine @tgod009 ?

tgod009 commented 1 year ago

Running Drivine like this throws the routing table error

const query = new QuerySpecification()
      .withStatement('Merge(a:Application {name: $appName})')
      .bind(createUserApplications);
    return this.persistenceManager.execute(query);
 ERROR [ExceptionsHandler] Could not perform discovery. No routing servers available. Known routing table: RoutingTable[database=default database, expirationTime=0, currentTime=1679379048963, routers=[], readers=[], writers=[]]
jasperblues commented 1 year ago

Here's what I did to make it work:

    @Transactional()
    async createApp(name: string): Promise<void> {
        const query = new QuerySpecification()
            .withStatement('Merge(a:Application {name: $appName})')
            .bind({appName: name});
        return this.persistenceManager.execute(query);
    }

^-- Note that the params are slightly different. Since we bind name parameters we supply the name.

Final Step

Modify the RouteRepository.spec.ts. Add this test:

    it('should create an app', async () => {
        await repo.createApp("foobar")
    });

The test passes. If you want to see the result in the DB, at the top of that file change the following:

RunWithDrivine({rollback: false}); <-- change rollback to false

If you follow the approach above, does it work for you? The may be an issue but the above works for me.

tgod009 commented 1 year ago

That's with the sample application?

jasperblues commented 1 year ago

No, I just added it to Drivine directly. You can clone that repo, create an env file, then run the tests.

Run this gist for most tests to pass: https://gist.github.com/jasperblues/7a6e774090c9ef0f18c44920b48b6b23

There are two tests that need additional setup steps. Don't worry about those, just add the code above and let me know what happens with your Neo4j server. If it works - it was a setup issue. If it does, its something environment related.

I was going to add to the sample app, but I think I need to freshen dependencies. (Will do shortly).

tgod009 commented 1 year ago

I gave it try and I got the same error using my db info

Error: Could not perform discovery. No routing servers available. Known routing table: RoutingTable[database=default database, expirationTime=0, currentTime=1679435963014, routers=[], readers=[], writers=[]]
tgod009 commented 1 year ago

Side note not sure if this effects it but I'm using Aura not a local DB with the encrypted url

jasperblues commented 1 year ago

@tgod009 I will see if I can reproduce with Aura.

tgod009 commented 1 year ago

Not sure if this was causing it but I did just notice that I was using the non encrypted protocol

jasperblues commented 1 year ago

If you can try with both and compare results that would be great. This is puzzling!