@@ -23,8 +23,6 @@ import {newError, SERVICE_UNAVAILABLE, SESSION_EXPIRED} from "./error";
2323import RoundRobinArray from './internal/round-robin-array' ;
2424import "babel-polyfill" ;
2525
26-
27-
2826/**
2927 * A driver that supports routing in a core-edge cluster.
3028 */
@@ -35,9 +33,40 @@ class RoutingDriver extends Driver {
3533 this . _clusterView = new ClusterView ( new RoundRobinArray ( [ url ] ) ) ;
3634 }
3735
38- session ( mode ) {
39- let conn = this . _acquireConnection ( mode ) ;
40- return this . _createSession ( conn ) ;
36+ _createSession ( connectionPromise , cb ) {
37+ return new RoutingSession ( connectionPromise , cb , ( err , conn ) => {
38+ let code = err . code ;
39+ if ( ! code ) {
40+ try {
41+ code = err . fields [ 0 ] . code ;
42+ } catch ( e ) {
43+ code = 'UNKNOWN' ;
44+ }
45+ }
46+
47+ if ( code === SERVICE_UNAVAILABLE || code === SESSION_EXPIRED ) {
48+ if ( conn ) {
49+ this . _forget ( conn . url )
50+ } else {
51+ connectionPromise . then ( ( conn ) => {
52+ this . _forget ( conn . url ) ;
53+ } ) ;
54+ }
55+ return err ;
56+ } else if ( code === 'Neo.ClientError.Cluster.NotALeader' ) {
57+ let url = 'UNKNOWN' ;
58+ if ( conn ) {
59+ url = conn . url ;
60+ this . _clusterView . writers . remove ( conn . url ) ;
61+ } else {
62+ connectionPromise . then ( ( conn ) => {
63+ this . _clusterView . writers . remove ( conn . url ) ;
64+ } ) ;
65+ }
66+
67+ return newError ( "No longer possible to write to server at " + url , SESSION_EXPIRED ) ;
68+ }
69+ } ) ;
4170 }
4271
4372 _updatedClusterView ( ) {
@@ -60,6 +89,7 @@ class RoutingDriver extends Driver {
6089 return acc ;
6190 }
6291 }
92+
6393 _diff ( oldView , updatedView ) {
6494 let oldSet = oldView . all ( ) ;
6595 let newSet = updatedView . all ( ) ;
@@ -81,9 +111,17 @@ class RoutingDriver extends Driver {
81111 //update our cached view
82112 this . _clusterView = view ;
83113 if ( m === READ ) {
84- return this . _pool . acquire ( view . readers . hop ( ) ) ;
114+ let key = view . readers . hop ( ) ;
115+ if ( ! key ) {
116+ return Promise . reject ( newError ( 'No read servers available' , SESSION_EXPIRED ) ) ;
117+ }
118+ return this . _pool . acquire ( key ) ;
85119 } else if ( m === WRITE ) {
86- return this . _pool . acquire ( view . writers . hop ( ) ) ;
120+ let key = view . writers . hop ( ) ;
121+ if ( ! key ) {
122+ return Promise . reject ( newError ( 'No write servers available' , SESSION_EXPIRED ) ) ;
123+ }
124+ return this . _pool . acquire ( key ) ;
87125 } else {
88126 return Promise . reject ( m + " is not a valid option" ) ;
89127 }
@@ -96,7 +134,6 @@ class RoutingDriver extends Driver {
96134 }
97135}
98136
99-
100137class ClusterView {
101138 constructor ( routers , readers , writers , expires ) {
102139 this . routers = routers || new RoundRobinArray ( ) ;
@@ -133,6 +170,17 @@ class ClusterView {
133170 }
134171}
135172
173+ class RoutingSession extends Session {
174+ constructor ( connectionPromise , onClose , onFailedConnection ) {
175+ super ( connectionPromise , onClose ) ;
176+ this . _onFailedConnection = onFailedConnection ;
177+ }
178+
179+ _onRunFailure ( ) {
180+ return this . _onFailedConnection ;
181+ }
182+ }
183+
136184let GET_SERVERS = "CALL dbms.cluster.routing.getServers" ;
137185
138186/**
@@ -170,6 +218,9 @@ function newClusterView(session) {
170218 }
171219 }
172220 return new ClusterView ( routers , readers , writers , expires ) ;
221+ } )
222+ . catch ( ( ) => {
223+ return Promise . reject ( newError ( "No servers could be found at this instant." , SERVICE_UNAVAILABLE ) ) ;
173224 } ) ;
174225}
175226
0 commit comments