diff --git a/CHANGELOG.md b/CHANGELOG.md index ed4b727..eaf095b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ Please mark backwards incompatible changes with an exclamation mark at the start ## [Unreleased] ### Added +- The `#totals` method to `Elasticsearch::Stats::Index`, this gives the caller + access to the index's total metrics. +- The `Elasticsearch::Stats::Index::Totals` class. The class contains information + about an index's total metrics, for example, total number of documents, total + size, etc. - It is now possible to configure the type used by the `RSpec::TestDataCollector` class when pushing documents to Elasticsearch. If no type is specified in the configuration the default type will be used. diff --git a/lib/jay_api/elasticsearch/stats/index.rb b/lib/jay_api/elasticsearch/stats/index.rb index 7c0eb2b..2915805 100644 --- a/lib/jay_api/elasticsearch/stats/index.rb +++ b/lib/jay_api/elasticsearch/stats/index.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require_relative 'index/totals' + module JayAPI module Elasticsearch class Stats @@ -13,6 +15,17 @@ def initialize(name, data) @name = name @data = data end + + # @return [JayAPI::Elasticsearch::Stats::Index::Totals] Information + # about the index's total metrics. + # @raise [KeyError] If the given data doesn't have a +total+ key. + def totals + @totals ||= ::JayAPI::Elasticsearch::Stats::Index::Totals.new(data.fetch('total')) + end + + private + + attr_reader :data end end end diff --git a/lib/jay_api/elasticsearch/stats/index/totals.rb b/lib/jay_api/elasticsearch/stats/index/totals.rb new file mode 100644 index 0000000..62dca94 --- /dev/null +++ b/lib/jay_api/elasticsearch/stats/index/totals.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module JayAPI + module Elasticsearch + class Stats + class Index + # Contains information about an index's totals (docs, used space, etc). + class Totals + # @param [Hash] data The data under the index's +total+ key. + def initialize(data) + @data = data + end + + # @return [Integer] The total number of documents in the index. + def docs_count + @docs_count ||= docs.fetch('count') + end + + # @return [Integer] The total number of deleted documents in the index. + def deleted_docs + @deleted_docs ||= docs.fetch('deleted') + end + + private + + attr_reader :data + + # @return [Hash] The information about the documents in the index. + # Looks something like this: + # + # { "count" => 530626, "deleted" => 11 } + # + # @raise [KeyError] If the given data doesn't have a +docs+ key. + def docs + @docs ||= data.fetch('docs') + end + end + end + end + end +end diff --git a/spec/jay_api/elasticsearch/stats/index/totals_spec.rb b/spec/jay_api/elasticsearch/stats/index/totals_spec.rb new file mode 100644 index 0000000..18e64a0 --- /dev/null +++ b/spec/jay_api/elasticsearch/stats/index/totals_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'jay_api/elasticsearch/stats/index/totals' + +RSpec.describe JayAPI::Elasticsearch::Stats::Index::Totals do + subject(:totals) { described_class.new(data) } + + let(:docs) do + { 'count' => 530_626, 'deleted' => 11 } + end + + let(:data) do + { + 'docs' => docs, + 'store' => { 'size_in_bytes' => 1_001_425_875, 'reserved_in_bytes' => 0 }, + 'flush' => { 'total' => 25, 'periodic' => 0, 'total_time_in_millis' => 1924 }, + 'warmer' => { 'current' => 0, 'total' => 30, 'total_time_in_millis' => 0 }, + 'completion' => { 'size_in_bytes' => 0 } + } + end + + shared_examples_for '#docs' do + context "when the data doesn't have a 'docs' key" do + let(:data) { super().except('docs') } + + it 'raises a KeyError' do + expect { method_call }.to raise_error( + KeyError, 'key not found: "docs"' + ) + end + end + end + + describe '#docs_count' do + subject(:method_call) { totals.docs_count } + + it_behaves_like '#docs' + + context "when the data doesn't contain the total number of documents" do + let(:docs) { super().except('count') } + + it 'raises a KeyError' do + expect { method_call }.to raise_error( + KeyError, 'key not found: "count"' + ) + end + end + + it 'returns the expected number of documents' do + expect(method_call).to eq(530_626) + end + end + + describe '#deleted_docs' do + subject(:method_call) { totals.deleted_docs } + + it_behaves_like '#docs' + + context "when the data doesn't contain the number of deleted documents" do + let(:docs) { super().except('deleted') } + + it 'raises a KeyError' do + expect { method_call }.to raise_error( + KeyError, 'key not found: "deleted"' + ) + end + end + + it 'returns the expected number of deleted documents' do + expect(method_call).to eq(11) + end + end +end diff --git a/spec/jay_api/elasticsearch/stats/index_spec.rb b/spec/jay_api/elasticsearch/stats/index_spec.rb index 252d14a..823aa0a 100644 --- a/spec/jay_api/elasticsearch/stats/index_spec.rb +++ b/spec/jay_api/elasticsearch/stats/index_spec.rb @@ -6,7 +6,20 @@ subject(:index) { described_class.new(name, data) } let(:name) { 'xyz01_integration_tests' } - let(:data) { {} } + + let(:data) do + { + 'uuid' => 'rouPqkZMSrKHY5bzL7OhTA', + 'primaries' => { + 'docs' => { 'count' => 265_313, 'deleted' => 0 }, + 'store' => { 'size_in_bytes' => 497_335_237, 'reserved_in_bytes' => 0 } + }, + 'total' => { + 'docs' => { 'count' => 530_626, 'deleted' => 11 }, + 'store' => { 'size_in_bytes' => 1_001_425_875, 'reserved_in_bytes' => 0 } + } + } + end describe '#initialize' do subject(:method_call) { index } @@ -16,4 +29,45 @@ expect(index.name).to be(name) end end + + describe '#totals' do + subject(:method_call) { index.totals } + + let(:totals_hash) do + { + 'docs' => { 'count' => 530_626, 'deleted' => 11 }, + 'store' => { 'size_in_bytes' => 1_001_425_875, 'reserved_in_bytes' => 0 } + } + end + + let(:totals) do + instance_double( + JayAPI::Elasticsearch::Stats::Index::Totals + ) + end + + before do + allow(JayAPI::Elasticsearch::Stats::Index::Totals) + .to receive(:new).and_return(totals) + end + + context "when the index's data doesn't contain the totals information" do + let(:data) { super().except('total') } + + it 'raises a KeyError' do + expect { method_call }.to raise_error( + KeyError, 'key not found: "total"' + ) + end + end + + it 'creates a new instance of the Totals class with the expected Hash' do + expect(JayAPI::Elasticsearch::Stats::Index::Totals).to receive(:new).with(totals_hash) + method_call + end + + it 'returns the instance of the Totals class' do + expect(method_call).to be(totals) + end + end end