Spaces:
Runtime error
Runtime error
File size: 2,730 Bytes
9756872 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | import { clearTimeout, setTimeout } from 'timers';
import { MongoInvalidArgumentError } from './error';
import { noop } from './utils';
/** @internal */
export class TimeoutError extends Error {
override get name(): 'TimeoutError' {
return 'TimeoutError';
}
constructor(message: string, options?: { cause?: Error }) {
super(message, options);
}
static is(error: unknown): error is TimeoutError {
return (
error != null && typeof error === 'object' && 'name' in error && error.name === 'TimeoutError'
);
}
}
type Executor = ConstructorParameters<typeof Promise<never>>[0];
type Reject = Parameters<ConstructorParameters<typeof Promise<never>>[0]>[1];
/**
* @internal
* This class is an abstraction over timeouts
* The Timeout class can only be in the pending or rejected states. It is guaranteed not to resolve
* if interacted with exclusively through its public API
* */
export class Timeout extends Promise<never> {
get [Symbol.toStringTag](): 'MongoDBTimeout' {
return 'MongoDBTimeout';
}
private id?: NodeJS.Timeout;
public readonly start: number;
public ended: number | null = null;
public duration: number;
public timedOut = false;
/** Create a new timeout that expires in `duration` ms */
private constructor(executor: Executor = () => null, duration: number, unref = false) {
let reject!: Reject;
if (duration < 0) {
throw new MongoInvalidArgumentError('Cannot create a Timeout with a negative duration');
}
super((_, promiseReject) => {
reject = promiseReject;
executor(noop, promiseReject);
});
this.duration = duration;
this.start = Math.trunc(performance.now());
if (this.duration > 0) {
this.id = setTimeout(() => {
this.ended = Math.trunc(performance.now());
this.timedOut = true;
reject(new TimeoutError(`Expired after ${duration}ms`));
}, this.duration);
if (typeof this.id.unref === 'function' && unref) {
// Ensure we do not keep the Node.js event loop running
this.id.unref();
}
}
}
/**
* Clears the underlying timeout. This method is idempotent
*/
clear(): void {
clearTimeout(this.id);
this.id = undefined;
}
public static expires(durationMS: number, unref?: boolean): Timeout {
return new Timeout(undefined, durationMS, unref);
}
static is(timeout: unknown): timeout is Timeout {
return (
typeof timeout === 'object' &&
timeout != null &&
Symbol.toStringTag in timeout &&
timeout[Symbol.toStringTag] === 'MongoDBTimeout' &&
'then' in timeout &&
// eslint-disable-next-line github/no-then
typeof timeout.then === 'function'
);
}
}
|