123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- define([
- 'jquery',
- 'base/js/utils',
- 'services/kernels/kernel',
- ], function($, utils, kernel) {
- "use strict";
- /**
- * Session object for accessing the session REST api. The session
- * should be used to start kernels and then shut them down -- for
- * all other operations, the kernel object should be used.
- *
- * Preliminary documentation for the REST API is at
- * https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping#sessions-api
- *
- * Options should include:
- * - notebook_path: the path (not including name) to the notebook
- * - kernel_name: the type of kernel (e.g. python3)
- * - base_url: the root url of the notebook server
- * - ws_url: the url to access websockets
- * - notebook: Notebook object
- *
- * @class Session
- * @param {Object} options
- */
- var Session = function (options) {
- this.id = null;
- this.notebook_model = {
- path: options.notebook_path
- };
- this.kernel_model = {
- id: null,
- name: options.kernel_name
- };
- this.base_url = options.base_url;
- this.ws_url = options.ws_url;
- this.session_service_url = utils.url_path_join(this.base_url, 'api/sessions');
- this.session_url = null;
- this.notebook = options.notebook;
- this.kernel = null;
- this.events = options.notebook.events;
- this.bind_events();
- };
- Session.prototype.bind_events = function () {
- var that = this;
- var record_status = function (evt, info) {
- console.log('Session: ' + evt.type + ' (' + info.session.id + ')');
- };
- this.events.on('kernel_created.Session', record_status);
- this.events.on('kernel_dead.Session', record_status);
- this.events.on('kernel_killed.Session', record_status);
- // if the kernel dies, then also remove the session
- this.events.on('kernel_dead.Kernel', function () {
- that.delete();
- });
- this.events.on('kernel_failed_restart.Kernel', function () {
- that.notebook.start_session();
- });
- };
- // Public REST api functions
- /**
- * GET /api/sessions
- *
- * Get a list of the current sessions.
- *
- * @function list
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.list = function (success, error) {
- utils.ajax(this.session_service_url, {
- processData: false,
- cache: false,
- type: "GET",
- dataType: "json",
- success: success,
- error: this._on_error(error)
- });
- };
- /**
- * POST /api/sessions
- *
- * Start a new session. This function can only executed once.
- *
- * @function start
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.start = function (success, error) {
- var that = this;
- var on_success = function (data, status, xhr) {
- if (that.kernel) {
- that.kernel.name = that.kernel_model.name;
- } else {
- var kernel_service_url = utils.url_path_join(that.base_url, "api/kernels");
- that.kernel = new kernel.Kernel(kernel_service_url, that.ws_url, that.kernel_model.name);
- }
- that.events.trigger('kernel_created.Session', {session: that, kernel: that.kernel});
- that.kernel._kernel_created(data.kernel);
- if (success) {
- success(data, status, xhr);
- }
- };
- var on_error = function (xhr, status, err) {
- that.events.trigger('kernel_dead.Session', {session: that, xhr: xhr, status: status, error: err});
- if (error) {
- error(xhr, status, err);
- }
- };
- utils.ajax(this.session_service_url, {
- processData: false,
- cache: false,
- type: "POST",
- data: JSON.stringify(this._get_model()),
- contentType: 'application/json',
- dataType: "json",
- success: this._on_success(on_success),
- error: this._on_error(on_error)
- });
- };
- /**
- * GET /api/sessions/[:session_id]
- *
- * Get information about a session.
- *
- * @function get_info
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.get_info = function (success, error) {
- utils.ajax(this.session_url, {
- processData: false,
- cache: false,
- type: "GET",
- dataType: "json",
- success: this._on_success(success),
- error: this._on_error(error)
- });
- };
- /**
- * PATCH /api/sessions/[:session_id]
- *
- * Rename or move a notebook. If the given name or path are
- * undefined, then they will not be changed.
- *
- * @function rename_notebook
- * @param {string} [path] - new notebook path
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.rename_notebook = function (path, success, error) {
- if (path !== undefined) {
- this.notebook_model.path = path;
- }
- utils.ajax(this.session_url, {
- processData: false,
- cache: false,
- type: "PATCH",
- data: JSON.stringify(this._get_model()),
- contentType: 'application/json',
- dataType: "json",
- success: this._on_success(success),
- error: this._on_error(error)
- });
- };
- /**
- * DELETE /api/sessions/[:session_id]
- *
- * Kill the kernel and shutdown the session.
- *
- * @function delete
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.delete = function (success, error) {
- if (this.kernel && this.kernel.is_connected()) {
- this.events.trigger('kernel_killed.Session', {session: this, kernel: this.kernel});
- this.kernel._kernel_dead();
- }
- utils.ajax(this.session_url, {
- processData: false,
- cache: false,
- type: "DELETE",
- dataType: "json",
- success: this._on_success(success),
- error: this._on_error(error)
- });
- };
- /**
- * Restart the session by deleting it and the starting it
- * fresh. If options are given, they can include any of the
- * following:
- *
- * - notebook_path - the path to the notebook
- * - kernel_name - the name (type) of the kernel
- *
- * @function restart
- * @param {Object} [options] - options for the new kernel
- * @param {function} [success] - function executed on ajax success
- * @param {function} [error] - functon executed on ajax error
- */
- Session.prototype.restart = function (options, success, error) {
- var that = this;
- var start = function () {
- if (options && options.notebook_path) {
- that.notebook_model.path = options.notebook_path;
- }
- if (options && options.kernel_name) {
- that.kernel_model.name = options.kernel_name;
- }
- that.kernel_model.id = null;
- that.start(success, error);
- };
- this.delete(start, start);
- };
- // Helper functions
- /**
- * Get the data model for the session, which includes the notebook path
- * and kernel (name and id).
- *
- * @function _get_model
- * @returns {Object} - the data model
- */
- Session.prototype._get_model = function () {
- return {
- path: this.notebook_model.path,
- type: 'notebook',
- name: '',
- kernel: this.kernel_model
- };
- };
- /**
- * Update the data model from the given JSON object, which should
- * have attributes of `id`, `notebook`, and/or `kernel`. If
- * provided, the notebook data must include name and path, and the
- * kernel data must include name and id.
- *
- * @function _update_model
- * @param {Object} data - updated data model
- */
- Session.prototype._update_model = function (data) {
- if (data && data.id) {
- this.id = data.id;
- this.session_url = utils.url_path_join(this.session_service_url, this.id);
- }
- if (data && data.notebook) {
- this.notebook_model.path = data.path;
- }
- if (data && data.kernel) {
- this.kernel_model.name = data.kernel.name;
- this.kernel_model.id = data.kernel.id;
- }
- };
- /**
- * Handle a successful AJAX request by updating the session data
- * model with the response, and then optionally calling a provided
- * callback.
- *
- * @function _on_success
- * @param {function} success - callback
- */
- Session.prototype._on_success = function (success) {
- var that = this;
- return function (data, status, xhr) {
- that._update_model(data);
- if (success) {
- success(data, status, xhr);
- }
- };
- };
- /**
- * Handle a failed AJAX request by logging the error message, and
- * then optionally calling a provided callback.
- *
- * @function _on_error
- * @param {function} error - callback
- */
- Session.prototype._on_error = function (error) {
- return function (xhr, status, err) {
- utils.log_ajax_error(xhr, status, err);
- if (error) {
- error(xhr, status, err);
- }
- };
- };
- /**
- * Error type indicating that the session is already starting.
- */
- var SessionAlreadyStarting = function (message) {
- this.name = "SessionAlreadyStarting";
- this.message = (message || "");
- };
- SessionAlreadyStarting.prototype = Error.prototype;
- return {
- Session: Session,
- SessionAlreadyStarting: SessionAlreadyStarting
- };
- });
|