Skip to content

Commit 7cd083b

Browse files
committed
Fix TTL parsing when driver configured to use JS numbers
Driver can be created with `{disableLosslessIntegers: true}` config. Then all integer numbers returned in query results will be `Number` instead of `neo4j.Integer`. Routing table response parsing code did not expect `Number`s and failed to parse the TTL entry. This commit fixes parsing by always wrapping returned value of TTL in a `neo4j.Integer`. Also improved error messages around routing response parsing to include the original error message.
1 parent 19063bd commit 7cd083b

File tree

3 files changed

+45
-31
lines changed

3 files changed

+45
-31
lines changed

src/v1/internal/routing-util.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ export default class RoutingUtil {
6363
parseTtl(record, routerAddress) {
6464
try {
6565
const now = int(Date.now());
66-
const expires = record.get('ttl').multiply(1000).add(now);
66+
const expires = int(record.get('ttl')).multiply(1000).add(now);
6767
// if the server uses a really big expire time like Long.MAX_VALUE this may have overflowed
6868
if (expires.lessThan(now)) {
6969
return Integer.MAX_VALUE;
7070
}
7171
return expires;
7272
} catch (error) {
7373
throw newError(
74-
'Unable to parse TTL entry from router ' + routerAddress + ' from record:\n' + JSON.stringify(record),
74+
`Unable to parse TTL entry from router ${routerAddress} from record:\n${JSON.stringify(record)}\nError message: ${error.message}`,
7575
PROTOCOL_ERROR);
7676
}
7777
}
@@ -104,9 +104,9 @@ export default class RoutingUtil {
104104
readers: readers,
105105
writers: writers
106106
}
107-
} catch (ignore) {
107+
} catch (error) {
108108
throw newError(
109-
'Unable to parse servers entry from router ' + routerAddress + ' from record:\n' + JSON.stringify(record),
109+
`Unable to parse servers entry from router ${routerAddress} from record:\n${JSON.stringify(record)}\nError message: ${error.message}`,
110110
PROTOCOL_ERROR);
111111
}
112112
}

test/internal/routing-util.test.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,18 @@ describe('RoutingUtil', () => {
238238
});
239239

240240
function testValidTtlParsing(currentTime, ttlSeconds) {
241-
const record = newRecord({ttl: int(ttlSeconds)});
242241
clock.setSystemTime(currentTime);
242+
const expectedExpirationTime = currentTime + ttlSeconds * 1000;
243243

244-
const expirationTime = parseTtl(record).toNumber();
244+
// verify parsing when TTL is an Integer
245+
const record1 = newRecord({ttl: int(ttlSeconds)});
246+
const expirationTime1 = parseTtl(record1).toNumber();
247+
expect(expirationTime1).toEqual(expectedExpirationTime);
245248

246-
expect(expirationTime).toEqual(currentTime + ttlSeconds * 1000);
249+
// verify parsing when TTL is a JavaScript Number, this can happen when driver is configured with {disableLosslessIntegers: true}
250+
const record2 = newRecord({ttl: ttlSeconds});
251+
const expirationTime2 = parseTtl(record2).toNumber();
252+
expect(expirationTime2).toEqual(expectedExpirationTime);
247253
}
248254

249255
function testValidServersParsing(routerAddresses, readerAddresses, writerAddresses) {

test/v1/routing.driver.boltkit.test.js

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,31 +1916,11 @@ describe('routing driver with stub server', () => {
19161916
});
19171917

19181918
it('should rediscover using older getServers procedure when server is old', done => {
1919-
if (!boltStub.supported) {
1920-
done();
1921-
return;
1922-
}
1923-
1924-
const router = boltStub.start('./test/resources/boltstub/acquire_endpoints_old_routing_procedure.script', 9001);
1925-
const reader = boltStub.start('./test/resources/boltstub/read_server.script', 9005);
1926-
1927-
boltStub.run(() => {
1928-
const driver = boltStub.newDriver('bolt+routing://127.0.0.1:9001');
1919+
testDiscoveryAndReadQueryInAutoCommitTx('./test/resources/boltstub/acquire_endpoints_old_routing_procedure.script', {}, done);
1920+
});
19291921

1930-
const session = driver.session(READ);
1931-
session.run('MATCH (n) RETURN n.name').then(result => {
1932-
expect(result.records.map(record => record.get(0))).toEqual(['Bob', 'Alice', 'Tina']);
1933-
session.close();
1934-
driver.close();
1935-
router.exit(code1 => {
1936-
reader.exit(code2 => {
1937-
expect(code1).toEqual(0);
1938-
expect(code2).toEqual(0);
1939-
done();
1940-
});
1941-
});
1942-
}).catch(done.fail);
1943-
});
1922+
it('should connect to cluster when disableLosslessIntegers is on', done => {
1923+
testDiscoveryAndReadQueryInAutoCommitTx('./test/resources/boltstub/acquire_endpoints.script', {disableLosslessIntegers: true}, done);
19441924
});
19451925

19461926
function testAddressPurgeOnDatabaseError(query, accessMode, done) {
@@ -2031,6 +2011,34 @@ describe('routing driver with stub server', () => {
20312011
});
20322012
}
20332013

2014+
function testDiscoveryAndReadQueryInAutoCommitTx(routerScript, driverConfig, done) {
2015+
if (!boltStub.supported) {
2016+
done();
2017+
return;
2018+
}
2019+
2020+
const router = boltStub.start(routerScript, 9001);
2021+
const reader = boltStub.start('./test/resources/boltstub/read_server.script', 9005);
2022+
2023+
boltStub.run(() => {
2024+
const driver = boltStub.newDriver('bolt+routing://127.0.0.1:9001', driverConfig);
2025+
2026+
const session = driver.session(READ);
2027+
session.run('MATCH (n) RETURN n.name').then(result => {
2028+
expect(result.records.map(record => record.get(0))).toEqual(['Bob', 'Alice', 'Tina']);
2029+
session.close();
2030+
driver.close();
2031+
router.exit(code1 => {
2032+
reader.exit(code2 => {
2033+
expect(code1).toEqual(0);
2034+
expect(code2).toEqual(0);
2035+
done();
2036+
});
2037+
});
2038+
}).catch(done.fail);
2039+
});
2040+
}
2041+
20342042
function testForProtocolError(scriptFile, done) {
20352043
if (!boltStub.supported) {
20362044
done();

0 commit comments

Comments
 (0)