Skip to content

Commit

Permalink
Merge branch 'master' into jh-sa-already-deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
joehan committed Aug 7, 2019
2 parents bce3b24 + f0f2f26 commit baa785b
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 96 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
`projects:addFirebase`.
* Add new app management commands: `apps:create`, `apps:list`, `apps:sdkconfig`.
* Improve `init` command to be able to create a new project.
* Automatically choose a port for the Firestore emulator to serve WebChannel traffic.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"jsonwebtoken": "^8.2.1",
"lodash": "^4.17.14",
"marked": "^0.7.0",
"marked-terminal": "^3.1.1",
"marked-terminal": "^3.3.0",
"minimatch": "^3.0.4",
"open": "^6.3.0",
"ora": "^3.4.0",
Expand Down
25 changes: 25 additions & 0 deletions src/emulator/firestoreEmulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as fs from "fs";
import * as request from "request";
import * as clc from "cli-color";
import * as path from "path";
import * as pf from "portfinder";

import * as utils from "../utils";
import * as javaEmulators from "../serve/javaEmulators";
Expand All @@ -19,6 +20,7 @@ export interface FirestoreEmulatorArgs {
rules?: string;
functions_emulator?: string;
auto_download?: boolean;
webchannel_port?: number;
}

export class FirestoreEmulator implements EmulatorInstance {
Expand Down Expand Up @@ -54,6 +56,29 @@ export class FirestoreEmulator implements EmulatorInstance {
});
}

// Find a port for WebChannel traffic
const host = this.getInfo().host;
const basePort = this.getInfo().port;
const port = basePort + 1;
const stopPort = port + 10;
try {
const webChannelPort = await pf.getPortPromise({
port,
stopPort,
});
this.args.webchannel_port = webChannelPort;

utils.logLabeledBullet(
"firestore",
`Serving WebChannel traffic on at ${clc.bold(`http://${host}:${webChannelPort}`)}`
);
} catch (e) {
utils.logLabeledWarning(
"firestore",
`Not serving WebChannel traffic, unable to find an open port in range ${port}:${stopPort}]`
);
}

return javaEmulators.start(Emulators.FIRESTORE, this.args);
}

Expand Down
86 changes: 0 additions & 86 deletions src/ensureApiEnabled.js

This file was deleted.

93 changes: 93 additions & 0 deletions src/ensureApiEnabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as _ from "lodash";

import * as api from "./api";
import * as utils from "./utils";
import { FirebaseError } from "./error";

const POLL_INTERVAL = 10000; // 10 seconds
const POLLS_BEFORE_RETRY = 12; // Retry enabling the API after 2 minutes

export async function check(
projectId: string,
apiName: string,
prefix: string,
silent: boolean = false
): Promise<boolean> {
const response = await api.request("GET", `/v1/projects/${projectId}/services/${apiName}`, {
auth: true,
origin: api.serviceUsageOrigin,
});

const isEnabled = _.get(response.body, "state") === "ENABLED";
if (isEnabled && !silent) {
utils.logLabeledSuccess(prefix, "all necessary APIs are enabled");
}
return isEnabled;
}

export async function enable(projectId: string, apiName: string): Promise<void> {
return api.request("POST", `/v1/projects/${projectId}/services/${apiName}:enable`, {
auth: true,
origin: api.serviceUsageOrigin,
});
}

export async function ensure(
projectId: string,
apiName: string,
prefix: string,
silent: boolean = false
): Promise<void> {
if (!silent) {
utils.logLabeledBullet(prefix, "ensuring necessary APIs are enabled...");
}
const isEnabled = await check(projectId, apiName, prefix, silent);
if (isEnabled) {
return;
}
if (!silent) {
utils.logLabeledWarning(prefix, "missing necessary APIs. Enabling now...");
}
return enableApiWithRetries(projectId, apiName, prefix, silent);
}

async function pollCheckEnabled(
projectId: string,
apiName: string,
prefix: string,
silent: boolean,
enablementRetries: number,
pollRetries: number = 0
): Promise<void> {
if (pollRetries > POLLS_BEFORE_RETRY) {
return enableApiWithRetries(projectId, apiName, prefix, silent, enablementRetries + 1);
}

await new Promise((resolve) => {
setTimeout(resolve, POLL_INTERVAL);
});
const isEnabled = await check(projectId, apiName, prefix, silent);
if (isEnabled) {
return;
}
if (!silent) {
utils.logLabeledBullet(prefix, "waiting for APIs to activate...");
}
return pollCheckEnabled(projectId, apiName, prefix, silent, enablementRetries, pollRetries + 1);
}

async function enableApiWithRetries(
projectId: string,
apiName: string,
prefix: string,
silent: boolean,
enablementRetries = 0
): Promise<void> {
if (enablementRetries > 1) {
throw new FirebaseError(
"Timed out while waiting for APIs to enable. Please try again in a few minutes."
);
}
await enable(projectId, apiName);
return pollCheckEnabled(projectId, apiName, prefix, silent, enablementRetries);
}
12 changes: 6 additions & 6 deletions src/serve/javaEmulators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ const EmulatorDetails: { [s in JavaEmulators]: JavaEmulatorDetails } = {
stdout: null,
cacheDir: CACHE_DIR,
remoteUrl:
"https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.7.0.jar",
expectedSize: 59234749,
expectedChecksum: "8438fa31a7bf80ce96fe72cc32b7adb7",
localPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.7.0.jar"),
"https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.7.1.jar",
expectedSize: 59830668,
expectedChecksum: "883d685b39649ed5525ec35963aff679",
localPath: path.join(CACHE_DIR, "cloud-firestore-emulator-v1.7.1.jar"),
namePrefix: "cloud-firestore-emulator",
},
};
Expand All @@ -57,7 +57,7 @@ const Commands: { [s in JavaEmulators]: JavaEmulatorCommand } = {
firestore: {
binary: "java",
args: ["-Duser.language=en", "-jar", EmulatorDetails.firestore.localPath],
optionalArgs: ["port", "host", "rules", "functions_emulator"],
optionalArgs: ["port", "webchannel_port", "host", "rules", "functions_emulator"],
},
};

Expand Down Expand Up @@ -203,6 +203,6 @@ export async function start(targetName: JavaEmulators, args: any): Promise<void>
}

const command = _getCommand(targetName, args);
logger.debug(`Starting emulator ${targetName} with args ${JSON.stringify(args)}`);
logger.debug(`Starting emulator ${targetName} with command ${JSON.stringify(command)}`);
return _runBinary(emulator, command);
}

0 comments on commit baa785b

Please sign in to comment.