Implementing bolt+routing://

When it comes to building support for bolt+routing://, is it mainly a matter of routing queries that contain MERGE, CREATE, SET, and DELETE directives to the LEADER node? Can FOLLOWER nodes also accept writes at all?

Are there other special considerations for routing drivers to make?

A little experimentation shows the part about FOLLOWER nodes accepting writes is a resounding "no":

Unhandled exception: No write operations are allowed directly
on this database. Writes must pass through the leader. The role
of this server is: FOLLOWER
[Neo.ClientError.Cluster.NotALeader] (Neo4j::QueryException)

Still curious about the routing criteria, though. Is there a place in the docs that highlights it? It's unfortunately hard to google since everything I find just tells me how the driver handles routing for me. :smiley: Or does it seem more prudent to just provide different methods for read and write queries/transactions where the write version always goes to the leader?

I suppose I'd have to change up routing after a leader re-election, too. Is there any way to detect that without polling? For example, write errors occurring after the leader fails that I can tell the driver to refresh routing?

when using a connection URL of bolt+routing:// this indicates the session is now cluster aware, whereas bolt:// does not understand the other members in a cluster.
However it is not simply the bolt+routing:// connection URL is only half the story. It is also the usage of session.readTransaction() and session.writeTransaction() whereby each allows you to pass the Cypher to be executed. If you send a cypher statement through session.writeTransaction and the connection URL was bolt+routing:// then regardless of the member connected to, the Cypher write statement will be routed to the LEADER. As such if one connects to bolt+routing://<followerIP> and calls a session.writeTransaction() as the transaction is defined as a write it will automatically be routed to the LEADER.

It is important to note that Neo4j does not parse the Cypher statement to auto detect if the Cypher is a read or write statement.
So one could actually issue a session.readTransaction("create (n:Person {id:1})") and because it is defined as a 'readTransaction` it would be routed to a Follower, but then fail since only LEADERs can perform writes

1 Like

Excellent, the more I thought about it, the more this seemed like the right move for the driver I'm building. I didn't find it when searching, I just saw beginTransaction. :-)

Thanks @dana.canzano!