CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/jupyter/kernel/get-ports.ts
Views: 687
1
/*
2
3
Return n available ports, with options as specified in the portfinder module
4
(see https://github.com/http-party/node-portfinder#readme).
5
6
The difference between this and portfinder is that no matter what,
7
this function will never return a port it has aleady within 1 minute.
8
This avoids a major race condition, e.g., when creating multiple
9
jupyter notebooks at nearly the same time.
10
*/
11
12
import { promisify } from "util";
13
import { getPorts as getPorts0 } from "portfinder";
14
import LRU from "lru-cache";
15
16
const getPortsUnsafe = promisify(getPorts0);
17
18
const cache = new LRU<number, true>({
19
ttl: 60000,
20
max: 10000,
21
});
22
23
export default async function getPorts(
24
n: number,
25
options: {
26
port?: number; // minimum port
27
stopPort?: number; // maximum port
28
} = {}
29
): Promise<number[]> {
30
const ports: number[] = [];
31
while (ports.length < n) {
32
for (const port of await getPortsUnsafe(n - ports.length, options)) {
33
if (!cache.has(port)) {
34
cache.set(port, true);
35
ports.push(port);
36
}
37
}
38
if (ports.length < n) {
39
// we have to change something, otherwise getPortsUnsafe will never
40
// give us anything useful and we're stuck in a loop.
41
options = { ...options, port: (options.port ?? 8000) + 1 };
42
}
43
}
44
return ports;
45
}
46
47