After change log rendering method, to append HTML elements instead of
rerendering the entire thing, the case of gradual rendering of a log
started to behave much better (because we just append new elements), but
the initial render took a bit longer, because of the fact that appending
large separate HTML elements to DOM at once is not a good idea.
In order to make the situation better I added simple optimization.
Elements are added to DocumentFragment node before inserting to DOM and
appended to DOM only after all elements are processed. That way, when
log needs to be rendered all at once, we will not do any DOM operations
until log is ready.
Till now, log viewer was rendered in handlebars, which was the simplest
solution, but it had a major drawback - every append to log caused it to
rerender which was not efficient and memory consuming.
The new approach is to make Travis.Log interpret the log and send lines
with instructions to the view, so for example if view should add a line,
it gets something like:
{ number: 1, content: '$ bundle install' }
Such approach is required to handle cases where data coming from pusher
is not actually a new line. For example output containing dots from
tests needs to be appended:
$ rake
....
Such output could be sent to client in 2 chunks: "$ rake\n.." and "..".
In such situation we would need to send 3 instructions:
{ number: 1, content: '$ rake' }
{ number: 2, content: '..' }
{ number: 2, content: '..', append: true }
The third instruction can come much later, because tests can take a
while to run, so we can't assume that each line will come in one piece.
The other scenario is \r, for example when showing progress:
\rDownloading: 10%
\rDownloading: 50%
\rDownloading: 100%
Such input should be changed into such instructions:
{ number: 1, content: 'Downloading: 10%' }
{ number: 1, content: 'Downloading: 50%', replace: true }
{ number: 1, content: 'Downloading: 100%', replace: true }
Travis.Log also supports folds, for example on bundle install, the code
was rewritten to make folds management simpler.
We sometimes get "done" as a response body from API when authenticating.
We should properly fix it in the API, but for now I will add this quick
fix to not completely break on login when it happens until we have
proper fix.
Default regexp used in ember does not work well for us. With repos
starting with 'stats', ember will match such url for /stats/ page, even
though the rest of the url is different, I added ability to overwrite
default regexp.
Commit fields come in with build:started payload. We should split it
into 2 separate keys in the payload, like:
{
build: { .... },
commit: { .... }
}
but I can't change pusher v1 API at the moment, due to backwards
compatibility with the old client. We will be able to remove this manual
extraction as soon as we switch to pusher v2 API.
I couldn't reproduce it locally, but I got this exception once. This
implementation will need to be rewritten after upgrading to newest
ember, so I'll leave it as it is for now.
It's best to do that, because 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.
While testing in the wild I spotted a few problems with it:
* it didn't work for camel case names.
* it was sometimes setting loaded data too late - it needed to use find
and then save data on the record. Instead it should save data in
special array saved on store, indexed by clientId
* there is already method to get attributes in ember-data, it just
doesn't work with Travis.Foo.get('attributes'), it needs
Ember.get(Travis.Foo, 'attributes') - it makes implementation much
shorter
If we have 2 jobs within 1 build, with such config values:
{ rvm: 'jruby-head', jdk: 'oraclejdk7' }
{ rvm: '1.9.3', jdk: null }
We should return jdk in configValues for second build, even if it's not
present. Otherwise table rows may be missing.
(closes#28)
If we keep it only on states lower than root and afterSignIn is sent
when app is still in root.loading (which is often the case as we need to
wait for repository deserialization), it will try to find afterSignIn on
root.
In order to minimize ajax requests, I implemented isComplete property,
which can be used to check if record is fetched from the API or if it
was just partially loaded (for example by pusher event). This is nice in
terms of requests reduction, but caries risk of showing incomplete data.
This commit fixes this situation by saving which attributes were
provided on "incomplete" load and triggering refresh when any unknown
attribute is tried to be fetched.
The implementation is really simple and will probably need refactoring,
but I would like to test it in the wild before putting much more time
into it.
When we get payload from pusher, we usually don't send the entire
record. Initially such records where fetched from server right away to
get missing data. This was done becuase Ember can't tell if given data
is complete or not and just assumes that the record is loaded.
To not fire unneeded request, this code sets incomplete flag on records
loaded from pusher and loads the rest of the data only if needed.
Technically it's the same thing, but since in coffeescript it's just a
few characters, there is no need to use something that does not
explicitly say what it does.
initialState in some of the routes where needed because router was
behaving incorrectly when going to 'default state'. Now it is fixed, so
initialState entries are not needed anymore in those places.
This is working implementation of links on log line numbers. Although it
does the job, it's really hacky and involves overriding some of the
ember's methods (resolvePath, routeMatcher) beacuse currently
HistoryLocation can't handle hash additions in an easy way.
This code should be fixed as soon as ember's router gets more powerful
and gives much more granular control over matching routes.