Commit 064d34e4 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'get_rid_of_as_json_es_indexer' into 'master'

[ES] More accurate as_indexed_json

fixes https://gitlab.com/gitlab-org/gitlab-ee/issues/349

It makes database indexer stable to corrupted data in database.

/cc @jnijhof 

See merge request !244
parents 89a63467 72fa451d
...@@ -7,6 +7,7 @@ v 8.6.0 (unreleased) ...@@ -7,6 +7,7 @@ v 8.6.0 (unreleased)
- [Elastic] Removing repository and wiki index after removing project - [Elastic] Removing repository and wiki index after removing project
- [Elastic] Update index on push to wiki - [Elastic] Update index on push to wiki
- [Elastic] Use subprocesses for ElasticSearch index jobs - [Elastic] Use subprocesses for ElasticSearch index jobs
- [Elastic] More accurate as_indexed_json (More stable database indexer)
v 8.5.4 v 8.5.4
- [Elastic][Security] Notes exposure - [Elastic][Security] Notes exposure
......
...@@ -27,12 +27,18 @@ module Elastic ...@@ -27,12 +27,18 @@ module Elastic
end end
def as_indexed_json(options = {}) def as_indexed_json(options = {})
as_json( data = {}
include: {
project: { only: :id }, # We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
author: { only: :id } # https://gitlab.com/gitlab-org/gitlab-ee/issues/349
} [:id, :iid, :title, :description, :created_at, :updated_at, :state, :project_id, :author_id].each do |attr|
).merge({ updated_at_sort: updated_at }) data[attr.to_s] = self.send(attr)
end
data['project'] = { 'id' => project.id }
data['author'] = { 'id' => author.id }
data['updated_at_sort'] = updated_at
data
end end
def self.elastic_search(query, options: {}) def self.elastic_search(query, options: {})
......
...@@ -34,28 +34,33 @@ module Elastic ...@@ -34,28 +34,33 @@ module Elastic
end end
def as_indexed_json(options = {}) def as_indexed_json(options = {})
as_json({ # We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
only: [ # https://gitlab.com/gitlab-org/gitlab-ee/issues/349
:id, data = {}
:iid,
:target_branch, [
:source_branch, :id,
:title, :iid,
:description, :target_branch,
:created_at, :source_branch,
:updated_at, :title,
:state, :description,
:merge_status, :created_at,
:source_project_id, :updated_at,
:target_project_id, :state,
:author_id :merge_status,
], :source_project_id,
include: { :target_project_id,
source_project: { only: :id }, :author_id
target_project: { only: :id }, ].each do |attr|
author: { only: :id } data[attr.to_s] = self.send(attr)
} end
}).merge({ updated_at_sort: updated_at })
data['source_project'] = { 'id' => source_project_id }
data['target_project'] = { 'id' => target_project_id }
data['author'] = { 'id' => author.id }
data['updated_at_sort'] = updated_at
data
end end
def self.elastic_search(query, options: {}) def self.elastic_search(query, options: {})
......
...@@ -16,9 +16,16 @@ module Elastic ...@@ -16,9 +16,16 @@ module Elastic
end end
def as_indexed_json(options = {}) def as_indexed_json(options = {})
as_json( data = {}
only: [:id, :note, :project_id, :created_at]
).merge({ updated_at_sort: updated_at }) # We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[:id, :note, :project_id, :created_at].each do |attr|
data[attr.to_s] = self.send(attr)
end
data['updated_at_sort'] = updated_at
data
end end
def self.elastic_search(query, options: {}) def self.elastic_search(query, options: {})
......
...@@ -29,23 +29,27 @@ module Elastic ...@@ -29,23 +29,27 @@ module Elastic
end end
def as_indexed_json(options = {}) def as_indexed_json(options = {})
as_json({ # We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
only: [ # https://gitlab.com/gitlab-org/gitlab-ee/issues/349
:id, data = {}
:name,
:path, [
:description, :id,
:namespace_id, :name,
:created_at, :path,
:archived, :description,
:visibility_level, :namespace_id,
:last_activity_at, :created_at,
:last_pushed_at :archived,
] :visibility_level,
}).merge({ :last_activity_at,
name_with_namespace: name_with_namespace, :name_with_namespace,
path_with_namespace: path_with_namespace :path_with_namespace
}) ].each do |attr|
data[attr.to_s] = self.send(attr)
end
data
end end
def self.elastic_search(query, options: {}) def self.elastic_search(query, options: {})
......
...@@ -27,4 +27,18 @@ describe "Issue", elastic: true do ...@@ -27,4 +27,18 @@ describe "Issue", elastic: true do
expect(Issue.elastic_search('term', options: options).total_count).to eq(2) expect(Issue.elastic_search('term', options: options).total_count).to eq(2)
end end
it "returns json with all needed elements" do
project = create :empty_project
issue = create :issue, project: project
expected_hash = issue.attributes.extract!('id', 'iid', 'title', 'description', 'created_at',
'updated_at', 'state', 'project_id', 'author_id')
expected_hash['project'] = { "id" => project.id }
expected_hash['author'] = { "id" => issue.author_id }
expected_hash['updated_at_sort'] = issue.updated_at
expect(issue.as_indexed_json).to eq(expected_hash)
end
end end
...@@ -27,4 +27,31 @@ describe "MergeRequest", elastic: true do ...@@ -27,4 +27,31 @@ describe "MergeRequest", elastic: true do
expect(MergeRequest.elastic_search('term', options: options).total_count).to eq(2) expect(MergeRequest.elastic_search('term', options: options).total_count).to eq(2)
end end
it "returns json with all needed elements" do
merge_request = create :merge_request
expected_hash = merge_request.attributes.extract!(
'id',
'iid',
'target_branch',
'source_branch',
'title',
'description',
'created_at',
'updated_at',
'state',
'merge_status',
'source_project_id',
'target_project_id',
'author_id'
)
expected_hash['source_project'] = { 'id' => merge_request.source_project_id }
expected_hash['target_project'] = { 'id' => merge_request.target_project_id }
expected_hash['author'] = { 'id' => merge_request.author.id }
expected_hash['updated_at_sort'] = merge_request.updated_at
expect(merge_request.as_indexed_json).to eq(expected_hash)
end
end end
...@@ -27,4 +27,20 @@ describe "Milestone", elastic: true do ...@@ -27,4 +27,20 @@ describe "Milestone", elastic: true do
expect(Milestone.elastic_search('term', options: options).total_count).to eq(2) expect(Milestone.elastic_search('term', options: options).total_count).to eq(2)
end end
it "returns json with all needed elements" do
milestone = create :milestone
expected_hash = milestone.attributes.extract!(
'id',
'title',
'description',
'project_id',
'created_at'
)
expected_hash[:updated_at_sort] = milestone.updated_at
expect(milestone.as_indexed_json).to eq(expected_hash)
end
end end
...@@ -26,4 +26,19 @@ describe "Note", elastic: true do ...@@ -26,4 +26,19 @@ describe "Note", elastic: true do
expect(Note.elastic_search('term', options: options).total_count).to eq(1) expect(Note.elastic_search('term', options: options).total_count).to eq(1)
end end
it "returns json with all needed elements" do
note = create :note
expected_hash = note.attributes.extract!(
'id',
'note',
'project_id',
'created_at'
)
expected_hash['updated_at_sort'] = note.updated_at
expect(note.as_indexed_json).to eq(expected_hash)
end
end end
...@@ -24,4 +24,25 @@ describe "Projects", elastic: true do ...@@ -24,4 +24,25 @@ describe "Projects", elastic: true do
expect(Project.elastic_search('test1', options: { pids: @project_ids }).total_count).to eq(1) expect(Project.elastic_search('test1', options: { pids: @project_ids }).total_count).to eq(1)
expect(Project.elastic_search('someone_elses_project', options: { pids: @project_ids }).total_count).to eq(0) expect(Project.elastic_search('someone_elses_project', options: { pids: @project_ids }).total_count).to eq(0)
end end
it "returns json with all needed elements" do
project = create :project
expected_hash = project.attributes.extract!(
'id',
'name',
'path',
'description',
'namespace_id',
'created_at',
'archived',
'visibility_level',
'last_activity_at'
)
expected_hash['name_with_namespace'] = project.name_with_namespace
expected_hash['path_with_namespace'] = project.path_with_namespace
expect(project.as_indexed_json).to eq(expected_hash)
end
end end
...@@ -44,4 +44,25 @@ describe "Snippet", elastic: true do ...@@ -44,4 +44,25 @@ describe "Snippet", elastic: true do
expect(Snippet.elastic_search('home', options: options).total_count).to eq(1) expect(Snippet.elastic_search('home', options: options).total_count).to eq(1)
expect(Snippet.elastic_search('index.php', options: options).total_count).to eq(1) expect(Snippet.elastic_search('index.php', options: options).total_count).to eq(1)
end end
it "returns json with all needed elements" do
snippet = create :project_snippet
expected_hash = snippet.attributes.extract!(
'id',
'title',
'file_name',
'content',
'created_at',
'updated_at',
'state',
'project_id',
'author_id',
)
expected_hash['project'] = { 'id' => snippet.project.id }
expected_hash['author'] = { 'id' => snippet.author.id }
expect(snippet.as_indexed_json).to eq(expected_hash)
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment