Class: PgEventstore::Web::Paginator::StreamsCollection
- Inherits:
-
BaseCollection
- Object
- BaseCollection
- PgEventstore::Web::Paginator::StreamsCollection
- Defined in:
- lib/pg_eventstore/web/paginator/streams_collection.rb,
sig/pg_eventstore/web/paginator/streams_collection.rbs
Constant Summary collapse
- SQL_DIRECTIONS =
Returns SQL directions, string-to-symbol mapping.
{ 'asc' => :asc, 'desc' => :desc, }.tap do |directions| directions.default = :desc end.freeze
- PER_PAGE =
Returns per page limits, string to Integer mapping.
%w[10 20 50 100 1000].to_h { [_1, _1.to_i] }.tap do |per_page| per_page.default = 10 end.freeze
- MAX_NUMBER_TO_COUNT =
Returns max number of events after which we don't perform the exact count and keep the estimate count instead because of the potential performance degradation.
10_000
Constants inherited from BaseCollection
BaseCollection::MIN_QUERY_SIZE_FOR_ADVANCE_SEARCH
Instance Attribute Summary
Attributes inherited from BaseCollection
#config_name, #options, #order, #per_page, #starting_id
Instance Method Summary collapse
- #collection ⇒ Array<PgEventstore::Stream>
- #estimate_count(sql_builder) ⇒ Integer
- #next_page_starting_id ⇒ Integer?
- #prev_page_starting_id ⇒ Integer?
- #regular_count(sql_builder) ⇒ Integer
- #starting_position(sql_builder) ⇒ Integer?
- #total_count ⇒ Integer
Methods inherited from BaseCollection
#connection, #count, #initialize
Constructor Details
This class inherits a constructor from PgEventstore::Web::Paginator::BaseCollection
Instance Method Details
#collection ⇒ Array<PgEventstore::Stream>
23 24 25 26 27 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 23 def collection @collection ||= PgEventstore.client(config_name).read_streams( options: { from_position: starting_id, max_count: per_page, direction: order } ) end |
#estimate_count(sql_builder) ⇒ Integer
68 69 70 71 72 73 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 68 def estimate_count(sql_builder) sql, params = sql_builder.to_exec_params connection.with do |conn| conn.exec_params("EXPLAIN #{sql}", params) end.to_a.first['QUERY PLAN'].match(/rows=(\d+)/)[1].to_i end |
#next_page_starting_id ⇒ Integer?
30 31 32 33 34 35 36 37 38 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 30 def next_page_starting_id return unless collection.size == per_page from_position = collection.first&.starting_position sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination( from_position:, max_count: 1, direction: order ).unselect.select('starting_position').offset(per_page) starting_position(sql_builder) end |
#prev_page_starting_id ⇒ Integer?
41 42 43 44 45 46 47 48 49 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 41 def prev_page_starting_id from_position = collection.first&.starting_position || starting_id sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination( from_position:, max_count: per_page, direction: order == :asc ? :desc : :asc ).unselect.select('starting_position').offset(1) sql_builder = SQLBuilder.new.select('starting_position').from(sql_builder) sql_builder.order("starting_position #{order}").limit(1) starting_position(sql_builder) end |
#regular_count(sql_builder) ⇒ Integer
77 78 79 80 81 82 83 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 77 def regular_count(sql_builder) sql_builder.unselect.select('count(*) as count_all') connection.with do |conn| conn.exec_params(*sql_builder.to_exec_params) end.to_a.first['count_all'] end |
#starting_position(sql_builder) ⇒ Integer?
87 88 89 90 91 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 87 def starting_position(sql_builder) connection.with do |conn| conn.exec_params(*sql_builder.to_exec_params) end.to_a.dig(0, 'starting_position') end |
#total_count ⇒ Integer
52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/pg_eventstore/web/paginator/streams_collection.rb', line 52 def total_count @total_count ||= begin sql_builder = QueryBuilders::StreamsGlobalIndexFiltering.sql_builder_for_basic_pagination({}) sql_builder.remove_limit.remove_group.remove_order count = estimate_count(sql_builder) return count if count > MAX_NUMBER_TO_COUNT regular_count(sql_builder) end end |