Thanks to visit codestin.com
Credit goes to github.com

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

Conversation

jimmc
Copy link
Contributor

@jimmc jimmc commented May 30, 2017

No description provided.

@jimmc jimmc requested review from yelsayd, ojarjur and chmeyers May 30, 2017 20:21

const idleCheckIntervalSeconds = 5; // Seconds to wait between idle checks

let idleTimeoutEnabled = true; // Allow for explicit disable without clearing other values
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I understand this comment. maybe clarify a bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the comment on this line and the next. Let me know if this is any better.


let idleTimeoutEnabled = true; // Allow for explicit disable without clearing other values
let idleTimeoutSeconds = 0; // Shutdown after being idle this long; disabled if 0 or NaN
let lastUserActivity: number; // The epoch, in seconds, of the last user activity
Copy link
Contributor

Choose a reason for hiding this comment

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

also, can we define what user activity means here? or ideally in a comment at the head of the file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed this variable to be more reflective of reality. This module doesn't define what user activity is.

export VM_PROJECT="${vm_project}"
export VM_NAME=$(curl -s "${compute_metadata_url}/instance/hostname" -H "Metadata-Flavor: Google" | cut -d '.' -f 1)
export VM_ZONE=$(curl -s "${compute_metadata_url}/instance/zone" -H "Metadata-Flavor: Google" | sed 's/.*zones\///')
export DATALAB_SHUTDOWN_COMMAND="gcloud compute instances stop ${VM_NAME} --project ${VM_PROJECT} --zone ${VM_ZONE}"
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, we can get all three values by importing info.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean in the javascript code?
Putting the shutdown command here means it gets set when running in a VM but not otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

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

but what's the value of this? we can already check if we're in a VM.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By using this environment variable, it is easy for me to set a different shutdown command in my startup.sh that shuts down my local notebook server during development. If you prefer, I can remove this line from this script, and instead add code to idleTimeout.ts that calls getVmInfo, checks to see if we are on a VM, and builds this shutdown command if so.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, no I think it's fine to stick with the env var if it's more convenient in code.

}
} else {
idleTimeoutSeconds = NaN; // No shutdown command available
logging.getLogger().debug('No shutdown command, idle timeout is disabled');
Copy link
Contributor

Choose a reason for hiding this comment

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

this one should probably be info instead of debug, this is the default log level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


// Parse a string like '30s' or '1h 15m 5s' and return seconds.
// If no input string, or unrecognized stuff, returns NaN.
function parseInterval(str: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we grab an npm package for this? something like https://www.npmjs.com/package/parse-duration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds reasonable. What are the rules regarding adding new packages to what we ship? Licensing guidelines?

Copy link
Contributor

Choose a reason for hiding this comment

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

MIT license is generally fine.
@Di-Ku just in case.

let showDebugLog = false; // Set to true in the dev console to get log messages during development.
function _debugLog(msg) {
if (showDebugLog) {
console.log(msg);
Copy link
Contributor

Choose a reason for hiding this comment

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

can we import and use util.debug.log instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

window.setTimeout(_alertIdleShutdown, delayToLetOtherHandlersRun);
}
}
timeoutInfo.enabled = false; // Make sure we don't get a false indication later.
Copy link
Contributor

Choose a reason for hiding this comment

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

should this go inside the inner if statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, I want it to be disabled any time this method is called. Changed the method name to be clear about that.

_debugLog('== updating timeout display');
_debugLog(dropdown);
if (timeoutInfo.enabled) {
let secondsRemaining = Math.floor((timeoutInfo.expirationTime - Date.now()) / 1000);
Copy link
Contributor

Choose a reason for hiding this comment

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

I really don't think this should be in seconds, because of the fact that the client code isn't always in sync with the server state. the user will likely see the timer go down second by second, then jump up when the server resets and the client polls the new state.
minutes makes a lot more sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A few lines below, the call to roundToApproximateTime will generally round to minutes or larger chunks. The user will only see seconds when the time gets down to the last couple of minutes. I find seeing the seconds to be useful for development work. I expect users will rarely see that.

_debugLog('== Changing enabled to ' + newValue);
updateTimeoutInfo(dropdown);
xhr(timeoutUrl, () => {
timeoutInfo.enabled = newValue; // Display the new value right away.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also put the UI update here in the success callback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is there a couple of lines below. Or did you mean something besides a call to updateTimeoutInfo?

});

idleTimeout.setupKernelBusyHeartbeat();
$('#mainArea').scroll(idleTimeout.notebookScrolled);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we'll need a different div to trigger this event in the non-notebook pages

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't played around as much with non-notebook pages. The list page is very reset-happy, it seems to refresh the list of notebooks pretty often, so I didn't bother adding anything else there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea I think you're right about the list page, the sessions page also uses the same code so it'll do the same refresh requests.
We have to think about other pages though, for now we only have the editor and terminal pages, which both sound like the user can spend some time on. Can we make sure we have those covered?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will take a look at those pages.

export VM_PROJECT="${vm_project}"
export VM_NAME=$(curl -s "${compute_metadata_url}/instance/hostname" -H "Metadata-Flavor: Google" | cut -d '.' -f 1)
export VM_ZONE=$(curl -s "${compute_metadata_url}/instance/zone" -H "Metadata-Flavor: Google" | sed 's/.*zones\///')
export DATALAB_SHUTDOWN_COMMAND="gcloud compute instances stop ${VM_NAME} --project ${VM_PROJECT} --zone ${VM_ZONE}"
Copy link
Contributor

Choose a reason for hiding this comment

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

but what's the value of this? we can already check if we're in a VM.

return total;
}

export function resetBasedOnPath(path: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Never mind, I missed this was actually called before handling requests.

});

idleTimeout.setupKernelBusyHeartbeat();
$('#mainArea').scroll(idleTimeout.notebookScrolled);
Copy link
Contributor

Choose a reason for hiding this comment

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

Yea I think you're right about the list page, the sessions page also uses the same code so it'll do the same refresh requests.
We have to think about other pages though, for now we only have the editor and terminal pages, which both sound like the user can spend some time on. Can we make sure we have those covered?

it('converts single-unit strings correctly', function() {
expect(idleTimeout._secondsToString(1)).toEqual('1s');
expect(idleTimeout._secondsToString(15)).toEqual('15s');
expect(idleTimeout._secondsToString(2*60)).toEqual('2m');
Copy link
Contributor

Choose a reason for hiding this comment

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

one more test with an unrounded number, e.g. 260+1 or 360*60+61?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Multi-unit outputs are in the next test, a few lines lower. Is there something you want me to add there?

Copy link
Contributor

Choose a reason for hiding this comment

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

Nope, I think it's all covered.

@jimmc jimmc merged commit 460d186 into master Jun 2, 2017
@jimmc jimmc deleted the jimmc/1264-vm-timeout branch June 2, 2017 00:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants