Class: PgEventstore::Web::Paginator::EventsCollection

Inherits:
BaseCollection
  • Object
show all
Defined in:
lib/pg_eventstore/web/paginator/events_collection.rb

Constant Summary collapse

SQL_DIRECTIONS =

Returns SQL directions, string-to-symbol mapping.

Returns:

  • (Hash<String => Symbol>)

    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.

Returns:

  • (Hash<String => Integer>)

    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.

Returns:

  • (Integer)

    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

Instance Attribute Summary

Attributes inherited from BaseCollection

#config_name, #options, #order, #per_page, #starting_id

Instance Method Summary collapse

Methods inherited from BaseCollection

#count

Constructor Details

#initialize(config_name, starting_id:, per_page:, order:, options: {}, system_stream: nil) ⇒ EventsCollection

Returns a new instance of EventsCollection.

Parameters:

  • config_name (Symbol)
  • starting_id (String, Integer, nil)
  • per_page (Integer)
  • order (Symbol)

    :asc or :desc

  • options (Hash) (defaults to: {})

    additional options to filter the collection

  • system_stream (String, nil) (defaults to: nil)

    a name of system stream



28
29
30
31
# File 'lib/pg_eventstore/web/paginator/events_collection.rb', line 28

def initialize(config_name, starting_id:, per_page:, order:, options: {}, system_stream: nil)
  super(config_name, starting_id: starting_id, per_page: per_page, order: order, options: options)
  @stream = system_stream ? PgEventstore::Stream.system_stream(system_stream) : PgEventstore::Stream.all_stream
end

Instance Method Details

#collectionArray<PgEventstore::Event>

Returns:



34
35
36
37
38
39
# File 'lib/pg_eventstore/web/paginator/events_collection.rb', line 34

def collection
  @collection ||= PgEventstore.client(config_name).read(
    @stream,
    options: options.merge(from_position: starting_id, max_count: per_page, direction: order)
  )
end

#next_page_starting_idInteger?

Returns:

  • (Integer, nil)


42
43
44
45
46
47
48
49
50
51
# File 'lib/pg_eventstore/web/paginator/events_collection.rb', line 42

def next_page_starting_id
  return unless collection.size == per_page

  from_position = event_global_position(collection.first)
  sql_builder = QueryBuilders::EventsFiltering.events_filtering(
    @stream,
    options.merge(from_position: from_position, max_count: 1, direction: order)
  ).to_sql_builder.unselect.select('global_position').offset(per_page)
  global_position(sql_builder)
end

#prev_page_starting_idInteger?

Returns:

  • (Integer, nil)


54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/pg_eventstore/web/paginator/events_collection.rb', line 54

def prev_page_starting_id
  from_position = event_global_position(collection.first) || starting_id
  sql_builder = QueryBuilders::EventsFiltering.events_filtering(
    @stream,
    options.merge(from_position: from_position, max_count: per_page, direction: order == :asc ? :desc : :asc)
  ).to_sql_builder.unselect.select('global_position').offset(1)
  sql, params = sql_builder.to_exec_params
  sql = "SELECT * FROM (#{sql}) events ORDER BY global_position #{order} LIMIT 1"
  connection.with do |conn|
    conn.exec_params(sql, params)
  end.to_a.dig(0, 'global_position')
end

#total_countInteger

Returns:

  • (Integer)


68
69
70
71
72
73
74
75
76
77
78
# File 'lib/pg_eventstore/web/paginator/events_collection.rb', line 68

def total_count
  @total_count ||=
    begin
      sql_builder = QueryBuilders::EventsFiltering.events_filtering(@stream, options).to_sql_builder
      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