@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
121 lines • 12.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResourcePool = void 0;
const xpmutex_1 = require("./xpmutex");
/**
* A class that holds a pool of resources and gives them out and returns them on-demand
*
* The resources will be given out front to back, when they are returned
* the most recently returned version will be given out again (for best
* cache coherency).
*
* If there are multiple consumers waiting for a resource, consumers are serviced
* in FIFO order for most fairness.
*/
class ResourcePool {
pool;
static withResources(name, resources) {
const pool = xpmutex_1.XpMutexPool.fromName(name);
return new ResourcePool(pool, resources);
}
resources;
mutexes = {};
locks = {};
constructor(pool, resources) {
this.pool = pool;
if (resources.length === 0) {
throw new Error('Must have at least one resource in the pool');
}
// Shuffle to reduce contention
resources = [...resources];
fisherYatesShuffle(resources);
this.resources = resources;
for (const res of resources) {
this.mutexes[res] = this.pool.mutex(res);
}
}
/**
* Take one value from the resource pool
*
* If no such value is currently available, wait until it is.
*/
async take() {
while (true) {
// Start a wait on the unlock now -- if the unlock signal comes after
// we try to acquire but before we start the wait, we might miss it.
//
// (The timeout is in case the unlock signal doesn't come for whatever reason).
const wait = this.pool.awaitUnlock(10_000);
// Try all mutexes, we might need to reacquire an expired lock
for (const res of this.resources) {
const lease = await this.tryObtainLease(res);
if (lease) {
// Ignore the wait (count as handled)
wait.then(() => {
}, () => {
});
return lease;
}
}
// None available, wait until one gets unlocked then try again
await wait;
}
}
/**
* Execute a block using a single resource from the pool
*/
async using(block) {
const lease = await this.take();
try {
return await block(lease.value);
}
finally {
await lease.dispose();
}
}
async tryObtainLease(value) {
const lock = await this.mutexes[value].tryAcquire();
if (!lock) {
return undefined;
}
this.locks[value] = lock;
return this.makeLease(value);
}
makeLease(value) {
let disposed = false;
return {
value,
dispose: async () => {
if (disposed) {
throw new Error('Calling dispose() on an already-disposed lease.');
}
disposed = true;
return this.returnValue(value);
},
};
}
/**
* When a value is returned:
*
* - If someone's waiting for it, give it to them
* - Otherwise put it back into the pool
*/
async returnValue(value) {
const lock = this.locks[value];
delete this.locks[value];
await lock?.release();
}
}
exports.ResourcePool = ResourcePool;
/**
* Shuffle an array in-place
*/
function fisherYatesShuffle(xs) {
for (let i = xs.length - 1; i >= 1; i--) {
const j = Math.floor(Math.random() * i);
const h = xs[j];
xs[j] = xs[i];
xs[i] = h;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtcG9vbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc291cmNlLXBvb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsdUNBQXdDO0FBRXhDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQWEsWUFBWTtJQVVjO0lBVDlCLE1BQU0sQ0FBQyxhQUFhLENBQW1CLElBQVksRUFBRSxTQUFjO1FBQ3hFLE1BQU0sSUFBSSxHQUFHLHFCQUFXLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxZQUFZLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFZ0IsU0FBUyxDQUFtQjtJQUM1QixPQUFPLEdBQTRCLEVBQUUsQ0FBQztJQUN0QyxLQUFLLEdBQXNDLEVBQUUsQ0FBQztJQUUvRCxZQUFxQyxJQUFpQixFQUFFLFNBQWM7UUFBakMsU0FBSSxHQUFKLElBQUksQ0FBYTtRQUNwRCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFFRCwrQkFBK0I7UUFDL0IsU0FBUyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQztRQUMzQixrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUUzQixLQUFLLE1BQU0sR0FBRyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLElBQUk7UUFDZixPQUFPLElBQUksRUFBRSxDQUFDO1lBQ1oscUVBQXFFO1lBQ3JFLG9FQUFvRTtZQUNwRSxFQUFFO1lBQ0YsK0VBQStFO1lBQy9FLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTNDLDhEQUE4RDtZQUM5RCxLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUM3QyxJQUFJLEtBQUssRUFBRSxDQUFDO29CQUNWLHFDQUFxQztvQkFDckMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQ2YsQ0FBQyxFQUFFLEdBQUcsRUFBRTtvQkFDUixDQUFDLENBQUMsQ0FBQztvQkFDSCxPQUFPLEtBQUssQ0FBQztnQkFDZixDQUFDO1lBQ0gsQ0FBQztZQUVELDhEQUE4RDtZQUM5RCxNQUFNLElBQUksQ0FBQztRQUNiLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsS0FBSyxDQUFJLEtBQStCO1FBQ25ELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xDLENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWMsQ0FBQyxLQUFRO1FBQ25DLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNwRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDVixPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDekIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTyxTQUFTLENBQUMsS0FBUTtRQUN4QixJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDckIsT0FBTztZQUNMLEtBQUs7WUFDTCxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ2xCLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO2dCQUNyRSxDQUFDO2dCQUNELFFBQVEsR0FBRyxJQUFJLENBQUM7Z0JBQ2hCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBYTtRQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixNQUFNLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN4QixDQUFDO0NBQ0Y7QUF0R0Qsb0NBc0dDO0FBaUJEOztHQUVHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBSSxFQUFPO0lBQ3BDLEtBQUssSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoQixFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2QsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNaLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBJTG9jaywgWHBNdXRleCB9IGZyb20gJy4veHBtdXRleCc7XG5pbXBvcnQgeyBYcE11dGV4UG9vbCB9IGZyb20gJy4veHBtdXRleCc7XG5cbi8qKlxuICogQSBjbGFzcyB0aGF0IGhvbGRzIGEgcG9vbCBvZiByZXNvdXJjZXMgYW5kIGdpdmVzIHRoZW0gb3V0IGFuZCByZXR1cm5zIHRoZW0gb24tZGVtYW5kXG4gKlxuICogVGhlIHJlc291cmNlcyB3aWxsIGJlIGdpdmVuIG91dCBmcm9udCB0byBiYWNrLCB3aGVuIHRoZXkgYXJlIHJldHVybmVkXG4gKiB0aGUgbW9zdCByZWNlbnRseSByZXR1cm5lZCB2ZXJzaW9uIHdpbGwgYmUgZ2l2ZW4gb3V0IGFnYWluIChmb3IgYmVzdFxuICogY2FjaGUgY29oZXJlbmN5KS5cbiAqXG4gKiBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgY29uc3VtZXJzIHdhaXRpbmcgZm9yIGEgcmVzb3VyY2UsIGNvbnN1bWVycyBhcmUgc2VydmljZWRcbiAqIGluIEZJRk8gb3JkZXIgZm9yIG1vc3QgZmFpcm5lc3MuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVBvb2w8QSBleHRlbmRzIHN0cmluZz1zdHJpbmc+IHtcbiAgcHVibGljIHN0YXRpYyB3aXRoUmVzb3VyY2VzPEEgZXh0ZW5kcyBzdHJpbmc+KG5hbWU6IHN0cmluZywgcmVzb3VyY2VzOiBBW10pIHtcbiAgICBjb25zdCBwb29sID0gWHBNdXRleFBvb2wuZnJvbU5hbWUobmFtZSk7XG4gICAgcmV0dXJuIG5ldyBSZXNvdXJjZVBvb2wocG9vbCwgcmVzb3VyY2VzKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzb3VyY2VzOiBSZWFkb25seUFycmF5PEE+O1xuICBwcml2YXRlIHJlYWRvbmx5IG11dGV4ZXM6IFJlY29yZDxzdHJpbmcsIFhwTXV0ZXg+ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgbG9ja3M6IFJlY29yZDxzdHJpbmcsIElMb2NrIHwgdW5kZWZpbmVkPiA9IHt9O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwb29sOiBYcE11dGV4UG9vbCwgcmVzb3VyY2VzOiBBW10pIHtcbiAgICBpZiAocmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHJlc291cmNlIGluIHRoZSBwb29sJyk7XG4gICAgfVxuXG4gICAgLy8gU2h1ZmZsZSB0byByZWR1Y2UgY29udGVudGlvblxuICAgIHJlc291cmNlcyA9IFsuLi5yZXNvdXJjZXNdO1xuICAgIGZpc2hlcllhdGVzU2h1ZmZsZShyZXNvdXJjZXMpO1xuICAgIHRoaXMucmVzb3VyY2VzID0gcmVzb3VyY2VzO1xuXG4gICAgZm9yIChjb25zdCByZXMgb2YgcmVzb3VyY2VzKSB7XG4gICAgICB0aGlzLm11dGV4ZXNbcmVzXSA9IHRoaXMucG9vbC5tdXRleChyZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUYWtlIG9uZSB2YWx1ZSBmcm9tIHRoZSByZXNvdXJjZSBwb29sXG4gICAqXG4gICAqIElmIG5vIHN1Y2ggdmFsdWUgaXMgY3VycmVudGx5IGF2YWlsYWJsZSwgd2FpdCB1bnRpbCBpdCBpcy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyB0YWtlKCk6IFByb21pc2U8SUxlYXNlPEE+PiB7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIC8vIFN0YXJ0IGEgd2FpdCBvbiB0aGUgdW5sb2NrIG5vdyAtLSBpZiB0aGUgdW5sb2NrIHNpZ25hbCBjb21lcyBhZnRlclxuICAgICAgLy8gd2UgdHJ5IHRvIGFjcXVpcmUgYnV0IGJlZm9yZSB3ZSBzdGFydCB0aGUgd2FpdCwgd2UgbWlnaHQgbWlzcyBpdC5cbiAgICAgIC8vXG4gICAgICAvLyAoVGhlIHRpbWVvdXQgaXMgaW4gY2FzZSB0aGUgdW5sb2NrIHNpZ25hbCBkb2Vzbid0IGNvbWUgZm9yIHdoYXRldmVyIHJlYXNvbikuXG4gICAgICBjb25zdCB3YWl0ID0gdGhpcy5wb29sLmF3YWl0VW5sb2NrKDEwXzAwMCk7XG5cbiAgICAgIC8vIFRyeSBhbGwgbXV0ZXhlcywgd2UgbWlnaHQgbmVlZCB0byByZWFjcXVpcmUgYW4gZXhwaXJlZCBsb2NrXG4gICAgICBmb3IgKGNvbnN0IHJlcyBvZiB0aGlzLnJlc291cmNlcykge1xuICAgICAgICBjb25zdCBsZWFzZSA9IGF3YWl0IHRoaXMudHJ5T2J0YWluTGVhc2UocmVzKTtcbiAgICAgICAgaWYgKGxlYXNlKSB7XG4gICAgICAgICAgLy8gSWdub3JlIHRoZSB3YWl0IChjb3VudCBhcyBoYW5kbGVkKVxuICAgICAgICAgIHdhaXQudGhlbigoKSA9PiB7XG4gICAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBsZWFzZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBOb25lIGF2YWlsYWJsZSwgd2FpdCB1bnRpbCBvbmUgZ2V0cyB1bmxvY2tlZCB0aGVuIHRyeSBhZ2FpblxuICAgICAgYXdhaXQgd2FpdDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBhIGJsb2NrIHVzaW5nIGEgc2luZ2xlIHJlc291cmNlIGZyb20gdGhlIHBvb2xcbiAgICovXG4gIHB1YmxpYyBhc3luYyB1c2luZzxCPihibG9jazogKHg6IEEpID0+IEIgfCBQcm9taXNlPEI+KTogUHJvbWlzZTxCPiB7XG4gICAgY29uc3QgbGVhc2UgPSBhd2FpdCB0aGlzLnRha2UoKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGJsb2NrKGxlYXNlLnZhbHVlKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgbGVhc2UuZGlzcG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdHJ5T2J0YWluTGVhc2UodmFsdWU6IEEpIHtcbiAgICBjb25zdCBsb2NrID0gYXdhaXQgdGhpcy5tdXRleGVzW3ZhbHVlXS50cnlBY3F1aXJlKCk7XG4gICAgaWYgKCFsb2NrKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRoaXMubG9ja3NbdmFsdWVdID0gbG9jaztcbiAgICByZXR1cm4gdGhpcy5tYWtlTGVhc2UodmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBtYWtlTGVhc2UodmFsdWU6IEEpOiBJTGVhc2U8QT4ge1xuICAgIGxldCBkaXNwb3NlZCA9IGZhbHNlO1xuICAgIHJldHVybiB7XG4gICAgICB2YWx1ZSxcbiAgICAgIGRpc3Bvc2U6IGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKGRpc3Bvc2VkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYWxsaW5nIGRpc3Bvc2UoKSBvbiBhbiBhbHJlYWR5LWRpc3Bvc2VkIGxlYXNlLicpO1xuICAgICAgICB9XG4gICAgICAgIGRpc3Bvc2VkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuVmFsdWUodmFsdWUpO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZW4gYSB2YWx1ZSBpcyByZXR1cm5lZDpcbiAgICpcbiAgICogLSBJZiBzb21lb25lJ3Mgd2FpdGluZyBmb3IgaXQsIGdpdmUgaXQgdG8gdGhlbVxuICAgKiAtIE90aGVyd2lzZSBwdXQgaXQgYmFjayBpbnRvIHRoZSBwb29sXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJldHVyblZhbHVlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2NrID0gdGhpcy5sb2Nrc1t2YWx1ZV07XG4gICAgZGVsZXRlIHRoaXMubG9ja3NbdmFsdWVdO1xuICAgIGF3YWl0IGxvY2s/LnJlbGVhc2UoKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgc2luZ2xlIHZhbHVlIHRha2VuIGZyb20gdGhlIHBvb2xcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJTGVhc2U8QT4ge1xuICAvKipcbiAgICogVGhlIHZhbHVlIG9idGFpbmVkIGJ5IHRoZSBsZWFzZVxuICAgKi9cbiAgcmVhZG9ubHkgdmFsdWU6IEE7XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbGVhc2VkIHZhbHVlIHRvIHRoZSBwb29sXG4gICAqL1xuICBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD47XG59XG5cbi8qKlxuICogU2h1ZmZsZSBhbiBhcnJheSBpbi1wbGFjZVxuICovXG5mdW5jdGlvbiBmaXNoZXJZYXRlc1NodWZmbGU8QT4oeHM6IEFbXSkge1xuICBmb3IgKGxldCBpID0geHMubGVuZ3RoIC0gMTsgaSA+PSAxOyBpLS0pIHtcbiAgICBjb25zdCBqID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogaSk7XG4gICAgY29uc3QgaCA9IHhzW2pdO1xuICAgIHhzW2pdID0geHNbaV07XG4gICAgeHNbaV0gPSBoO1xuICB9XG59XG4iXX0=