Skip to content

Added configuration option 'reconnect_timeout'. #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions R/SockJSAdapter.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ local({
disableProtocols <- paste('"', disableProtocols, '"', sep = '', collapse = ',')
}
reconnect <- if (identical("true", tolower(input[11]))) "true" else "false"
reconnectTimeout <- as.numeric(input[14]) * 1000
options(shiny.sanitize.errors = identical("true", tolower(input[12])))

# Top-level bookmarking directory (for all users)
Expand Down Expand Up @@ -191,8 +192,8 @@ local({
tags$script(src='__assets__/sockjs-0.3.4.min.js'),
tags$script(src='__assets__/shiny-server-client.min.js'),
tags$script(
sprintf("preShinyInit({reconnect:%s,disableProtocols:[%s]});",
reconnect, disableProtocols
sprintf("preShinyInit({reconnect:%s,disableProtocols:[%s],reconnectTimeout:%s});",
reconnect, disableProtocols, reconnectTimeout
)
),
tags$link(rel='stylesheet', type='text/css', href='__assets__/shiny-server.css'),
Expand Down
8 changes: 8 additions & 0 deletions config/shiny-server-rules.config
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ sockjs_disconnect_delay {
maxcount 1;
}

reconnect_timeout {
desc "The number of seconds to retain an abruptly closed connection
before passing along its closed and/or end events. Defaults to 15 seconds.";
param Float timeout "The number of seconds to retain an abruptly closed connection.";
at $;
maxcount 1;
}

simple_scheduler {
desc "A basic scheduler which will spawn one single-threaded R worker for each application. If no scheduler is specified, this is the default scheduler.";
param Integer [maxRequests] "The maximum number of requests to assign to this scheduler before it should start returning rejecting incoming traffic using a '503 - Service Unavailable' message. Once this threshold is hit, users attempting to initialize a new session will receive 503 errors." 100;
Expand Down
3 changes: 2 additions & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ var loadConfig_p = qutil.serialized(function() {

// Create SockJS server
sockjsServer = proxy_sockjs.createServer(metarouter, schedulerRegistry,
configRouter.sockjsHeartbeatDelay, configRouter.sockjsDisconnectDelay);
configRouter.sockjsHeartbeatDelay, configRouter.sockjsDisconnectDelay,
configRouter.reconnectTimeout);
sockjsHandler = sockjsServer.middleware();

socketTimeout = configRouter.httpKeepaliveTimeout;
Expand Down
4 changes: 2 additions & 2 deletions lib/proxy/sockjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var RobustSockJS = require('./robust-sockjs');
var errorcode = require("./errorcode");

exports.createServer = createServer;
function createServer(router, schedulerRegistry, heartbeatDelay, disconnectDelay) {
function createServer(router, schedulerRegistry, heartbeatDelay, disconnectDelay, reconnectTimeout) {
if (!heartbeatDelay || heartbeatDelay < 0) {
logger.warn("Ignoring invalid SockJS heartbeat delay: " + heartbeatDelay);
heartbeatDelay = 25 * 1000;
Expand All @@ -45,7 +45,7 @@ function createServer(router, schedulerRegistry, heartbeatDelay, disconnectDelay
disconnect_delay: disconnectDelay
});

var robust = new RobustSockJS();
var robust = new RobustSockJS(reconnectTimeout);
sockjsServer.on('connection', function(conn) {
var robustConn = robust.robustify(conn);
if (!robustConn){
Expand Down
5 changes: 5 additions & 0 deletions lib/router/config-router-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ function parseApplication(settings, locNode, provideDefaults){
appSettings.reconnect = false;
}

if (locNode.getValues('reconnect_timeout') &&
locNode.getValues('reconnect_timeout').timeout){
appSettings.reconnectTimeout = locNode.getValues('reconnect_timeout').timeout;
}

if (locNode.getOne('sanitize_errors') &&
locNode.getValues('sanitize_errors').enabled === false) {
appSettings.sanitizeErrors = false;
Expand Down
5 changes: 5 additions & 0 deletions lib/router/config-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ function ConfigRouter(conf, schedulerRegistry) {
this.sockjsDisconnectDelay = conf.getValues('sockjs_disconnect_delay').delay * 1000;
}

this.reconnectTimeout = 15;
if (conf.getOne('reconnect_timeout')) {
this.reconnectTimeout = conf.getValues('reconnect_timeout').timeout;
}

var apps = conf.search("application", true);
if (apps && apps.length > 0){
logger.error("The `application` configuration has been deprecated. Please "+
Expand Down
3 changes: 2 additions & 1 deletion lib/worker/app-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ var AppWorker = function(appSpec, endpoint, logStream, workerId, home) {
appSpec.settings.appDefaults.disableProtocols.join(",") + '\n' +
appSpec.settings.appDefaults.reconnect + '\n' +
appSpec.settings.appDefaults.sanitizeErrors + '\n' +
appSpec.settings.appDefaults.bookmarkStateDir + '\n'
appSpec.settings.appDefaults.bookmarkStateDir + '\n' +
appSpec.settings.appDefaults.reconnectTimeout + '\n'
);
self.$proc.stdout.pipe(split()).on('data', function(line){
var match = null;
Expand Down