Skip to content
This repository was archived by the owner on Apr 3, 2024. It is now read-only.

feat: Enable isReady for debugger for GCF#358

Merged
gaofanmichael merged 10 commits intogoogleapis:masterfrom
gaofanmichael:gcf2
Nov 16, 2017
Merged

feat: Enable isReady for debugger for GCF#358
gaofanmichael merged 10 commits intogoogleapis:masterfrom
gaofanmichael:gcf2

Conversation

@gaofanmichael
Copy link
Copy Markdown
Contributor

This PR mainly serve for GCF. The introduced isReady will return a
promise, and to be resolved either

  1. time since last breakpoint fetch is within a heuristic duration.
  2. breakpoint update completed.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Nov 6, 2017
@jmdobry jmdobry removed the cla: yes This human has signed the Contributor License Agreement. label Nov 6, 2017
@gaofanmichael gaofanmichael changed the title chore: Enable isReady for debugger for GCF feat: Enable isReady for debugger for GCF Nov 6, 2017
// to force the debug agent to return a new promise for isReady. The value is
// the average of Stackdriver debugger hanging get duration (40s) and TCP
// time-out on GCF (540s).
const PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS = 290 * 1000;

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

// was successful. It is returned by isReady.
private breakpointFetched: Promise<void>|null;
// breakpointFetchedResolve is the resolve function for breakpointFetched.
private breakpointFetchedResolve: (() => void);

This comment was marked as spam.

This comment was marked as spam.

// registration was successful.
private debuggeeRegistered: Promise<void>;
// debuggeeRegisteredResolve is the resolve function for debuggeeRegistered.
private debuggeeRegisteredResolve: (() => void);

This comment was marked as spam.

This comment was marked as spam.

});
this.scheduleBreakpointFetch_(
0 /*immediately*/, true /*only fetch once*/);
return this.breakpointFetched;

This comment was marked as spam.

This comment was marked as spam.

src/index.ts Outdated

// We return the debuglet to facilitate testing.
return agentConfig.testMode_ ? debuglet : undefined;
return debuglet;

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

debugPromise
.then(() => {
setTimeout(function() {
debuglet.stop();

This comment was marked as spam.

This comment was marked as spam.

debuglet.start();
});

it('should resolve promises before exiting user functions', function(done) {

This comment was marked as spam.

This comment was marked as spam.

* feature is mainly used in Google Cloud Function (GCF), as it is a
* serverless environment and we wanted to make sure debug agent always
* captures the snapshots.
*/

This comment was marked as spam.

This comment was marked as spam.

* @private
*/
scheduleBreakpointFetch_(seconds: number): void {
scheduleBreakpointFetch_(seconds: number, onlyOnce: boolean): void {

This comment was marked as spam.

This comment was marked as spam.

that.scheduleBreakpointFetch_(
that.config.breakpointUpdateIntervalSec);
if (onlyOnce) {
that.breakpointFetchedTimestamp = Date.now();

This comment was marked as spam.

This comment was marked as spam.

if (this.breakpointFetched) {
return this.breakpointFetched;
}
this.debuggeeRegistered.then(() => {

This comment was marked as spam.

This comment was marked as spam.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Nov 7, 2017
Copy link
Copy Markdown
Contributor

@kjin kjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM from my end w/ nits.

private debuggeeRegistered: Promise<void>;
// debuggeeRegisteredResolve is the resolve function for debuggeeRegistered.
private debuggeeRegisteredResolve: (() => void);
private debuggeeRegisteredResolve: () => void;

This comment was marked as spam.

This comment was marked as spam.

.reply(200, {debuggee: {id: DEBUGGEE_ID}})
.get(BPS_PATH + '?successOnTimeout=true')
.reply(200, {breakpoints: [breakpoint]})
.get(BPS_PATH + '?successOnTimeout=true')

This comment was marked as spam.

This comment was marked as spam.

@gaofanmichael gaofanmichael force-pushed the gcf2 branch 2 times, most recently from 036f402 to 1cbb8d3 Compare November 8, 2017 23:16
private promise: Promise<void>|null;
private promiseResolve: () => void;

constructor() {

This comment was marked as spam.

This comment was marked as spam.

PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS) {
return Promise.resolve();
} else {
if (this.breakpointFetched.get() !== null) {

This comment was marked as spam.

This comment was marked as spam.

it('CachedPromise.get() will be null if it has been cleared', (done) => {
this.timeout(2000);
let cachedPromise = new CachedPromise();
assert(cachedPromise.get() === null);

This comment was marked as spam.

This comment was marked as spam.

this.promiseResolve = resolve;
});
}
get(): Promise<void>|null {

This comment was marked as spam.

This comment was marked as spam.

this.breakpointFetched.refresh();
(this.debuggeeRegistered.get() as Promise<void>).then(() => {
this.scheduleBreakpointFetch_(
0 /*immediately*/, true /*only fetch once*/);

This comment was marked as spam.

This comment was marked as spam.

if (this.breakpointFetched.get() !== null) {
return this.breakpointFetched.get() as Promise<void>;
}
this.breakpointFetched.refresh();

This comment was marked as spam.

This comment was marked as spam.

private breakpointFetched: CachedPromise;
// debuggeeRegistered is a CachedPromise only to be resolved after debuggee
// registration was successful.
private debuggeeRegistered: CachedPromise;

This comment was marked as spam.

This comment was marked as spam.

@gaofanmichael
Copy link
Copy Markdown
Contributor Author

@ofrobots @DominicKramer I have comments addressed. PTAL :)

/**
* IsReadyManager is a wrapper class to call debuglet.isReady().
*/
export class IsReadyManager {

This comment was marked as spam.

This comment was marked as spam.

}
}
clear(): void {
this.promise = null;

This comment was marked as spam.

/**
* IsReadyManager is a wrapper class to call debuglet.isReady().
*/
class IsReadyImpl implements IsReady {

This comment was marked as spam.

This comment was marked as spam.

return result;
}
this.breakpointFetched.refresh();
(this.debuggeeRegistered.get() as Promise<void>).then(() => {

This comment was marked as spam.

that.fetcherActive = false;
that.debuggeeRegistered.refresh();
that.breakpointFetched.resolve();
that.breakpointFetched.clear();

This comment was marked as spam.

This comment was marked as spam.

// breakpoint fetcher.
that.debuggeeRegistered.refresh();
that.breakpointFetched.resolve();
that.breakpointFetched.clear();

This comment was marked as spam.

@gaofanmichael gaofanmichael force-pushed the gcf2 branch 2 times, most recently from 6312c8a to ee39261 Compare November 15, 2017 19:23
This PR mainly serve for GCF. The introduced isReady will return a
promise, and to be resolved either
1) time since last breakpoint fetch is within a heuristic duration.
2) breakpoint update completed.
debuggee might expire, but debuggeRegistered promise is resolved. This
was a bug introduced before. This commit fixed this by refreshing
debuggeeRegistered promise when debuggee expired. Since
debuggeeRegistered promise is been updated so the next time user calls
isReady, a new debuggeeRegistered promise will return and user will wait
upon that new promise for debuggee re-registration. Also, we will
resolve breakpointFetch together so that no cloud function will hang
there foreever.
* function resolve() and can only be resolved once.
*/
export class CachedPromise {
private promiseResolve: (() => void) | null;

This comment was marked as spam.

This comment was marked as spam.


get(): Promise<void> {
return this.promise;
}

This comment was marked as spam.

This comment was marked as spam.

this.completedBreakpointMap = {};

this.breakpointFetchedTimestamp = -Infinity;

This comment was marked as spam.

This comment was marked as spam.

// again after a while. Successful registration will restart the
// breakpoint fetcher.
that.debuggeeRegistered = new CachedPromise();
if (that.breakpointFetched) {

This comment was marked as spam.

This comment was marked as spam.

that.logger.info('\t404 Registration expired.');
that.fetcherActive = false;
that.debuggeeRegistered = new CachedPromise();
if (that.breakpointFetched) {

This comment was marked as spam.


/**
* IsReady will return a promise to user after user starting the debug agent.
* This promise will be resolved when

This comment was marked as spam.

this.completedBreakpointMap = {};

this.breakpointFetched = null;

This comment was marked as spam.

this.breakpointFetched = null;

this.breakpointFetchedTimestamp = -Infinity;

This comment was marked as spam.

Copy link
Copy Markdown
Contributor

@DominicKramer DominicKramer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after the tests pass

* non-fetchable breakpoints.
*/
updatePromise_() {
this.debuggeeRegistered = new CachedPromise();

This comment was marked as spam.

@gaofanmichael gaofanmichael merged commit a828ea6 into googleapis:master Nov 16, 2017
@gaofanmichael gaofanmichael deleted the gcf2 branch November 27, 2017 21:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants