Merge branch 'master' into ps-ember-update
Conflicts: assets/scripts/app/models/artifact.coffee assets/scripts/app/store.coffee assets/scripts/app/views/job.coffee assets/scripts/spec/spec_helper.coffee
This commit is contained in:
commit
e02ece9424
92
assets/scripts/lib/travis/chunk_buffer.coffee
Normal file
92
assets/scripts/lib/travis/chunk_buffer.coffee
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
get = Ember.get
|
||||||
|
|
||||||
|
Travis.ChunkBuffer = Em.ArrayProxy.extend
|
||||||
|
timeout: 5000
|
||||||
|
checkTimeoutFrequency: 1000
|
||||||
|
start: 1
|
||||||
|
next: 1
|
||||||
|
|
||||||
|
init: ->
|
||||||
|
@_super.apply this, arguments
|
||||||
|
|
||||||
|
@lastInsert = 0
|
||||||
|
|
||||||
|
@set('next', @get('start'))
|
||||||
|
|
||||||
|
@checkTimeout()
|
||||||
|
|
||||||
|
if @get('content.length')
|
||||||
|
@get('queue.content').pushObjects @get('content').toArray()
|
||||||
|
|
||||||
|
arrangedContent: (->
|
||||||
|
[]
|
||||||
|
).property('content')
|
||||||
|
|
||||||
|
addObject: (obj) ->
|
||||||
|
@get('content').pushObject(obj)
|
||||||
|
|
||||||
|
removeObject: (obj) ->
|
||||||
|
@get('content').removeObject(obj)
|
||||||
|
|
||||||
|
replaceContent: (idx, amt, objects) ->
|
||||||
|
@get('content').replace(idx, amt, objects)
|
||||||
|
|
||||||
|
queue: (->
|
||||||
|
Em.ArrayProxy.create(Em.SortableMixin,
|
||||||
|
content: []
|
||||||
|
sortProperties: ['number']
|
||||||
|
sortAscending: true
|
||||||
|
)
|
||||||
|
).property()
|
||||||
|
|
||||||
|
contentArrayDidChange: (array, index, removedCount, addedCount) ->
|
||||||
|
@_super.apply this, arguments
|
||||||
|
|
||||||
|
if addedCount
|
||||||
|
queue = @get('queue.content')
|
||||||
|
addedObjects = array.slice(index, index + addedCount)
|
||||||
|
console.log 'Added log parts with numbers:', addedObjects.map( (element) -> get(element, 'number') )+'', 'current', @get('next')
|
||||||
|
queue.pushObjects addedObjects
|
||||||
|
@check()
|
||||||
|
@inserted()
|
||||||
|
|
||||||
|
check: ->
|
||||||
|
queue = @get('queue')
|
||||||
|
next = @get('next')
|
||||||
|
|
||||||
|
arrangedContent = @get('arrangedContent')
|
||||||
|
toPush = []
|
||||||
|
|
||||||
|
while queue.get('firstObject.number') <= next
|
||||||
|
element = queue.shiftObject()
|
||||||
|
if get(element, 'number') == next
|
||||||
|
toPush.pushObject get(element, 'content')
|
||||||
|
next += 1
|
||||||
|
|
||||||
|
if toPush.length
|
||||||
|
arrangedContent.pushObjects toPush
|
||||||
|
|
||||||
|
@set('next', next)
|
||||||
|
|
||||||
|
inserted: ->
|
||||||
|
now = @now()
|
||||||
|
@lastInsert = now
|
||||||
|
|
||||||
|
checkTimeout: ->
|
||||||
|
now = @now()
|
||||||
|
if now - @lastInsert > @get('timeout')
|
||||||
|
@giveUpOnMissingParts()
|
||||||
|
@set 'runLaterId', Ember.run.later(this, @checkTimeout, @get('checkTimeoutFrequency'))
|
||||||
|
|
||||||
|
willDestroy: ->
|
||||||
|
Ember.run.cancel @get('runLaterId')
|
||||||
|
@_super.apply this, arguments
|
||||||
|
|
||||||
|
now: ->
|
||||||
|
(new Date()).getTime()
|
||||||
|
|
||||||
|
giveUpOnMissingParts: ->
|
||||||
|
if number = @get('queue.firstObject.number')
|
||||||
|
console.log 'Giving up on missing parts in the buffer, switching to:', number
|
||||||
|
@set('next', number)
|
||||||
|
@check()
|
|
@ -6,7 +6,6 @@ minispade.require 'app'
|
||||||
waits(50)
|
waits(50)
|
||||||
runs ->
|
runs ->
|
||||||
Travis.reset()
|
Travis.reset()
|
||||||
|
|
||||||
url = "/#{url}" unless url.match /^\//
|
url = "/#{url}" unless url.match /^\//
|
||||||
Travis.__container__.lookup('router:main').handleURL(url)
|
Travis.__container__.lookup('router:main').handleURL(url)
|
||||||
|
|
||||||
|
|
93
assets/scripts/spec/unit/chunk_buffer_spec.coffee
Normal file
93
assets/scripts/spec/unit/chunk_buffer_spec.coffee
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
createChunk = (number, content) ->
|
||||||
|
Em.Object.create(number: number, content: content)
|
||||||
|
|
||||||
|
describe 'Travis.ChunkBuffer', ->
|
||||||
|
it 'waits for parts to be in order before revealing them', ->
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: [])
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(3, "baz")
|
||||||
|
buffer.pushObject createChunk(2, "bar")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(0)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(1, "foo")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(3)
|
||||||
|
|
||||||
|
expect(buffer.toArray()).toEqual(['foo', 'bar', 'baz'])
|
||||||
|
|
||||||
|
it 'ignores a part if it fails to be delivered within timeout', ->
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: [], timeout: 20, checkTimeoutFrequency: 5)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(3, "baz")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(0)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(1, "foo")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(1)
|
||||||
|
|
||||||
|
waits 40
|
||||||
|
runs ->
|
||||||
|
expect(buffer.get('length')).toEqual(2)
|
||||||
|
expect(buffer.toArray()).toEqual(['foo', 'baz'])
|
||||||
|
|
||||||
|
buffer.destroy()
|
||||||
|
|
||||||
|
it 'works correctly when parts are passed as content', ->
|
||||||
|
content = [createChunk(2, 'bar')]
|
||||||
|
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: content)
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(0)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(1, "foo")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(2)
|
||||||
|
expect(buffer.toArray()).toEqual(['foo', 'bar'])
|
||||||
|
|
||||||
|
it 'works correctly when parts duplicated', ->
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: [])
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(1, "foo")
|
||||||
|
buffer.pushObject createChunk(2, "bar")
|
||||||
|
buffer.pushObject createChunk(3, "baz")
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(2, "bar")
|
||||||
|
buffer.pushObject createChunk(3, "baz")
|
||||||
|
buffer.pushObject createChunk(4, "qux")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(4)
|
||||||
|
expect(buffer.toArray()).toEqual(['foo', 'bar', 'baz', 'qux'])
|
||||||
|
|
||||||
|
it 'fires array observers properly', ->
|
||||||
|
changes = []
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: [])
|
||||||
|
|
||||||
|
observer = Em.Object.extend(
|
||||||
|
init: ->
|
||||||
|
@_super.apply this, arguments
|
||||||
|
|
||||||
|
@get('content').addArrayObserver this,
|
||||||
|
willChange: 'arrayWillChange',
|
||||||
|
didChange: 'arrayDidChange'
|
||||||
|
|
||||||
|
arrayWillChange: (->)
|
||||||
|
arrayDidChange: (array, index, removedCount, addedCount) ->
|
||||||
|
changes.pushObject([index, addedCount])
|
||||||
|
).create(content: buffer)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(2, "baz")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(0)
|
||||||
|
expect(changes.length).toEqual(0)
|
||||||
|
|
||||||
|
buffer.pushObject createChunk(1, "foo")
|
||||||
|
|
||||||
|
expect(buffer.get('length')).toEqual(2)
|
||||||
|
expect(changes.length).toEqual(1)
|
||||||
|
expect(changes[0]).toEqual([0, 2])
|
||||||
|
|
||||||
|
it 'sets next to start if start is given at init', ->
|
||||||
|
buffer = Travis.ChunkBuffer.create(content: [], start: 5)
|
||||||
|
expect(buffer.get('next')).toEqual(5)
|
Loading…
Reference in New Issue
Block a user