diff --git a/assets/scripts/app/store.coffee b/assets/scripts/app/store.coffee index 3b1d6b93..23df703a 100644 --- a/assets/scripts/app/store.coffee +++ b/assets/scripts/app/store.coffee @@ -77,14 +77,16 @@ Travis.Store = DS.Store.extend _loadOne: (store, type, json) -> root = type.singularName() - # we get other types of records only on build, it comes with repository - # attached. I don't want to use store.sideload here as it will not use merge, - # if we need sideload becasue we have side records with other events it needs to - # be revised + # we get other types of records only in a few situations and + # it's not always needed to update data, so I'm specyfing which + # things I want to update here: if type == Travis.Build && (json.repository || json.repo) @loadIncomplete(Travis.Repo, json.repository || json.repo) else if type == Travis.Worker && json.worker.payload if repo = (json.worker.payload.repo || json.worker.payload.repository) + # I use skipIfExists here, cause worker payload is usually outdated + # If there is no info on repo yet, it's worth to add it, but if it already + # exists, we will most likely end up with inconsistent situation @loadIncomplete(Travis.Repo, repo, skipIfExists: true) if job = json.worker.payload.job @loadIncomplete(Travis.Job, job) @@ -102,7 +104,18 @@ Travis.Store = DS.Store.extend if data = recordsData[clientId] data.contains(key) - loadIncomplete: (type, hash) -> + loadIncomplete: (type, hash, options) -> + options ?= {} + + id = hash.id + + typeMap = @typeMapFor(type) + dataCache = typeMap.cidToHash + clientId = typeMap.idToCid[id] + + if dataCache[clientId] && options.skipIfExists + return + result = @merge(type, hash) if result && result.clientId diff --git a/assets/scripts/spec/event_spec.coffee b/assets/scripts/spec/event_spec.coffee index 73ea19dc..63645cfc 100644 --- a/assets/scripts/spec/event_spec.coffee +++ b/assets/scripts/spec/event_spec.coffee @@ -187,3 +187,33 @@ describe 'events', -> row: 3 item: { name: 'ruby-3', state: 'ready' } + + describe 'an event updating a worker', -> + beforeEach -> + app '/travis-ci/travis-core' + waitFor workersRendered + + it 'does not update repository if it\'s already in store', -> + payload = + worker: + id: 1 + host: 'worker.travis-ci.org' + name: 'ruby-2' + state: 'working' + payload: + repository: + id: 1 + last_build_id: 999 + last_build_number: '999' + + Em.run -> + Travis.app.receive 'worker:updated', payload + + waits(100) + runs -> + listsRepo + row: 2 + item: { slug: 'travis-ci/travis-core', build: { number: 1, url: '/travis-ci/travis-core/builds/1', duration: '30 sec', finishedAt: '3 minutes ago' } } + + + diff --git a/public/scripts/app.js b/public/scripts/app.js index f0416cc6..cdf442c2 100644 --- a/public/scripts/app.js +++ b/public/scripts/app.js @@ -30753,4 +30753,4 @@ var _require=function(){function c(a,c){document.addEventListener?a.addEventList ++g&&setTimeout(c,0)})}}(); (function(){!window.WebSocket&&window.MozWebSocket&&(window.WebSocket=window.MozWebSocket);if(window.WebSocket)Pusher.Transport=window.WebSocket,Pusher.TransportType="native";var c=(document.location.protocol=="http:"?Pusher.cdn_http:Pusher.cdn_https)+Pusher.VERSION,a=[];window.JSON||a.push(c+"/json2"+Pusher.dependency_suffix+".js");if(!window.WebSocket)window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION=!0,a.push(c+"/flashfallback"+Pusher.dependency_suffix+".js");var b=function(){return window.WebSocket?function(){Pusher.ready()}: function(){window.WebSocket?(Pusher.Transport=window.WebSocket,Pusher.TransportType="flash",window.WEB_SOCKET_SWF_LOCATION=c+"/WebSocketMain.swf",WebSocket.__addTask(function(){Pusher.ready()}),WebSocket.__initialize()):(Pusher.Transport=null,Pusher.TransportType="none",Pusher.ready())}}(),e=function(a){var b=function(){document.body?a():setTimeout(b,0)};b()},g=function(){e(b)};a.length>0?_require(a,g):g()})(); -;minispade.register('app', "(function() {(function() {\nminispade.require('auth');\nminispade.require('controllers');\nminispade.require('helpers');\nminispade.require('models');\nminispade.require('pusher');\nminispade.require('routes');\nminispade.require('slider');\nminispade.require('store');\nminispade.require('tailing');\nminispade.require('templates');\nminispade.require('views');\nminispade.require('config/locales');\nminispade.require('data/sponsors');\n\n Travis.reopen({\n App: Em.Application.extend({\n autoinit: false,\n currentUserBinding: 'auth.user',\n authStateBinding: 'auth.state',\n init: function() {\n this._super.apply(this, arguments);\n this.store = Travis.Store.create();\n this.store.loadMany(Travis.Sponsor, Travis.SPONSORS);\n this.slider = new Travis.Slider();\n this.pusher = new Travis.Pusher(Travis.config.pusher_key);\n this.tailing = new Travis.Tailing();\n return this.set('auth', Travis.Auth.create({\n app: this,\n endpoint: Travis.config.api_endpoint\n }));\n },\n storeAfterSignInPath: function(path) {\n return this.get('auth').storeAfterSignInPath(path);\n },\n autoSignIn: function(path) {\n return this.get('auth').autoSignIn(path);\n },\n signIn: function() {\n return this.get('auth').signIn();\n },\n signOut: function() {\n this.get('auth').signOut();\n return this.get('router').send('afterSignOut');\n },\n receive: function() {\n return this.store.receive.apply(this.store, arguments);\n },\n toggleSidebar: function() {\n var element;\n $('body').toggleClass('maximized');\n element = $('');\n $('#top .profile').append(element);\n Em.run.later((function() {\n return element.remove();\n }), 10);\n element = $('');\n $('#repo').append(element);\n return Em.run.later((function() {\n return element.remove();\n }), 10);\n }\n })\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=app");minispade.register('auth', "(function() {(function() {\n\n this.Travis.Auth = Ember.Object.extend({\n iframe: $('