Skip to content

Commit 0ebdcca

Browse files
authored
Merge pull request #368 from lutovich/1.6-filter-in-pool
Couple fixes for release of broken connections to the pool
2 parents 398e443 + e87c70c commit 0ebdcca

File tree

2 files changed

+97
-7
lines changed

2 files changed

+97
-7
lines changed

src/v1/internal/pool.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,25 +154,25 @@ class Pool {
154154
// key has been purged, don't put it back, just destroy the resource
155155
this._destroy(resource);
156156
}
157+
resourceReleased(key, this._activeResourceCounts);
157158

158159
// check if there are any pending requests
159160
const requests = this._acquireRequests[key];
160161
if (requests) {
161-
const pending = requests.shift();
162+
const pending = requests[0];
162163

163164
if (pending) {
164165
const resource = this._acquire(key);
165166
if (resource) {
166-
pending.resolve(resource);
167-
168-
return;
167+
// managed to acquire a valid resource from the pool to satisfy the pending acquire request
168+
resourceAcquired(key, this._activeResourceCounts); // increment the active counter
169+
requests.shift(); // forget the pending request
170+
pending.resolve(resource); // resolve the pending request with the acquired resource
169171
}
170172
} else {
171173
delete this._acquireRequests[key];
172174
}
173175
}
174-
175-
resourceReleased(key, this._activeResourceCounts);
176176
}
177177
}
178178

test/internal/pool.test.js

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,16 +522,106 @@ describe('Pool', () => {
522522
});
523523
});
524524

525+
it('should resolve pending acquisition request when single invalid resource returned', done => {
526+
const key = 'bolt://localhost:7687';
527+
const acquisitionTimeout = 1000;
528+
let counter = 0;
529+
530+
const pool = new Pool(
531+
(url, release) => new Resource(url, counter++, release),
532+
resource => {
533+
},
534+
resourceValidOnlyOnceValidationFunction,
535+
new PoolConfig(1, acquisitionTimeout)
536+
);
537+
538+
pool.acquire(key).then(resource1 => {
539+
expect(resource1.id).toEqual(0);
540+
expect(pool.activeResourceCount(key)).toEqual(1);
541+
542+
// release the resource before the acquisition timeout, it should be treated as invalid
543+
setTimeout(() => {
544+
expectNumberOfAcquisitionRequests(pool, key, 1);
545+
resource1.close();
546+
}, acquisitionTimeout / 2);
547+
548+
pool.acquire(key).then(resource2 => {
549+
expect(resource2.id).toEqual(1);
550+
expectNoPendingAcquisitionRequests(pool);
551+
expect(pool.activeResourceCount(key)).toEqual(1);
552+
done();
553+
}).catch(error => {
554+
done.fail(error);
555+
});
556+
});
557+
});
558+
559+
it('should work fine when invalid resources released and acquisition attempt pending', done => {
560+
const key = 'bolt://localhost:7687';
561+
const acquisitionTimeout = 1000;
562+
let counter = 0;
563+
564+
const pool = new Pool(
565+
(url, release) => new Resource(url, counter++, release),
566+
resource => {
567+
},
568+
resourceValidOnlyOnceValidationFunction,
569+
new PoolConfig(2, acquisitionTimeout)
570+
);
571+
572+
pool.acquire(key).then(resource1 => {
573+
expect(resource1.id).toEqual(0);
574+
expect(pool.activeResourceCount(key)).toEqual(1);
575+
576+
pool.acquire(key).then(resource2 => {
577+
expect(resource2.id).toEqual(1);
578+
expect(pool.activeResourceCount(key)).toEqual(2);
579+
580+
// release both resources before the acquisition timeout, they should be treated as invalid
581+
setTimeout(() => {
582+
expectNumberOfAcquisitionRequests(pool, key, 1);
583+
resource1.close();
584+
resource2.close();
585+
}, acquisitionTimeout / 2);
586+
587+
pool.acquire(key).then(resource3 => {
588+
expect(resource3.id).toEqual(2);
589+
expectNoPendingAcquisitionRequests(pool);
590+
expect(pool.activeResourceCount(key)).toEqual(1);
591+
done();
592+
}).catch(error => {
593+
done.fail(error);
594+
});
595+
});
596+
});
597+
});
598+
525599
});
526600

527601
function expectNoPendingAcquisitionRequests(pool) {
528-
expect(pool._acquireRequests).toEqual({});
602+
const acquireRequests = pool._acquireRequests;
603+
Object.values(acquireRequests).forEach(requests => {
604+
if (Array.isArray(requests) && requests.length === 0) {
605+
requests = undefined;
606+
}
607+
expect(requests).not.toBeDefined();
608+
});
529609
}
530610

531611
function expectNumberOfAcquisitionRequests(pool, key, expectedNumber) {
532612
expect(pool._acquireRequests[key].length).toEqual(expectedNumber);
533613
}
534614

615+
function resourceValidOnlyOnceValidationFunction(resource) {
616+
// all resources are valid only once
617+
if (resource.validatedOnce) {
618+
return false;
619+
} else {
620+
resource.validatedOnce = true;
621+
return true;
622+
}
623+
}
624+
535625
class Resource {
536626

537627
constructor(key, id, release) {

0 commit comments

Comments
 (0)