Skip to content

Commit

Permalink
Merge 3c834a2 into 18412c1
Browse files Browse the repository at this point in the history
  • Loading branch information
samtstern committed Nov 20, 2019
2 parents 18412c1 + 3c834a2 commit 0c39d17
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1 +1,2 @@
* Improved error handling when exporting users.
* Fixes an issue where repeated invoations cause an `EADDRINUSE` error (#1815)
2 changes: 1 addition & 1 deletion src/emulator/emulatorLogger.ts
Expand Up @@ -84,7 +84,7 @@ export class EmulatorLogger {
EmulatorLogger.log("USER", `${clc.blackBright("> ")} ${log.text}`);
break;
case "DEBUG":
if (log.data && log.data !== {}) {
if (log.data && Object.keys(log.data).length > 0) {
EmulatorLogger.log("DEBUG", `[${log.type}] ${log.text} ${JSON.stringify(log.data)}`);
} else {
EmulatorLogger.log("DEBUG", `[${log.type}] ${log.text}`);
Expand Down
1 change: 0 additions & 1 deletion src/emulator/functionsEmulator.ts
Expand Up @@ -29,7 +29,6 @@ import { EmulatorLogger, Verbosity } from "./emulatorLogger";
import { RuntimeWorkerPool, RuntimeWorker } from "./functionsRuntimeWorker";
import { PubsubEmulator } from "./pubsubEmulator";
import { FirebaseError } from "../error";
import { pubsub } from "firebase-functions";

const EVENT_INVOKE = "functions:invoke";

Expand Down
19 changes: 13 additions & 6 deletions src/emulator/functionsEmulatorRuntime.ts
Expand Up @@ -9,7 +9,6 @@ import {
FunctionsRuntimeBundle,
FunctionsRuntimeFeatures,
getEmulatedTriggersFromDefinitions,
getTemporarySocketPath,
FunctionsRuntimeArgs,
} from "./functionsEmulatorShared";
import { parseVersionString, compareVersionStrings } from "./functionsEmulatorUtils";
Expand Down Expand Up @@ -810,11 +809,16 @@ async function processHTTPS(frb: FunctionsRuntimeBundle, trigger: EmulatedTrigge
await new Promise((resolveEphemeralServer, rejectEphemeralServer) => {
const handler = async (req: express.Request, res: express.Response) => {
try {
logDebug(`Ephemeral server used!`);
logDebug(`Ephemeral server handling ${req.method} request`);
const func = trigger.getRawFunction();

res.on("finish", () => {
instance.close(resolveEphemeralServer);
instance.close((err) => {
if (err) {
rejectEphemeralServer(err);
} else {
resolveEphemeralServer();
}
});
});

await runHTTPS([req, res], func);
Expand Down Expand Up @@ -858,9 +862,12 @@ async function processHTTPS(frb: FunctionsRuntimeBundle, trigger: EmulatedTrigge
functionRouter
);

logDebug(`Attempting to listen to socketPath: ${socketPath}`);
const instance = ephemeralServer.listen(socketPath, () => {
new EmulatorLog("SYSTEM", "runtime-status", "ready", { state: "ready" }).log();
});

instance.on("error", rejectEphemeralServer);
});
}

Expand Down Expand Up @@ -964,7 +971,7 @@ async function moduleResolutionDetective(frb: FunctionsRuntimeBundle, error: Err
}

function logDebug(msg: string, data?: any): void {
new EmulatorLog("DEBUG", "runtime-status", msg, data).log();
new EmulatorLog("DEBUG", "runtime-status", `[${process.pid}] ${msg}`, data).log();
}

async function invokeTrigger(
Expand All @@ -980,7 +987,7 @@ async function invokeTrigger(
}).log();

const trigger = triggers[frb.triggerId];
logDebug("", trigger.definition);
logDebug("triggerDefinition", trigger.definition);
const mode = trigger.definition.httpsTrigger ? "HTTPS" : "BACKGROUND";

logDebug(`Running ${frb.triggerId} in mode ${mode}`);
Expand Down
17 changes: 14 additions & 3 deletions src/emulator/functionsEmulatorShared.ts
Expand Up @@ -134,13 +134,24 @@ export function getEmulatedTriggersFromDefinitions(
}, {});
}

export function getTemporarySocketPath(id: string, cwd: string): string {
export function getTemporarySocketPath(pid: number, cwd: string): string {
// See "net" package docs for information about IPC pipes on Windows
// https://nodejs.org/api/net.html#net_identifying_paths_for_ipc_connections
//
// As noted in the linked documentation the socket path is truncated at a certain
// length:
// > On Unix, the local domain is also known as the Unix domain. The path is a filesystem pathname.
// > It gets truncated to a length of sizeof(sockaddr_un.sun_path) - 1, which varies 91 and 107 bytes
// > depending on the operating system. The typical values are 107 on Linux and 103 on macOS.
//
// On Mac our socket paths will begin with something like this:
// /var/folders/xl/6lkrzp7j07581mw8_4dlt3b000643s/T/{...}.sock
// Since the system prefix is about ~50 chargs we only have about ~50 more to work with
// before we will get truncated socket names and then undefined behavior.
if (process.platform === "win32") {
return path.join("\\\\?\\pipe", cwd, id.toString());
return path.join("\\\\?\\pipe", cwd, pid.toString());
} else {
return path.join(os.tmpdir(), `firebase_emulator_invocation_${id}.sock`);
return path.join(os.tmpdir(), `fire_emu_${pid.toString()}.sock`);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/emulator/functionsRuntimeWorker.ts
Expand Up @@ -69,7 +69,7 @@ export class RuntimeWorker {

// TODO(samstern): I would like to do this elsewhere...
if (!execFrb.socketPath) {
execFrb.socketPath = getTemporarySocketPath(this.id, execFrb.cwd);
execFrb.socketPath = getTemporarySocketPath(this.runtime.pid, execFrb.cwd);
this.log(`Assigning socketPath: ${execFrb.socketPath}`);
}

Expand Down

0 comments on commit 0c39d17

Please sign in to comment.