Commit f34f9a9ef364a5d67abece6dc235b015aa0fb380
Exists in
spb-stable
and in
2 other branches
Merge branch 'notes_finder_updated_at' into 'master'
NotesFinder filters by updated_at
Showing
7 changed files
with
62 additions
and
5 deletions
Show diff stats
app/assets/javascripts/notes.js.coffee
1 | 1 | class Notes |
2 | 2 | @interval: null |
3 | 3 | |
4 | - constructor: (notes_url, note_ids) -> | |
4 | + constructor: (notes_url, note_ids, last_fetched_at) -> | |
5 | 5 | @notes_url = notes_url |
6 | 6 | @notes_url = gon.relative_url_root + @notes_url if gon.relative_url_root? |
7 | 7 | @note_ids = note_ids |
8 | + @last_fetched_at = last_fetched_at | |
8 | 9 | @initRefresh() |
9 | 10 | @setupMainTargetNoteForm() |
10 | 11 | @cleanBinding() |
... | ... | @@ -76,9 +77,11 @@ class Notes |
76 | 77 | getContent: -> |
77 | 78 | $.ajax |
78 | 79 | url: @notes_url |
80 | + data: "last_fetched_at=" + @last_fetched_at | |
79 | 81 | dataType: "json" |
80 | 82 | success: (data) => |
81 | 83 | notes = data.notes |
84 | + @last_fetched_at = data.last_fetched_at | |
82 | 85 | $.each notes, (i, note) => |
83 | 86 | @renderNote(note) |
84 | 87 | ... | ... |
app/controllers/projects/notes_controller.rb
... | ... | @@ -5,9 +5,10 @@ class Projects::NotesController < Projects::ApplicationController |
5 | 5 | before_filter :authorize_admin_note!, only: [:update, :destroy] |
6 | 6 | |
7 | 7 | def index |
8 | + current_fetched_at = Time.now.to_i | |
8 | 9 | @notes = NotesFinder.new.execute(project, current_user, params) |
9 | 10 | |
10 | - notes_json = { notes: [] } | |
11 | + notes_json = { notes: [], last_fetched_at: current_fetched_at } | |
11 | 12 | |
12 | 13 | @notes.each do |note| |
13 | 14 | notes_json[:notes] << { | ... | ... |
app/finders/notes_finder.rb
1 | 1 | class NotesFinder |
2 | + FETCH_OVERLAP = 5.seconds | |
3 | + | |
2 | 4 | def execute(project, current_user, params) |
3 | 5 | target_type = params[:target_type] |
4 | 6 | target_id = params[:target_id] |
7 | + # Default to 0 to remain compatible with old clients | |
8 | + last_fetched_at = Time.at(params.fetch(:last_fetched_at, 0).to_i) | |
5 | 9 | |
6 | - case target_type | |
10 | + notes = case target_type | |
7 | 11 | when "commit" |
8 | 12 | project.notes.for_commit_id(target_id).not_inline.fresh |
9 | 13 | when "issue" |
... | ... | @@ -12,6 +16,11 @@ class NotesFinder |
12 | 16 | project.merge_requests.find(target_id).mr_and_commit_notes.inc_author.fresh |
13 | 17 | when "snippet" |
14 | 18 | project.snippets.find(target_id).notes.fresh |
19 | + else | |
20 | + raise 'invalid target_type' | |
15 | 21 | end |
22 | + | |
23 | + # Use overlapping intervals to avoid worrying about race conditions | |
24 | + notes.where('updated_at > ?', last_fetched_at - FETCH_OVERLAP) | |
16 | 25 | end |
17 | 26 | end | ... | ... |
app/views/projects/notes/_notes_with_form.html.haml
... | ... | @@ -7,4 +7,4 @@ |
7 | 7 | = render "projects/notes/form" |
8 | 8 | |
9 | 9 | :javascript |
10 | - new Notes("#{project_notes_path(target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}) | |
10 | + new Notes("#{project_notes_path(target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}) | ... | ... |
db/schema.rb
... | ... | @@ -11,7 +11,7 @@ |
11 | 11 | # |
12 | 12 | # It's strongly recommended that you check this file into your version control system. |
13 | 13 | |
14 | -ActiveRecord::Schema.define(version: 20140416185734) do | |
14 | +ActiveRecord::Schema.define(version: 20140428105831) do | |
15 | 15 | |
16 | 16 | # These are extensions that must be enabled in order to support this database |
17 | 17 | enable_extension "plpgsql" |
... | ... | @@ -200,6 +200,7 @@ ActiveRecord::Schema.define(version: 20140416185734) do |
200 | 200 | add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree |
201 | 201 | add_index "notes", ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree |
202 | 202 | add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree |
203 | + add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree | |
203 | 204 | |
204 | 205 | create_table "projects", force: true do |t| |
205 | 206 | t.string "name" | ... | ... |
... | ... | @@ -0,0 +1,38 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe NotesFinder do | |
4 | + let(:user) { create :user } | |
5 | + let(:project) { create :project } | |
6 | + let(:note1) { create :note_on_commit, project: project } | |
7 | + let(:note2) { create :note_on_commit, project: project } | |
8 | + let(:commit) { note1.noteable } | |
9 | + | |
10 | + before do | |
11 | + project.team << [user, :master] | |
12 | + end | |
13 | + | |
14 | + describe :execute do | |
15 | + let(:params) { { target_id: commit.id, target_type: 'commit', last_fetched_at: 1.hour.ago.to_i } } | |
16 | + | |
17 | + before do | |
18 | + note1 | |
19 | + note2 | |
20 | + end | |
21 | + | |
22 | + it 'should find all notes' do | |
23 | + notes = NotesFinder.new.execute(project, user, params) | |
24 | + notes.size.should eq(2) | |
25 | + end | |
26 | + | |
27 | + it 'should raise an exception for an invalid target_type' do | |
28 | + params.merge!(target_type: 'invalid') | |
29 | + expect { NotesFinder.new.execute(project, user, params) }.to raise_error('invalid target_type') | |
30 | + end | |
31 | + | |
32 | + it 'filters out old notes' do | |
33 | + note2.update_attribute(:updated_at, 2.hours.ago) | |
34 | + notes = NotesFinder.new.execute(project, user, params) | |
35 | + notes.should eq([note1]) | |
36 | + end | |
37 | + end | |
38 | +end | ... | ... |