-
Notifications
You must be signed in to change notification settings - Fork 50
Support GCF through a 'initialization completed promise' #341
Conversation
src/agent/debuglet.ts
Outdated
@@ -314,6 +319,14 @@ export class Debuglet extends EventEmitter { | |||
|
|||
}); | |||
} | |||
initializationPromise() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
initializationPromise() { | ||
this.promiseInitialized_ = true; | ||
return new Promise<void>((resolve) => { | ||
this.promiseResolve_ = () => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -115,6 +115,8 @@ export class Debuglet extends EventEmitter { | |||
private project_: string|null; | |||
private controller_: Controller; | |||
private completedBreakpointMap_: {[key: string]: boolean}; | |||
private promiseInitialized_: boolean; | |||
private promiseResolve_: (value?: void|PromiseLike<void>|undefined) => void; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
31e0cb2
to
aac1617
Compare
src/agent/debuglet.ts
Outdated
@@ -117,6 +118,9 @@ export class Debuglet extends EventEmitter { | |||
private controller_: Controller; | |||
private completedBreakpointMap_: {[key: string]: boolean}; | |||
|
|||
private promise_: Promise<void>|null; | |||
private promiseResolve_: (value?: void|PromiseLike<void>|undefined) => void; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -322,6 +329,18 @@ export class Debuglet extends EventEmitter { | |||
|
|||
}); | |||
} | |||
checkReady() { | |||
const diff = process.hrtime(this.promiseResolvedTimestamp_); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
if (diff[0] < PROMISE_RESOLVE_CUT_OFF_IN_SECONDS) { | ||
return Promise.resolve(); | ||
} | ||
this.promise_ = new Promise<void>((resolve) => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
debuglet.once('registered', function reg(id: string) { | ||
assert.equal(id, DEBUGGEE_ID); | ||
debugPromise.then(() => { | ||
setTimeout(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -175,6 +179,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
/** @private {Object.<string, Boolean>} */ | |||
this.completedBreakpointMap_ = {}; | |||
|
|||
/** @private {Array<number>} */ |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -175,6 +179,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
/** @private {Object.<string, Boolean>} */ | |||
this.completedBreakpointMap_ = {}; | |||
|
|||
/** @private {Array<number>} */ | |||
this.promiseResolvedTimestamp_ = [0, 0]; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
// debug agent return a promise when checkReady is called. The value is selected | ||
// between Stackdriver debugger hanging get duration (40s) and TCP default | ||
// time-out (https://tools.ietf.org/html/rfc5482). | ||
const PROMISE_RESOLVE_CUT_OFF_IN_SECONDS = 60; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -174,6 +183,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
/** @private {Object.<string, Boolean>} */ | |||
this.completedBreakpointMap_ = {}; | |||
|
|||
/** @private {Array<number>} */ | |||
this.promiseResolvedTimestamp_ = Date.now(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
if (this.promise_) return this.promise_; | ||
const diff = Date.now() - this.promiseResolvedTimestamp_; | ||
if (diff < PROMISE_RESOLVE_CUT_OFF_IN_SECONDS * 1000) { | ||
return Promise.resolve(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -597,6 +622,11 @@ export class Debuglet extends EventEmitter { | |||
} | |||
that.scheduleBreakpointFetch_( | |||
that.config_.breakpointUpdateIntervalSec); | |||
if (that.promise_) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -597,6 +622,11 @@ export class Debuglet extends EventEmitter { | |||
} | |||
that.scheduleBreakpointFetch_( | |||
that.config_.breakpointUpdateIntervalSec); | |||
if (that.promise_) { | |||
that.promiseResolve_(); | |||
that.promise_ = null; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -175,6 +179,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
/** @private {Object.<string, Boolean>} */ | |||
this.completedBreakpointMap_ = {}; | |||
|
|||
/** @private {Array<number>} */ |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -174,6 +183,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
/** @private {Object.<string, Boolean>} */ | |||
this.completedBreakpointMap_ = {}; | |||
|
|||
/** @private {Array<number>} */ | |||
this.promiseResolvedTimestamp_ = Date.now(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -62,6 +62,12 @@ const BREAKPOINT_ACTION_MESSAGE = | |||
'The only currently supported breakpoint actions' + | |||
' are CAPTURE and LOG.'; | |||
|
|||
// PROMISE_RESOLVE_CUT_OFF_IN_SECONDS is a heuristic that we set to force the |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -62,6 +62,12 @@ const BREAKPOINT_ACTION_MESSAGE = | |||
'The only currently supported breakpoint actions' + | |||
' are CAPTURE and LOG.'; | |||
|
|||
// PROMISE_RESOLVE_CUT_OFF_IN_SECONDS is a heuristic that we set to force the | |||
// debug agent return a promise when checkReady is called. The value is selected |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -322,6 +333,17 @@ export class Debuglet extends EventEmitter { | |||
|
|||
}); | |||
} | |||
checkReady() { | |||
const diff = Date.now() - this.promiseResolvedTimestamp; | |||
if (diff > PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -114,6 +120,9 @@ export class Debuglet extends EventEmitter { | |||
private controller_: Controller; | |||
private completedBreakpointMap_: {[key: string]: boolean}; | |||
|
|||
private promise: Promise<void>; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
private promiseResolve: (() => void)|null; | ||
private promiseResolvedTimestamp: number; | ||
constructor() { | ||
this.promiseResolvedTimestamp = -Infinity; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
constructor() { | ||
this.promiseResolvedTimestamp = -Infinity; | ||
} | ||
isReady() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
return this.promise; | ||
} | ||
|
||
makeReady() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
* old one if it steals. makeReady will resolve the promise at appropriate | ||
* code location (in our case is after listActiveBreakpoints executed). | ||
*/ | ||
export class IsReadyManager { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
// isReadyManager. The value is selected between Stackdriver debugger hanging | ||
// get duration (40s) and TCP default time-out | ||
// (https://tools.ietf.org/html/rfc5482). | ||
const PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS = 60 * 1000; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
// PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS is a heuristic that we set to force | ||
// the debug agent to return a promise when isReady is called in | ||
// isReadyManager. The value is selected between Stackdriver debugger hanging | ||
// get duration (40s) and TCP default time-out |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
isReady() { | ||
const diff = Date.now() - this.promiseResolvedTimestamp; | ||
if (diff > PROMISE_RESOLVE_CUT_OFF_IN_MILLISECONDS) { | ||
this.promise = new Promise<void>((resolve) => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
* listActiveBreakpoints executed). | ||
*/ | ||
export class CachedPromise { | ||
private promise: Promise<void>; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
/** | ||
* CachedPromise class is designed to support debug agent in Google Cloud | ||
* Function (GCF). As GCF is a serverless environment and we wanted to make | ||
* sure debug agent could always capture the snapshots. We designed this class |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
* CachedPromise class is designed to support debug agent in Google Cloud | ||
* Function (GCF). As GCF is a serverless environment and we wanted to make | ||
* sure debug agent could always capture the snapshots. We designed this class | ||
* so that GCF could wait the ListActiveBreakpoitns event completed before |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
* throttling CPU to 0. CachedPromise has two member functions. | ||
* get() is to create or return an existing promise. resolve() will resolve | ||
* the promise at appropriate code location (in our case is after | ||
* listActiveBreakpoints executed). |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
this.promise = new Promise<void>((resolve) => { | ||
this.promiseResolve = () => { | ||
resolve(); | ||
}; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -114,6 +160,7 @@ export class Debuglet extends EventEmitter { | |||
private controller_: Controller; | |||
private completedBreakpointMap_: {[key: string]: boolean}; | |||
|
|||
private cachedPromise: CachedPromise; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -322,6 +372,9 @@ export class Debuglet extends EventEmitter { | |||
|
|||
}); | |||
} | |||
isReady() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/test-debuglet.ts
Outdated
@@ -74,6 +74,19 @@ function verifyBreakpointRejection(re: RegExp, body: {breakpoint: any}) { | |||
const hasCorrectDescription = status.description.format.match(re); | |||
return status.isError && hasCorrectDescription; | |||
} | |||
describe('CachedPromise', function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/test-debuglet.ts
Outdated
@@ -74,6 +74,19 @@ function verifyBreakpointRejection(re: RegExp, body: {breakpoint: any}) { | |||
const hasCorrectDescription = status.description.format.match(re); | |||
return status.isError && hasCorrectDescription; | |||
} | |||
describe('CachedPromise', function() { | |||
it('CachedPromise can proceed execute when resolve is called', function(done) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/test-debuglet.ts
Outdated
this.timeout(2000); | ||
let cachedPromise = new CachedPromise(60 * 1000); | ||
let promise = cachedPromise.get(); | ||
setTimeout(function(){ |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Not sure about other people's opinions.
src/agent/debuglet.ts
Outdated
}); | ||
} | ||
assert(this.promise); | ||
return this.promise as Promise<void>; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic looks good... left a few comments on naming and comments.
src/agent/debuglet.ts
Outdated
private promise: Promise<void>|undefined; | ||
private promiseResolve: (() => void)|null; | ||
private promiseResolvedTimestamp = -Infinity; | ||
private refresh: number; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
private promiseResolvedTimestamp = -Infinity; | ||
private refresh: number; | ||
constructor(refresh: number) { | ||
this.refresh = refresh; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -106,6 +112,44 @@ const formatBreakpoints = function( | |||
.join('\n'); | |||
}; | |||
|
|||
/** | |||
* CachedPromise class is designed to support debug agent in Google Cloud |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/debuggee.ts
Outdated
private description: string; | ||
private agentVersion?: string; | ||
private sourceContexts?: Array<{[key: string]: any}>; | ||
uniquifier: string; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
describe('CachedPromise', function() { | ||
it('CachedPromise can proceed execute when resolve is called', (done) => { | ||
this.timeout(2000); | ||
let cachedPromise = new CachedPromise(60 * 1000); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/test-debuglet.ts
Outdated
@@ -87,6 +87,28 @@ describe('CachedPromise', function() { | |||
done(); | |||
}); | |||
}); | |||
|
|||
it('CachedPromise should return the same promise if not staled', (done) => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
* listActiveBreakpoints is executed). | ||
* CachedPromise stores a promise for a limited time. Its member function get() | ||
* will initially create a promise, or create a promise when previous promise | ||
* stales, then return that promise. resolve() will resolve the stored promise. | ||
*/ | ||
export class CachedPromise { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/agent/debuglet.ts
Outdated
@@ -368,6 +365,15 @@ export class Debuglet extends EventEmitter { | |||
|
|||
}); | |||
} | |||
|
|||
/** | |||
* isReady is designed to support debug agent on Google Cloud Function (GCF). |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good on my end. w/ nits
@@ -75,6 +75,53 @@ function verifyBreakpointRejection(re: RegExp, body: {breakpoint: any}) { | |||
return status.isError && hasCorrectDescription; | |||
} | |||
|
|||
describe('CachedPromise', function() { | |||
it('CachedPromise can proceed execute when resolve is called', (done) => { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
@@ -324,6 +367,18 @@ export class Debuglet extends EventEmitter { | |||
} | |||
|
|||
/** | |||
* isReady is designed to support debug agent on Google Cloud Function (GCF). |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Opened another PR #358 |
This PR is to support Google Cloud Function (GCF) through initialization stackdriver debugger through a initialization of a promise and resolve the promise after breakpointfetch being scheduled.