Skip to content

Commit 4e8afd7

Browse files
committed
Do not add seed router to the initial routing table
1 parent 1759015 commit 4e8afd7

10 files changed

+104
-88
lines changed

src/v1/internal/connection-providers.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class LoadBalancer extends ConnectionProvider {
6464
constructor(address, routingContext, connectionPool, loadBalancingStrategy, hostNameResolver, driverOnErrorCallback, log) {
6565
super();
6666
this._seedRouter = address;
67-
this._routingTable = new RoutingTable([this._seedRouter]);
67+
this._routingTable = new RoutingTable();
6868
this._rediscovery = new Rediscovery(new RoutingUtil(routingContext));
6969
this._connectionPool = connectionPool;
7070
this._driverOnErrorCallback = driverOnErrorCallback;
@@ -259,11 +259,8 @@ export class LoadBalancer extends ConnectionProvider {
259259
}
260260

261261
_updateRoutingTable(newRoutingTable) {
262-
const currentRoutingTable = this._routingTable;
263-
264262
// close old connections to servers not present in the new routing table
265-
const staleServers = currentRoutingTable.serversDiff(newRoutingTable);
266-
staleServers.forEach(server => this._connectionPool.purge(server));
263+
this._connectionPool.keepAll(newRoutingTable.allServers());
267264

268265
// make this driver instance aware of the new table
269266
this._routingTable = newRoutingTable;

src/v1/internal/pool.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ class Pool {
115115
Object.keys(this._pools).forEach(key => this._purgeKey(key));
116116
}
117117

118+
/**
119+
* Keep the idle resources for the provided addresses and purge the rest.
120+
*/
121+
keepAll(addresses) {
122+
const keysToKeep = addresses.map(a => a.asKey());
123+
const keysPresent = Object.keys(this._pools);
124+
const keysToPurge = keysPresent.filter(k => keysToKeep.indexOf(k) == -1);
125+
126+
keysToPurge.forEach(key => this._purgeKey(key));
127+
}
128+
118129
/**
119130
* Check if this pool contains resources for the given address.
120131
* @param {ServerAddress} address the address of the server to check.

src/v1/internal/routing-table.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,6 @@ export default class RoutingTable {
4747
this.writers = removeFromArray(this.writers, address);
4848
}
4949

50-
serversDiff(otherRoutingTable) {
51-
const oldServers = this._allServers();
52-
const newServers = otherRoutingTable._allServers();
53-
const diffTable = {};
54-
oldServers.forEach(oldServer => diffTable[oldServer.asKey()] = oldServer);
55-
newServers.forEach(newServer => delete diffTable[newServer.asKey()]);
56-
return Object.values(diffTable);
57-
}
58-
5950
/**
6051
* Check if this routing table is fresh to perform the required operation.
6152
* @param {string} accessMode the type of operation. Allowed values are {@link READ} and {@link WRITE}.
@@ -68,7 +59,7 @@ export default class RoutingTable {
6859
accessMode === WRITE && this.writers.length === 0;
6960
}
7061

71-
_allServers() {
62+
allServers() {
7263
return [...this.routers, ...this.readers, ...this.writers];
7364
}
7465

test/internal/connection-providers.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('LoadBalancer', () => {
174174
NO_OP_DRIVER_CALLBACK, Logger.noOp());
175175

176176
expectRoutingTable(loadBalancer,
177-
[serverABC],
177+
[],
178178
[],
179179
[]
180180
);

test/internal/node/routing.driver.boltkit.test.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ describe('routing driver with stub server', () => {
562562
// When
563563
const session1 = driver.session(neo4j.session.READ);
564564
session1.run("MATCH (n) RETURN n.name").catch(() => {
565+
const session2 = driver.session(neo4j.session.READ);
566+
session2.run('MATCH (n) RETURN n.name').then(() => {
565567
driver.close();
566568
seedServer.exit(code1 => {
567569
readServer.exit(code2 => {
@@ -570,6 +572,7 @@ describe('routing driver with stub server', () => {
570572
done();
571573
});
572574
});
575+
});
573576
});
574577
});
575578
});
@@ -2131,13 +2134,13 @@ describe('routing driver with stub server', () => {
21312134
// the first seed to get the routing table
21322135
// the returned routing table includes a non-reachable read-server and points to only one router
21332136
// which will return an invalid routing table
2134-
const seedServer1 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_point_to_empty_router.script', 9001);
2137+
const router1 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_point_to_empty_router_and_exit.script', 9001);
21352138
// returns an empty routing table
2136-
const failingSeedServer2 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_empty.script', 9004);
2139+
const router2 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_empty.script', 9004);
21372140
// returns a normal routing table
2138-
const seedServer3 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_three_servers.script', 9003);
2141+
const router3 = boltStub.start('./test/resources/boltstub/acquire_endpoints_v3_three_servers_and_exit.script', 9003);
21392142
// ordinary read server
2140-
const readServer = boltStub.start('./test/resources/boltstub/read_server_v3_read_tx.script', 9002);
2143+
const reader = boltStub.start('./test/resources/boltstub/read_server_v3_read_tx.script', 9002);
21412144

21422145
boltStub.run(() => {
21432146
const driver = boltStub.newDriver('bolt+routing://my.virtual.host:8080', {
@@ -2148,10 +2151,10 @@ describe('routing driver with stub server', () => {
21482151
session.readTransaction(tx => tx.run('MATCH (n) RETURN n.name')).then(res => {
21492152
session.close();
21502153
driver.close();
2151-
seedServer1.exit(code1 => {
2152-
failingSeedServer2.exit(code2 => {
2153-
seedServer3.exit(code3 => {
2154-
readServer.exit(code4 => {
2154+
router1.exit(code1 => {
2155+
router2.exit(code2 => {
2156+
router3.exit(code3 => {
2157+
reader.exit(code4 => {
21552158
expect(code1).toEqual(0);
21562159
expect(code2).toEqual(0);
21572160
expect(code3).toEqual(0);

test/internal/pool.test.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,83 @@ describe('Pool', () => {
296296
});
297297
});
298298

299+
it('purges keys other than the ones to keep', done => {
300+
let counter = 0;
301+
302+
const address1 = ServerAddress.fromUrl('bolt://localhost:7687');
303+
const address2 = ServerAddress.fromUrl('bolt://localhost:7688');
304+
const address3 = ServerAddress.fromUrl('bolt://localhost:7689');
305+
306+
const pool = new Pool((server, release) => Promise.resolve(new Resource(server, counter++, release)),
307+
res => {
308+
res.destroyed = true;
309+
return true;
310+
}
311+
);
312+
313+
const acquiredResources = [
314+
pool.acquire(address1),
315+
pool.acquire(address2),
316+
pool.acquire(address3),
317+
pool.acquire(address1),
318+
pool.acquire(address2),
319+
pool.acquire(address3)
320+
];
321+
322+
Promise.all(acquiredResources).then(values => {
323+
expect(pool.has(address1)).toBeTruthy();
324+
expect(pool.has(address2)).toBeTruthy();
325+
expect(pool.has(address3)).toBeTruthy();
326+
327+
pool.keepAll([address1, address3]);
328+
329+
expect(pool.has(address1)).toBeTruthy();
330+
expect(pool.has(address3)).toBeTruthy();
331+
expect(pool.has(address2)).toBeFalsy();
332+
333+
done();
334+
});
335+
});
336+
337+
it('purges all keys if addresses to keep is empty', done => {
338+
let counter = 0;
339+
340+
const address1 = ServerAddress.fromUrl('bolt://localhost:7687');
341+
const address2 = ServerAddress.fromUrl('bolt://localhost:7688');
342+
const address3 = ServerAddress.fromUrl('bolt://localhost:7689');
343+
344+
const pool = new Pool((server, release) => Promise.resolve(new Resource(server, counter++, release)),
345+
res => {
346+
res.destroyed = true;
347+
return true;
348+
}
349+
);
350+
351+
const acquiredResources = [
352+
pool.acquire(address1),
353+
pool.acquire(address2),
354+
pool.acquire(address3),
355+
pool.acquire(address1),
356+
pool.acquire(address2),
357+
pool.acquire(address3)
358+
];
359+
360+
Promise.all(acquiredResources).then(values => {
361+
expect(pool.has(address1)).toBeTruthy();
362+
expect(pool.has(address2)).toBeTruthy();
363+
expect(pool.has(address3)).toBeTruthy();
364+
365+
pool.keepAll([]);
366+
367+
expect(pool.has(address1)).toBeFalsy();
368+
expect(pool.has(address3)).toBeFalsy();
369+
expect(pool.has(address2)).toBeFalsy();
370+
371+
done();
372+
});
373+
});
374+
375+
299376
it('skips broken connections during acquire', (done) => {
300377
let validated = false;
301378
let counter = 0;

test/internal/rediscovery.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ describe('rediscovery', () => {
180180

181181
expect(routingTable.expirationTime).toEqual(expires);
182182

183-
const allServers = routingTable.serversDiff(new RoutingTable()).sort();
183+
const allServers = routingTable.allServers().sort();
184184
const allExpectedServers = [...routerAddresses, ...readerAddresses, ...writerAddresses].sort();
185185
expect(allServers.map(s => s.asHostPort())).toEqual(allExpectedServers);
186186

test/internal/routing-table.test.js

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -127,69 +127,6 @@ describe('routing-table', () => {
127127
expect(table.writers).toEqual([server5]);
128128
});
129129

130-
it('should return all servers in diff when other table is empty', () => {
131-
const oldTable = createTable([server1, server2], [server3, server4], [server5, server6], notExpired());
132-
const newTable = createTable([], [], [], notExpired());
133-
134-
const servers = oldTable.serversDiff(newTable);
135-
136-
expect(servers).toEqual([server1, server2, server3, server4, server5, server6]);
137-
});
138-
139-
it('should no servers in diff when this table is empty', () => {
140-
const oldTable = createTable([], [], [], notExpired());
141-
const newTable = createTable([server1, server2], [server3, server4], [server5, server6], notExpired());
142-
143-
const servers = oldTable.serversDiff(newTable);
144-
145-
expect(servers).toEqual([]);
146-
});
147-
148-
it('should include different routers in servers diff', () => {
149-
const oldTable = createTable([server1, server7, server2, server42], [server3, server4], [server5, server6], notExpired());
150-
const newTable = createTable([server1, server2], [server3, server4], [server5, server6], notExpired());
151-
152-
const servers = oldTable.serversDiff(newTable);
153-
154-
expect(servers).toEqual([server7, server42]);
155-
});
156-
157-
it('should include different readers in servers diff', () => {
158-
const oldTable = createTable([server1, server2], [server3, server7, server4, server42], [server5, server6], notExpired());
159-
const newTable = createTable([server1, server2], [server3, server4], [server5, server6], notExpired());
160-
161-
const servers = oldTable.serversDiff(newTable);
162-
163-
expect(servers).toEqual([server7, server42]);
164-
});
165-
166-
it('should include different writers in servers diff', () => {
167-
const oldTable = createTable([server1, server2], [server3, server4], [server5, server7, server6, server42], notExpired());
168-
const newTable = createTable([server1, server2], [server3, server4], [server5, server6], notExpired());
169-
170-
const servers = oldTable.serversDiff(newTable);
171-
172-
expect(servers).toEqual([server7, server42]);
173-
});
174-
175-
it('should include different servers in diff', () => {
176-
const oldTable = createTable([server1, server2, server11], [server22, server3, server33, server4], [server5, server44, server6], notExpired());
177-
const newTable = createTable([server1], [server2, server3, server4, server6], [server5], notExpired());
178-
179-
const servers = oldTable.serversDiff(newTable);
180-
181-
expect(servers).toEqual([server11, server22, server33, server44]);
182-
});
183-
184-
it('should include different servers in diff with logical equality', () => {
185-
const oldTable = createTable([server1, server11], [server2, server22], [server3, server33], notExpired());
186-
const newTable = createTable([ServerAddress.fromUrl(server1.asHostPort())], [ServerAddress.fromUrl(server2.asHostPort())], [ServerAddress.fromUrl(server3.asHostPort())], notExpired());
187-
188-
const servers = oldTable.serversDiff(newTable);
189-
190-
expect(servers).toEqual([server11, server22, server33]);
191-
});
192-
193130
it('should have correct toString', () => {
194131
const originalDateNow = Date.now;
195132
try {

0 commit comments

Comments
 (0)