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?
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. 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
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. :-)