Compare commits
15 Commits
2.1638-vsc
...
2.1655-vsc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e22964915a | ||
|
|
197d0b6ca9 | ||
|
|
422503ef98 | ||
|
|
ea36345d2c | ||
|
|
a89d83cbba | ||
|
|
83ff31b620 | ||
|
|
3a9b032c72 | ||
|
|
f73e9225b4 | ||
|
|
168ccb0dfc | ||
|
|
58f7f5b769 | ||
|
|
b8e6369fbe | ||
|
|
d81d5f499f | ||
|
|
4be178d234 | ||
|
|
9c40466b4b | ||
|
|
95693fb58e |
@@ -30,7 +30,7 @@ jobs:
|
|||||||
- name: "MacOS build"
|
- name: "MacOS build"
|
||||||
os: osx
|
os: osx
|
||||||
if: tag IS blank
|
if: tag IS blank
|
||||||
script: travis_wait 40 scripts/ci.bash
|
script: travis_wait 60 scripts/ci.bash
|
||||||
|
|
||||||
git:
|
git:
|
||||||
depth: 3
|
depth: 3
|
||||||
|
|||||||
@@ -303,14 +303,16 @@ class Builder {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// This is so it doesn't get cached along with VS Code. There's no point
|
// Prevent needless cache changes.
|
||||||
// since there isn't anything like an incremental build.
|
await this.task("Cleaning for smaller cache", () => {
|
||||||
await this.task("Removing build files for smaller cache", () => {
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
fs.remove(serverPath),
|
fs.remove(serverPath),
|
||||||
fs.remove(path.join(vscodeSourcePath, "out-vscode")),
|
fs.remove(path.join(vscodeSourcePath, "out-vscode")),
|
||||||
fs.remove(path.join(vscodeSourcePath, "out-vscode-min")),
|
fs.remove(path.join(vscodeSourcePath, "out-vscode-min")),
|
||||||
fs.remove(path.join(vscodeSourcePath, "out-build")),
|
fs.remove(path.join(vscodeSourcePath, "out-build")),
|
||||||
|
util.promisify(cp.exec)("git reset --hard", { cwd: vscodeSourcePath }).then(() => {
|
||||||
|
return util.promisify(cp.exec)("git clean -fd", { cwd: vscodeSourcePath });
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,21 @@ index a657f4a4d9..66bd13dffa 100644
|
|||||||
} else if (typeof process === 'object') {
|
} else if (typeof process === 'object') {
|
||||||
_isWindows = (process.platform === 'win32');
|
_isWindows = (process.platform === 'win32');
|
||||||
_isMacintosh = (process.platform === 'darwin');
|
_isMacintosh = (process.platform === 'darwin');
|
||||||
|
diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts
|
||||||
|
index c52f7b3774..5635cfac8a 100644
|
||||||
|
--- a/src/vs/base/common/processes.ts
|
||||||
|
+++ b/src/vs/base/common/processes.ts
|
||||||
|
@@ -110,7 +110,9 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve
|
||||||
|
/^ELECTRON_.+$/,
|
||||||
|
/^GOOGLE_API_KEY$/,
|
||||||
|
/^VSCODE_.+$/,
|
||||||
|
- /^SNAP(|_.*)$/
|
||||||
|
+ /^SNAP(|_.*)$/,
|
||||||
|
+ /^NBIN_BYPASS$/,
|
||||||
|
+ /^LAUNCH_VSCODE$/
|
||||||
|
];
|
||||||
|
const envKeys = Object.keys(env);
|
||||||
|
envKeys
|
||||||
diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js
|
diff --git a/src/vs/base/node/languagePacks.js b/src/vs/base/node/languagePacks.js
|
||||||
index 3ae24454cb..fac8679290 100644
|
index 3ae24454cb..fac8679290 100644
|
||||||
--- a/src/vs/base/node/languagePacks.js
|
--- a/src/vs/base/node/languagePacks.js
|
||||||
@@ -87,7 +102,7 @@ index 990755c4f3..06449bb9cb 100644
|
|||||||
+ extraBuiltinExtensionPaths: string[];
|
+ extraBuiltinExtensionPaths: string[];
|
||||||
}
|
}
|
||||||
diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts
|
diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts
|
||||||
index 3e48fe4ddd..e0962b8736 100644
|
index 3e48fe4ddd..2212ff5471 100644
|
||||||
--- a/src/vs/platform/environment/node/argv.ts
|
--- a/src/vs/platform/environment/node/argv.ts
|
||||||
+++ b/src/vs/platform/environment/node/argv.ts
|
+++ b/src/vs/platform/environment/node/argv.ts
|
||||||
@@ -58,6 +58,8 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
@@ -58,6 +58,8 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
||||||
@@ -99,6 +114,15 @@ index 3e48fe4ddd..e0962b8736 100644
|
|||||||
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
|
||||||
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") },
|
||||||
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") },
|
||||||
|
@@ -185,7 +187,7 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||||
|
delete parsedArgs[o.deprecates];
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (val) {
|
||||||
|
+ if (typeof val !== 'undefined') {
|
||||||
|
if (o.type === 'string[]') {
|
||||||
|
if (val && !Array.isArray(val)) {
|
||||||
|
val = [val];
|
||||||
diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts
|
diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts
|
||||||
index f7d207009d..5c37b52dab 100644
|
index f7d207009d..5c37b52dab 100644
|
||||||
--- a/src/vs/platform/environment/node/environmentService.ts
|
--- a/src/vs/platform/environment/node/environmentService.ts
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import { URI } from "vs/base/common/uri";
|
|||||||
import { registerSingleton } from "vs/platform/instantiation/common/extensions";
|
import { registerSingleton } from "vs/platform/instantiation/common/extensions";
|
||||||
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
||||||
import { ILocalizationsService } from "vs/platform/localizations/common/localizations";
|
import { ILocalizationsService } from "vs/platform/localizations/common/localizations";
|
||||||
import { LocalizationsService } from "vs/workbench/services/localizations/electron-browser/localizationsService";
|
import { PersistentConnectionEventType } from "vs/platform/remote/common/remoteAgentConnection";
|
||||||
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
|
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
|
||||||
import { coderApi, vscodeApi } from "vs/server/src/browser/api";
|
import { coderApi, vscodeApi } from "vs/server/src/browser/api";
|
||||||
import { IUploadService, UploadService } from "vs/server/src/browser/upload";
|
import { IUploadService, UploadService } from "vs/server/src/browser/upload";
|
||||||
import { INodeProxyService, NodeProxyChannelClient } from "vs/server/src/common/nodeProxy";
|
import { INodeProxyService, NodeProxyChannelClient } from "vs/server/src/common/nodeProxy";
|
||||||
import { TelemetryChannelClient } from "vs/server/src/common/telemetry";
|
import { TelemetryChannelClient } from "vs/server/src/common/telemetry";
|
||||||
|
import { split } from "vs/server/src/common/util";
|
||||||
import "vs/workbench/contrib/localizations/browser/localizations.contribution";
|
import "vs/workbench/contrib/localizations/browser/localizations.contribution";
|
||||||
|
import { LocalizationsService } from "vs/workbench/services/localizations/electron-browser/localizationsService";
|
||||||
import { IRemoteAgentService } from "vs/workbench/services/remote/common/remoteAgentService";
|
import { IRemoteAgentService } from "vs/workbench/services/remote/common/remoteAgentService";
|
||||||
import { PersistentConnectionEventType } from "vs/platform/remote/common/remoteAgentConnection";
|
|
||||||
|
|
||||||
class TelemetryService extends TelemetryChannelClient {
|
class TelemetryService extends TelemetryChannelClient {
|
||||||
public constructor(
|
public constructor(
|
||||||
@@ -79,7 +80,7 @@ export const withQuery = (url: string, replace: Query): string => {
|
|||||||
const uri = URI.parse(url);
|
const uri = URI.parse(url);
|
||||||
const query = { ...replace };
|
const query = { ...replace };
|
||||||
uri.query.split("&").forEach((kv) => {
|
uri.query.split("&").forEach((kv) => {
|
||||||
const [key, value] = kv.split("=", 2);
|
const [key, value] = split(kv, "=");
|
||||||
if (!(key in query)) {
|
if (!(key in query)) {
|
||||||
query[key] = value;
|
query[key] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/common/util.ts
Normal file
10
src/common/util.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Split a string up to the delimiter. If the delimiter doesn't exist the first
|
||||||
|
* item will have all the text and the second item will be an empty string.
|
||||||
|
*/
|
||||||
|
export const split = (str: string, delimiter: string): [string, string] => {
|
||||||
|
const index = str.indexOf(delimiter);
|
||||||
|
return index !== -1
|
||||||
|
? [str.substring(0, index).trim(), str.substring(index + 1)]
|
||||||
|
: [str, ""];
|
||||||
|
};
|
||||||
@@ -90,7 +90,7 @@ const startVscode = async (): Promise<void | void[]> => {
|
|||||||
basePath: args["base-path"],
|
basePath: args["base-path"],
|
||||||
cert: args.cert,
|
cert: args.cert,
|
||||||
certKey: args["cert-key"],
|
certKey: args["cert-key"],
|
||||||
folderUri: extra.length > 1 ? extra[extra.length - 1] : undefined,
|
openUri: extra.length > 1 ? extra[extra.length - 1] : undefined,
|
||||||
host: args.host,
|
host: args.host,
|
||||||
password: process.env.PASSWORD,
|
password: process.env.PASSWORD,
|
||||||
};
|
};
|
||||||
@@ -204,6 +204,7 @@ export class WrapperProcess {
|
|||||||
logger.info("Relaunching...");
|
logger.info("Relaunching...");
|
||||||
this.started = undefined;
|
this.started = undefined;
|
||||||
if (this.process) {
|
if (this.process) {
|
||||||
|
this.process.removeAllListeners();
|
||||||
this.process.kill();
|
this.process.kill();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -223,7 +224,9 @@ export class WrapperProcess {
|
|||||||
public start(): Promise<void> {
|
public start(): Promise<void> {
|
||||||
if (!this.started) {
|
if (!this.started) {
|
||||||
const child = this.spawn();
|
const child = this.spawn();
|
||||||
this.started = ipcMain.handshake(child);
|
this.started = ipcMain.handshake(child).then(() => {
|
||||||
|
child.once("exit", (code) => exit(code!));
|
||||||
|
});
|
||||||
this.process = child;
|
this.process = child;
|
||||||
}
|
}
|
||||||
return this.started;
|
return this.started;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import { resolveCommonProperties } from "vs/platform/telemetry/node/commonProper
|
|||||||
import { UpdateChannel } from "vs/platform/update/electron-main/updateIpc";
|
import { UpdateChannel } from "vs/platform/update/electron-main/updateIpc";
|
||||||
import { INodeProxyService, NodeProxyChannel } from "vs/server/src/common/nodeProxy";
|
import { INodeProxyService, NodeProxyChannel } from "vs/server/src/common/nodeProxy";
|
||||||
import { TelemetryChannel } from "vs/server/src/common/telemetry";
|
import { TelemetryChannel } from "vs/server/src/common/telemetry";
|
||||||
|
import { split } from "vs/server/src/common/util";
|
||||||
import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService } from "vs/server/src/node/channel";
|
import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService } from "vs/server/src/node/channel";
|
||||||
import { Connection, ExtensionHostConnection, ManagementConnection } from "vs/server/src/node/connection";
|
import { Connection, ExtensionHostConnection, ManagementConnection } from "vs/server/src/node/connection";
|
||||||
import { TelemetryClient } from "vs/server/src/node/insights";
|
import { TelemetryClient } from "vs/server/src/node/insights";
|
||||||
@@ -115,7 +116,7 @@ export interface ServerOptions {
|
|||||||
readonly connectionToken?: string;
|
readonly connectionToken?: string;
|
||||||
readonly cert?: string;
|
readonly cert?: string;
|
||||||
readonly certKey?: string;
|
readonly certKey?: string;
|
||||||
readonly folderUri?: string;
|
readonly openUri?: string;
|
||||||
readonly host?: string;
|
readonly host?: string;
|
||||||
readonly password?: string;
|
readonly password?: string;
|
||||||
readonly port?: number;
|
readonly port?: number;
|
||||||
@@ -193,6 +194,11 @@ export abstract class Server {
|
|||||||
return { content: await util.promisify(fs.readFile)(filePath), filePath };
|
return { content: await util.promisify(fs.readFile)(filePath), filePath };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async getAnyResource(...parts: string[]): Promise<Response> {
|
||||||
|
const filePath = path.join(...parts);
|
||||||
|
return { content: await util.promisify(fs.readFile)(filePath), filePath };
|
||||||
|
}
|
||||||
|
|
||||||
protected async getTarredResource(...parts: string[]): Promise<Response> {
|
protected async getTarredResource(...parts: string[]): Promise<Response> {
|
||||||
const filePath = this.ensureAuthorizedFilePath(...parts);
|
const filePath = this.ensureAuthorizedFilePath(...parts);
|
||||||
return { stream: tarFs.pack(filePath), filePath, mime: "application/tar", cache: true };
|
return { stream: tarFs.pack(filePath), filePath, mime: "application/tar", cache: true };
|
||||||
@@ -207,8 +213,8 @@ export abstract class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected withBase(request: http.IncomingMessage, path: string): string {
|
protected withBase(request: http.IncomingMessage, path: string): string {
|
||||||
const split = request.url ? request.url.split("?", 2) : [];
|
const [, query] = request.url ? split(request.url, "?") : [];
|
||||||
return `${this.protocol}://${request.headers.host}${this.options.basePath}${path}${split.length === 2 ? `?${split[1]}` : ""}`;
|
return `${this.protocol}://${request.headers.host}${this.options.basePath}${path}${query ? `?${query}` : ""}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isAllowedRequestPath(path: string): boolean {
|
private isAllowedRequestPath(path: string): boolean {
|
||||||
@@ -435,8 +441,8 @@ export abstract class Server {
|
|||||||
const cookies: { [key: string]: string } = {};
|
const cookies: { [key: string]: string } = {};
|
||||||
if (request.headers.cookie) {
|
if (request.headers.cookie) {
|
||||||
request.headers.cookie.split(";").forEach((keyValue) => {
|
request.headers.cookie.split(";").forEach((keyValue) => {
|
||||||
const [key, value] = keyValue.split("=", 2);
|
const [key, value] = split(keyValue, "=");
|
||||||
cookies[key.trim()] = decodeURI(value);
|
cookies[key] = decodeURI(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return cookies as T;
|
return cookies as T;
|
||||||
@@ -469,6 +475,9 @@ export class MainServer extends Server {
|
|||||||
private readonly proxyTimeout = 5000;
|
private readonly proxyTimeout = 5000;
|
||||||
|
|
||||||
private settings: Settings = {};
|
private settings: Settings = {};
|
||||||
|
private heartbeatTimer?: NodeJS.Timeout;
|
||||||
|
private heartbeatInterval = 60000;
|
||||||
|
private lastHeartbeat = 0;
|
||||||
|
|
||||||
public constructor(options: ServerOptions, args: ParsedArgs) {
|
public constructor(options: ServerOptions, args: ParsedArgs) {
|
||||||
super(options);
|
super(options);
|
||||||
@@ -486,6 +495,7 @@ export class MainServer extends Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async handleWebSocket(socket: net.Socket, parsedUrl: url.UrlWithParsedQuery): Promise<void> {
|
protected async handleWebSocket(socket: net.Socket, parsedUrl: url.UrlWithParsedQuery): Promise<void> {
|
||||||
|
this.heartbeat();
|
||||||
if (!parsedUrl.query.reconnectionToken) {
|
if (!parsedUrl.query.reconnectionToken) {
|
||||||
throw new Error("Reconnection token is missing from query parameters");
|
throw new Error("Reconnection token is missing from query parameters");
|
||||||
}
|
}
|
||||||
@@ -509,12 +519,13 @@ export class MainServer extends Server {
|
|||||||
parsedUrl: url.UrlWithParsedQuery,
|
parsedUrl: url.UrlWithParsedQuery,
|
||||||
request: http.IncomingMessage,
|
request: http.IncomingMessage,
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
|
this.heartbeat();
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case "/": return this.getRoot(request, parsedUrl);
|
case "/": return this.getRoot(request, parsedUrl);
|
||||||
case "/resource":
|
case "/resource":
|
||||||
case "/vscode-remote-resource":
|
case "/vscode-remote-resource":
|
||||||
if (typeof parsedUrl.query.path === "string") {
|
if (typeof parsedUrl.query.path === "string") {
|
||||||
return this.getResource(parsedUrl.query.path);
|
return this.getAnyResource(parsedUrl.query.path);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "/tar":
|
case "/tar":
|
||||||
@@ -523,8 +534,8 @@ export class MainServer extends Server {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "/webview":
|
case "/webview":
|
||||||
if (requestPath.indexOf("/vscode-resource") === 0) {
|
if (/^\/vscode-resource/.test(requestPath)) {
|
||||||
return this.getResource(requestPath.replace(/^\/vscode-resource/, ""));
|
return this.getAnyResource(requestPath.replace(/^\/vscode-resource(\/file)?/, ""));
|
||||||
}
|
}
|
||||||
return this.getResource(
|
return this.getResource(
|
||||||
this.rootPath,
|
this.rootPath,
|
||||||
@@ -541,9 +552,9 @@ export class MainServer extends Server {
|
|||||||
util.promisify(fs.readFile)(filePath, "utf8"),
|
util.promisify(fs.readFile)(filePath, "utf8"),
|
||||||
this.getFirstValidPath([
|
this.getFirstValidPath([
|
||||||
{ path: parsedUrl.query.workspace, workspace: true },
|
{ path: parsedUrl.query.workspace, workspace: true },
|
||||||
{ path: parsedUrl.query.folder },
|
{ path: parsedUrl.query.folder, workspace: false },
|
||||||
(await this.readSettings()).lastVisited,
|
(await this.readSettings()).lastVisited,
|
||||||
{ path: this.options.folderUri }
|
{ path: this.options.openUri }
|
||||||
]),
|
]),
|
||||||
this.servicesPromise,
|
this.servicesPromise,
|
||||||
]);
|
]);
|
||||||
@@ -587,7 +598,9 @@ export class MainServer extends Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Choose the first valid path.
|
* Choose the first valid path. If `workspace` is undefined then either a
|
||||||
|
* workspace or a directory are acceptable. Otherwise it must be a file if a
|
||||||
|
* workspace or a directory otherwise.
|
||||||
*/
|
*/
|
||||||
private async getFirstValidPath(startPaths: Array<StartPath | undefined>): Promise<{ uri: URI, workspace?: boolean} | undefined> {
|
private async getFirstValidPath(startPaths: Array<StartPath | undefined>): Promise<{ uri: URI, workspace?: boolean} | undefined> {
|
||||||
const logger = this.services.get(ILogService) as ILogService;
|
const logger = this.services.get(ILogService) as ILogService;
|
||||||
@@ -602,9 +615,8 @@ export class MainServer extends Server {
|
|||||||
const uri = URI.file(sanitizeFilePath(paths[j], cwd));
|
const uri = URI.file(sanitizeFilePath(paths[j], cwd));
|
||||||
try {
|
try {
|
||||||
const stat = await util.promisify(fs.stat)(uri.fsPath);
|
const stat = await util.promisify(fs.stat)(uri.fsPath);
|
||||||
// Workspace must be a file.
|
if (typeof startPath.workspace === "undefined" || startPath.workspace !== stat.isDirectory()) {
|
||||||
if (!!startPath.workspace !== stat.isDirectory()) {
|
return { uri, workspace: !stat.isDirectory() };
|
||||||
return { uri, workspace: startPath.workspace };
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn(error.message);
|
logger.warn(error.message);
|
||||||
@@ -871,4 +883,48 @@ export class MainServer extends Server {
|
|||||||
(this.services.get(ILogService) as ILogService).warn(error.message);
|
(this.services.get(ILogService) as ILogService).warn(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the file path for the heartbeat file.
|
||||||
|
*/
|
||||||
|
private get heartbeatPath(): string {
|
||||||
|
const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
|
||||||
|
return path.join(environment.userDataPath, "heartbeat");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all online connections regardless of type.
|
||||||
|
*/
|
||||||
|
private get onlineConnections(): Connection[] {
|
||||||
|
const online = <Connection[]>[];
|
||||||
|
this.connections.forEach((connections) => {
|
||||||
|
connections.forEach((connection) => {
|
||||||
|
if (typeof connection.offline === "undefined") {
|
||||||
|
online.push(connection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return online;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to the heartbeat file if we haven't already done so within the
|
||||||
|
* timeout and start or reset a timer that keeps running as long as there are
|
||||||
|
* active connections. Failures are logged as warnings.
|
||||||
|
*/
|
||||||
|
private heartbeat(): void {
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - this.lastHeartbeat >= this.heartbeatInterval) {
|
||||||
|
util.promisify(fs.writeFile)(this.heartbeatPath, "").catch((error) => {
|
||||||
|
(this.services.get(ILogService) as ILogService).warn(error.message);
|
||||||
|
});
|
||||||
|
this.lastHeartbeat = now;
|
||||||
|
clearTimeout(this.heartbeatTimer!); // We can clear undefined so ! is fine.
|
||||||
|
this.heartbeatTimer = setTimeout(() => {
|
||||||
|
if (this.onlineConnections.length > 0) {
|
||||||
|
this.heartbeat();
|
||||||
|
}
|
||||||
|
}, this.heartbeatInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user