diff --git a/assets/scripts/app/initializers/config.coffee b/assets/scripts/app/initializers/config.coffee index 8980bb9a..b2dbb2d0 100644 --- a/assets/scripts/app/initializers/config.coffee +++ b/assets/scripts/app/initializers/config.coffee @@ -10,12 +10,25 @@ loadConfig = -> # to allow more granular config later pro = $('meta[name="travis.pro"]').attr('value') == 'true' || enterprise + if config.pro + pusher = + channels: [] + channel_prefix: 'private-' + encrypted: true + key: '' + else + pusher = + channels: ['common'] + channel_prefix: '' + encrypted: false + return { syncingPageRedirectionTime: 5000 api_endpoint: $('meta[rel="travis.api_endpoint"]').attr('href') source_endpoint: $('meta[rel="travis.source_endpoint"]').attr('href') pusher_key: $('meta[name="travis.pusher_key"]').attr('value') pusher_host: $('meta[name="travis.pusher_host"]').attr('value') + pusher_path: $('meta[name="travis.pusher_path"]').attr('value') ga_code: $('meta[name="travis.ga_code"]').attr('value') code_climate: $('meta[name="travis.code_climate"]').attr('value') ssh_key_enabled: $('meta[name="travis.ssh_key_enabled"]').attr('value') == 'true' @@ -38,15 +51,19 @@ loadConfig = -> customer_io_site_id: customer_io_site_id intervals: { times: -1, updateTimes: 1000 } + pusher: pusher } initialize = (container, application) -> - application.register 'config:main', application.config, { instantiate: false } + config = application.config + application.register 'config:main', config, { instantiate: false } application.inject('controller', 'config', 'config:main') application.inject('route', 'config', 'config:main') application.inject('auth', 'config', 'config:main') + application.pusher.config = config + ConfigInitializer = name: 'config' initialize: initialize diff --git a/assets/scripts/app/routes/main.coffee b/assets/scripts/app/routes/main.coffee index d28941fe..180b7fe6 100644 --- a/assets/scripts/app/routes/main.coffee +++ b/assets/scripts/app/routes/main.coffee @@ -1,7 +1,6 @@ require 'routes/route' TravisRoute = Travis.Route -channels = Travis.Pusher.CHANNELS Route = TravisRoute.extend renderTemplate: -> @@ -18,7 +17,7 @@ Route = TravisRoute.extend activate: -> # subscribe to pusher only if we're at a main route - if channels - @get('pusher').subscribeAll(channels) + if @config.pusher.channels + @get('pusher').subscribeAll(@config.pusher.channels) Travis.MainRoute = Route diff --git a/assets/scripts/app/utils/pusher.coffee b/assets/scripts/app/utils/pusher.coffee index b10de488..4fd55f64 100644 --- a/assets/scripts/app/utils/pusher.coffee +++ b/assets/scripts/app/utils/pusher.coffee @@ -1,117 +1,101 @@ -Travis.Pusher = (config) -> +TravisPusher = (config) -> @init(config) this -if Travis.config.pro - $.extend Travis.Pusher, - CHANNELS: [] - CHANNEL_PREFIX: 'private-' - ENCRYPTED: true - KEY: '' -else - $.extend Travis.Pusher, - CHANNELS: ['common'] - CHANNEL_PREFIX: '' - ENCRYPTED: false +TravisPusher.prototype.active_channels = [] -$.extend Travis.Pusher.prototype, - active_channels: [] +TravisPusher.prototype.init = (config) -> + Pusher.warn = @warn.bind(this) + Pusher.host = config.host if config.host + @pusher = new Pusher(config.key, encrypted: @config.pusher.encrypted, disableStats: true) - init: (config) -> - Pusher.warn = @warn.bind(this) - Pusher.host = config.host if config.host - @pusher = new Pusher(config.key, encrypted: Travis.Pusher.ENCRYPTED, disableStats: true) + @callbacksToProcess = [] - @callbacksToProcess = [] + Visibility.change (e, state) => + @processSavedCallbacks() if state == 'visible' - Visibility.change (e, state) => - @processSavedCallbacks() if state == 'visible' + setInterval @processSavedCallbacks.bind(this), @processingIntervalWhenHidden - setInterval @processSavedCallbacks.bind(this), @processingIntervalWhenHidden +TravisPusher.prototype.subscribeAll = (channels) -> + @subscribe(channel) for channel in channels - subscribeAll: (channels) -> - @subscribe(channel) for channel in channels +TravisPusher.prototype.unsubscribeAll = (channels) -> + @unsubscribe(channel) for channel in channels - unsubscribeAll: (channels) -> - @unsubscribe(channel) for channel in channels +TravisPusher.prototype.subscribe = (channel) -> + return unless channel + channel = @prefix(channel) + console.log("subscribing to #{channel}") + unless @pusher?.channel(channel) + @pusher.subscribe(channel).bind_all((event, data) => @receive(event, data)) - subscribe: (channel) -> - return unless channel - channel = @prefix(channel) - console.log("subscribing to #{channel}") - unless @pusher?.channel(channel) - @pusher.subscribe(channel).bind_all((event, data) => @receive(event, data)) +TravisPusher.prototype.unsubscribe = (channel) -> + return unless channel + channel = @prefix(channel) + console.log("unsubscribing from #{channel}") + @pusher.unsubscribe(channel) if @pusher?.channel(channel) - unsubscribe: (channel) -> - return unless channel - channel = @prefix(channel) - console.log("unsubscribing from #{channel}") - @pusher.unsubscribe(channel) if @pusher?.channel(channel) +TravisPusher.prototype.prefix = (channel) -> + if channel.indexOf(@config.pusher.channel_prefix) != 0 + "#{@config.pusher.channel_prefix}#{channel}" + else + channel - prefix: (channel) -> - if channel.indexOf(Travis.Pusher.CHANNEL_PREFIX) != 0 - "#{Travis.Pusher.CHANNEL_PREFIX}#{channel}" - else - channel +# process pusher messages in batches every 5 minutes when the page is hidden +TravisPusher.prototype.processingIntervalWhenHidden = 1000 * 60 * 5 - # process pusher messages in batches every 5 minutes when the page is hidden - processingIntervalWhenHidden: 1000 * 60 * 5 +TravisPusher.prototype.receive = (event, data) -> + return if event.substr(0, 6) == 'pusher' + data = @normalize(event, data) if data.id - receive: (event, data) -> - return if event.substr(0, 6) == 'pusher' - data = @normalize(event, data) if data.id + @processWhenVisible => + # TODO remove job:requeued, once sf-restart-event has been merged + # TODO this also needs to clear logs on build:created if matrix jobs are already loaded + if event == 'job:created' || event == 'job:requeued' + if job = Travis.__container__.lookup('store:main').getById('job', data.job.id) + job.clearLog() - @processWhenVisible => - # TODO remove job:requeued, once sf-restart-event has been merged - # TODO this also needs to clear logs on build:created if matrix jobs are already loaded - if event == 'job:created' || event == 'job:requeued' - if job = Travis.__container__.lookup('store:main').getById('job', data.job.id) - job.clearLog() + Ember.run.next -> + Travis.receive(event, data) - Ember.run.next -> - Travis.receive(event, data) +TravisPusher.prototype.processSavedCallbacks = -> + while callback = @callbacksToProcess.shiftObject() + callback.call(this) - processSavedCallbacks: -> - while callback = @callbacksToProcess.shiftObject() - callback.call(this) +TravisPusher.prototype.processLater = (callback) -> + @callbacksToProcess.pushObject(callback) - processLater: (callback) -> - @callbacksToProcess.pushObject(callback) +TravisPusher.prototype.processWhenVisible = (callback) -> + if Visibility.hidden() && Visibility.isSupported() + @processLater(callback) + else + callback.call(this) - processWhenVisible: (callback) -> - if Visibility.hidden() && Visibility.isSupported() - @processLater(callback) - else - callback.call(this) +TravisPusher.prototype.normalize = (event, data) -> + switch event + when 'build:started', 'build:finished' + data + when 'job:created', 'job:started', 'job:requeued', 'job:finished', 'job:log', 'job:canceled', 'job:received' + data.queue = data.queue.replace('builds.', '') if data.queue + { job: data } + when 'worker:added', 'worker:updated', 'worker:removed' + { worker: data } + when 'annotation:created', 'annotation:updated' + { annotation: data } - normalize: (event, data) -> - switch event - when 'build:started', 'build:finished' - data - when 'job:created', 'job:started', 'job:requeued', 'job:finished', 'job:log', 'job:canceled', 'job:received' - data.queue = data.queue.replace('builds.', '') if data.queue - { job: data } - when 'worker:added', 'worker:updated', 'worker:removed' - { worker: data } - when 'annotation:created', 'annotation:updated' - { annotation: data } +TravisPusher.prototype.warn = (type, object) -> + console.warn(type, object.error) unless @ignoreWarning(type, object.error) - warn: (type, object) -> - console.warn(type, object.error) unless @ignoreWarning(type, object.error) +TravisPusher.prototype.ignoreWarning = (type, error) -> + code = error?.data?.code || 0 + message = error?.data?.message || '' + @ignoreCode(code) || @ignoreMessage(message) - ignoreWarning: (type, error) -> - code = error?.data?.code || 0 - message = error?.data?.message || '' - @ignoreCode(code) || @ignoreMessage(message) +TravisPusher.prototype.ignoreCode = (code) -> + code == 1006 - ignoreCode: (code) -> - code == 1006 - - ignoreMessage: (message) -> - message.indexOf('Existing subscription') == 0 or message.indexOf('No current subscription') == 0 - -pusher_host = $('meta[name="travis.pusher_host"]').attr('value') -pusher_path = $('meta[name="travis.pusher_path"]').attr('value') +TravisPusher.prototype.ignoreMessage = (message) -> + message.indexOf('Existing subscription') == 0 or message.indexOf('No current subscription') == 0 Pusher.SockJSTransport.isSupported = -> false if pusher_host != 'ws.pusherapp.com'