@@ -21,6 +21,7 @@ import { Connection, DelegateConnection } from '../../src/connection'
21
21
import { authTokenManagers , internal , newError , ServerInfo , staticAuthTokenManager } from 'neo4j-driver-core'
22
22
import AuthenticationProvider from '../../src/connection-provider/authentication-provider'
23
23
import { functional } from '../../src/lang'
24
+ import LivenessCheckProvider from '../../src/connection-provider/liveness-check-provider'
24
25
25
26
const {
26
27
serverAddress : { ServerAddress } ,
@@ -281,16 +282,23 @@ describe('constructor', () => {
281
282
} )
282
283
283
284
it ( 'should register the release function into the connection' , async ( ) => {
284
- const { create } = setup ( )
285
- const releaseResult = { property : 'some property' }
286
- const release = jest . fn ( ( ) => releaseResult )
285
+ jest . useFakeTimers ( )
286
+ try {
287
+ const { create } = setup ( )
288
+ const releaseResult = { property : 'some property' }
289
+ const release = jest . fn ( ( ) => releaseResult )
287
290
288
- const connection = await create ( { } , server0 , release )
291
+ const connection = await create ( { } , server0 , release )
292
+ connection . idleTimestamp = - 1234
289
293
290
- const released = connection . release ( )
294
+ const released = connection . release ( )
291
295
292
- expect ( released ) . toBe ( releaseResult )
293
- expect ( release ) . toHaveBeenCalledWith ( server0 , connection )
296
+ expect ( released ) . toBe ( releaseResult )
297
+ expect ( release ) . toHaveBeenCalledWith ( server0 , connection )
298
+ expect ( connection . idleTimestamp ) . toBeCloseTo ( Date . now ( ) )
299
+ } finally {
300
+ jest . useRealTimers ( )
301
+ }
294
302
} )
295
303
296
304
it . each ( [
@@ -361,26 +369,27 @@ describe('constructor', () => {
361
369
const connection = new FakeConnection ( server0 )
362
370
connection . creationTimestamp = Date . now ( )
363
371
364
- const { validateOnAcquire, authenticationProviderHook } = setup ( )
372
+ const { validateOnAcquire, authenticationProviderHook, livenessCheckProviderHook } = setup ( )
365
373
366
374
await expect ( validateOnAcquire ( { auth } , connection ) ) . resolves . toBe ( true )
367
375
368
376
expect ( authenticationProviderHook . authenticate ) . toHaveBeenCalledWith ( {
369
377
connection, auth
370
378
} )
379
+ expect ( livenessCheckProviderHook . check ) . toHaveBeenCalledWith ( connection )
371
380
} )
372
381
373
382
it . each ( [
374
383
null ,
375
384
undefined ,
376
385
{ scheme : 'bearer' , credentials : 'token01' }
377
- ] ) ( 'should return true when connection is open and within the lifetime and authentication fails (auth=%o)' , async ( auth ) => {
386
+ ] ) ( 'should return false when connection is open and within the lifetime and authentication fails (auth=%o)' , async ( auth ) => {
378
387
const connection = new FakeConnection ( server0 )
379
388
const error = newError ( 'failed' )
380
389
const authenticationProvider = jest . fn ( ( ) => Promise . reject ( error ) )
381
390
connection . creationTimestamp = Date . now ( )
382
391
383
- const { validateOnAcquire, authenticationProviderHook, log } = setup ( { authenticationProvider } )
392
+ const { validateOnAcquire, authenticationProviderHook, log, livenessCheckProviderHook } = setup ( { authenticationProvider } )
384
393
385
394
await expect ( validateOnAcquire ( { auth } , connection ) ) . resolves . toBe ( false )
386
395
@@ -391,6 +400,7 @@ describe('constructor', () => {
391
400
expect ( log . debug ) . toHaveBeenCalledWith (
392
401
`The connection ${ connection . id } is not valid because of an error ${ error . code } '${ error . message } '`
393
402
)
403
+ expect ( livenessCheckProviderHook . check ) . toHaveBeenCalledWith ( connection )
394
404
} )
395
405
396
406
it . each ( [
@@ -401,45 +411,67 @@ describe('constructor', () => {
401
411
const auth = { }
402
412
connection . creationTimestamp = Date . now ( )
403
413
404
- const { validateOnAcquire, authenticationProviderHook } = setup ( )
414
+ const { validateOnAcquire, authenticationProviderHook, livenessCheckProviderHook } = setup ( )
405
415
406
416
await expect ( validateOnAcquire ( { auth, skipReAuth } , connection ) ) . resolves . toBe ( true )
407
417
408
418
expect ( authenticationProviderHook . authenticate ) . toHaveBeenCalledWith ( {
409
419
connection, auth, skipReAuth
410
420
} )
421
+ expect ( livenessCheckProviderHook . check ) . toHaveBeenCalledWith ( connection )
422
+ } )
423
+
424
+ it ( 'should return false when liveness checks fails' , async ( ) => {
425
+ const connection = new FakeConnection ( server0 )
426
+ connection . creationTimestamp = Date . now ( )
427
+ const error = newError ( '#themessage' , '#thecode' )
428
+
429
+ const { validateOnAcquire, authenticationProviderHook, log, livenessCheckProviderHook } = setup ( {
430
+ livenessCheckProvider : ( ) => Promise . reject ( error )
431
+ } )
432
+
433
+ await expect ( validateOnAcquire ( { } , connection ) ) . resolves . toBe ( false )
434
+
435
+ expect ( livenessCheckProviderHook . check ) . toBeCalledWith ( connection )
436
+ expect ( log . debug ) . toBeCalledWith (
437
+ `The connection ${ connection . id } is not alive because of an error ${ error . code } '${ error . message } '`
438
+ )
439
+ expect ( authenticationProviderHook . authenticate ) . not . toHaveBeenCalled ( )
411
440
} )
412
441
413
442
it ( 'should return false when connection is closed and within the lifetime' , async ( ) => {
414
443
const connection = new FakeConnection ( server0 )
415
444
connection . creationTimestamp = Date . now ( )
416
445
await connection . close ( )
417
446
418
- const { validateOnAcquire, authenticationProviderHook } = setup ( )
447
+ const { validateOnAcquire, authenticationProviderHook, livenessCheckProviderHook } = setup ( )
419
448
420
449
await expect ( validateOnAcquire ( { } , connection ) ) . resolves . toBe ( false )
421
450
expect ( authenticationProviderHook . authenticate ) . not . toHaveBeenCalled ( )
451
+ expect ( livenessCheckProviderHook . check ) . not . toHaveBeenCalled ( )
422
452
} )
423
453
424
454
it ( 'should return false when connection is open and out of the lifetime' , async ( ) => {
425
455
const connection = new FakeConnection ( server0 )
426
456
connection . creationTimestamp = Date . now ( ) - 4000
427
457
428
- const { validateOnAcquire, authenticationProviderHook } = setup ( { maxConnectionLifetime : 3000 } )
458
+ const { validateOnAcquire, authenticationProviderHook, livenessCheckProviderHook } = setup ( { maxConnectionLifetime : 3000 } )
429
459
430
460
await expect ( validateOnAcquire ( { } , connection ) ) . resolves . toBe ( false )
431
461
expect ( authenticationProviderHook . authenticate ) . not . toHaveBeenCalled ( )
462
+ expect ( livenessCheckProviderHook . check ) . not . toHaveBeenCalled ( )
432
463
} )
433
464
434
465
it ( 'should return false when connection is closed and out of the lifetime' , async ( ) => {
435
466
const connection = new FakeConnection ( server0 )
436
467
await connection . close ( )
437
468
connection . creationTimestamp = Date . now ( ) - 4000
438
469
439
- const { validateOnAcquire, authenticationProviderHook } = setup ( { maxConnectionLifetime : 3000 } )
470
+ const { validateOnAcquire, authenticationProviderHook, livenessCheckProviderHook } = setup ( { maxConnectionLifetime : 3000 } )
440
471
441
472
await expect ( validateOnAcquire ( { } , connection ) ) . resolves . toBe ( false )
442
473
expect ( authenticationProviderHook . authenticate ) . not . toHaveBeenCalled ( )
474
+ expect ( livenessCheckProviderHook . check ) . not . toHaveBeenCalled ( )
443
475
} )
444
476
} )
445
477
@@ -492,14 +524,17 @@ describe('constructor', () => {
492
524
} )
493
525
} )
494
526
495
- function setup ( { createConnection, authenticationProvider, maxConnectionLifetime } = { } ) {
527
+ function setup ( { createConnection, authenticationProvider, maxConnectionLifetime, livenessCheckProvider } = { } ) {
496
528
const newPool = jest . fn ( ( ...args ) => new Pool ( ...args ) )
497
529
const log = new Logger ( 'debug' , ( ) => undefined )
498
530
jest . spyOn ( log , 'debug' )
499
531
const createChannelConnectionHook = createConnection || jest . fn ( async ( address ) => new FakeConnection ( address ) )
500
532
const authenticationProviderHook = new AuthenticationProvider ( { } )
533
+ const livenessCheckProviderHook = new LivenessCheckProvider ( { } )
501
534
jest . spyOn ( authenticationProviderHook , 'authenticate' )
502
535
. mockImplementation ( authenticationProvider || jest . fn ( ( { connection } ) => Promise . resolve ( connection ) ) )
536
+ jest . spyOn ( livenessCheckProviderHook , 'check' )
537
+ . mockImplementation ( livenessCheckProvider || jest . fn ( ( ) => Promise . resolve ( true ) ) )
503
538
const provider = new DirectConnectionProvider ( {
504
539
newPool,
505
540
config : {
@@ -510,11 +545,13 @@ describe('constructor', () => {
510
545
} )
511
546
provider . _createChannelConnection = createChannelConnectionHook
512
547
provider . _authenticationProvider = authenticationProviderHook
548
+ provider . _livenessCheckProvider = livenessCheckProviderHook
513
549
return {
514
550
provider,
515
551
...newPool . mock . calls [ 0 ] [ 0 ] ,
516
552
createChannelConnectionHook,
517
553
authenticationProviderHook,
554
+ livenessCheckProviderHook,
518
555
log
519
556
}
520
557
}
@@ -812,6 +849,22 @@ class FakeConnection extends Connection {
812
849
return this . _supportsReAuth
813
850
}
814
851
852
+ set creationTimestamp ( value ) {
853
+ this . _creationTimestamp = value
854
+ }
855
+
856
+ get creationTimestamp ( ) {
857
+ return this . _creationTimestamp
858
+ }
859
+
860
+ set idleTimestamp ( value ) {
861
+ this . _idleTimestamp = value
862
+ }
863
+
864
+ get idleTimestamp ( ) {
865
+ return this . _idleTimestamp
866
+ }
867
+
815
868
async close ( ) {
816
869
this . _closed = true
817
870
}
0 commit comments