Skip to content

Commit

Permalink
FEATURE: allow long polling to go to a different url
Browse files Browse the repository at this point in the history
Added the site setting long_polling_base_url , this allows you
to farm long polling to a different server.

This setting is very important if a CDN is serving dynamic content.
  • Loading branch information
SamSaffron committed Oct 24, 2014
1 parent 1962563 commit aa9b3bb
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Expand Up @@ -163,7 +163,7 @@ GEM
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
memory_profiler (0.0.4) memory_profiler (0.0.4)
message_bus (1.0.0) message_bus (1.0.4)
eventmachine eventmachine
rack (>= 1.1.3) rack (>= 1.1.3)
redis redis
Expand Down
Expand Up @@ -2,7 +2,7 @@
Subscribes to user events on the message bus Subscribes to user events on the message bus
**/ **/
export default { export default {
name: "subscribe-user-notifications", name: 'subscribe-user-notifications',
after: 'message-bus', after: 'message-bus',
initialize: function(container) { initialize: function(container) {
var user = Discourse.User.current(); var user = Discourse.User.current();
Expand All @@ -13,14 +13,25 @@ export default {
var bus = Discourse.MessageBus; var bus = Discourse.MessageBus;
bus.callbackInterval = siteSettings.anon_polling_interval; bus.callbackInterval = siteSettings.anon_polling_interval;
bus.backgroundCallbackInterval = siteSettings.background_polling_interval; bus.backgroundCallbackInterval = siteSettings.background_polling_interval;
bus.baseUrl = siteSettings.long_polling_base_url;

if (bus.baseUrl !== '/') {
// zepto compatible, 1 param only
bus.ajax = function(opts){
opts.headers = opts.headers || {};
opts.headers['X-Shared-Session-Key'] = $('meta[name=shared_session_key]').attr('content');
return $.ajax(opts);
};
} else {
bus.baseUrl = Discourse.getURL('/');
}


if (user) { if (user) {
bus.callbackInterval = siteSettings.polling_interval; bus.callbackInterval = siteSettings.polling_interval;
bus.enableLongPolling = true; bus.enableLongPolling = true;
bus.baseUrl = Discourse.getURL("/");


if (user.admin || user.moderator) { if (user.admin || user.moderator) {
bus.subscribe("/flagged_counts", function(data) { bus.subscribe('/flagged_counts', function(data) {
user.set('site_flagged_posts_count', data.total); user.set('site_flagged_posts_count', data.total);
}); });
} }
Expand Down
11 changes: 11 additions & 0 deletions app/helpers/application_helper.rb
Expand Up @@ -11,6 +11,17 @@ module ApplicationHelper
include CanonicalURL::Helpers include CanonicalURL::Helpers
include ConfigurableUrls include ConfigurableUrls


def shared_session_key
if SiteSetting.long_polling_base_url != '/'.freeze && current_user
sk = "shared_session_key"
return request.env[sk] if request.env[sk]

request.env[sk] = key = (session[sk] ||= SecureRandom.hex)
$redis.setex "#{sk}_#{key}", 7.days, current_user.id.to_s
key
end
end

def script(*args) def script(*args)
if SiteSetting.enable_cdn_js_debugging && GlobalSetting.cdn_url if SiteSetting.enable_cdn_js_debugging && GlobalSetting.cdn_url
tags = javascript_include_tag(*args, "crossorigin" => "anonymous") tags = javascript_include_tag(*args, "crossorigin" => "anonymous")
Expand Down
4 changes: 4 additions & 0 deletions app/views/layouts/application.html.erb
Expand Up @@ -10,6 +10,10 @@
<meta name="fragment" content="!"> <meta name="fragment" content="!">
<%- end %> <%- end %>
<%- if shared_session_key %>
<meta name="shared_session_key" content="<%= shared_session_key %>">
<%- end %>
<%= script "preload_store" %> <%= script "preload_store" %>
<%= script "locales/#{I18n.locale}" %> <%= script "locales/#{I18n.locale}" %>
<%= script "vendor" %> <%= script "vendor" %>
Expand Down
8 changes: 8 additions & 0 deletions config/initializers/04-message_bus.rb
Expand Up @@ -2,6 +2,14 @@
RailsMultisite::ConnectionManagement.current_db RailsMultisite::ConnectionManagement.current_db
end end


MessageBus.extra_response_headers_lookup do |env|
{
"Access-Control-Allow-Origin" => Discourse.base_url,
"Access-Control-Allow-Methods" => "GET, POST",
"Access-Control-Allow-Headers" => "X-SILENCE-LOGGER, X-Shared-Session-Key"
}
end

MessageBus.user_id_lookup do |env| MessageBus.user_id_lookup do |env|
user = CurrentUser.lookup_from_env(env) user = CurrentUser.lookup_from_env(env)
user.id if user user.id if user
Expand Down
1 change: 1 addition & 0 deletions config/locales/server.en.yml
Expand Up @@ -698,6 +698,7 @@ en:
enable_private_messages: "Allow trust level 1 users to create private messages and reply to private messages" enable_private_messages: "Allow trust level 1 users to create private messages and reply to private messages"


enable_long_polling: "Message bus used for notification can use long polling" enable_long_polling: "Message bus used for notification can use long polling"
long_polling_base_url: "Base URL used for long polling (when a CDN is serving dynamic content, be sure to set this to origin pull) eg: http://origin.site.com"
long_polling_interval: "Amount of time the server should wait before responding to clients when there is no data to send (logged on users only)" long_polling_interval: "Amount of time the server should wait before responding to clients when there is no data to send (logged on users only)"
polling_interval: "When not long polling, how often should logged on clients poll in milliseconds" polling_interval: "When not long polling, how often should logged on clients poll in milliseconds"
anon_polling_interval: "How often should anonymous clients poll in milliseconds" anon_polling_interval: "How often should anonymous clients poll in milliseconds"
Expand Down
3 changes: 3 additions & 0 deletions config/site_settings.yml
Expand Up @@ -616,6 +616,9 @@ developer:
client: true client: true
default: true default: true
long_polling_interval: 25000 long_polling_interval: 25000
long_polling_base_url:
client: true
default: '/'
background_polling_interval: background_polling_interval:
client: true client: true
default: 60000 default: 60000
Expand Down
11 changes: 11 additions & 0 deletions lib/auth/default_current_user_provider.rb
Expand Up @@ -18,6 +18,17 @@ def initialize(env)
def current_user def current_user
return @env[CURRENT_USER_KEY] if @env.key?(CURRENT_USER_KEY) return @env[CURRENT_USER_KEY] if @env.key?(CURRENT_USER_KEY)


# bypass if we have the shared session header
if shared_key = @env['HTTP_X_SHARED_SESSION_KEY']
uid = $redis.get("shared_session_key_#{shared_key}")
user = nil
if uid
user = User.find_by(id: uid.to_i)
end
@env[CURRENT_USER_KEY] = user
return user
end

request = @request request = @request


auth_token = request.cookies[TOKEN_COOKIE] auth_token = request.cookies[TOKEN_COOKIE]
Expand Down

1 comment on commit aa9b3bb

@discoursebot
Copy link

Choose a reason for hiding this comment

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

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/1

Please sign in to comment.