Module: Redstruct::Utils::Iterable

Included in:
Factory, Hash, List, Set, SortedSet
Defined in:
lib/redstruct/utils/iterable.rb

Overview

Adds iterable capabilities to any object which implements a to_enum method with the correct arguments.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.bound_enumerator(enumerator, max:) ⇒ Enumerator

Returns an enumerator which limits the maximum number of iterations possible on another enumerator.

Parameters:

  • enumerator (Enumerator)

    the unbounded enumerator to wrap

  • max (Integer)

    maximum number of iterations possible

Returns:

  • (Enumerator)

Raises:

  • (ArgumentError)


37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/redstruct/utils/iterable.rb', line 37

def bound_enumerator(enumerator, max:)
  raise ArgumentError, 'max must be greater than 0' unless max.positive?

  return Enumerator.new do |yielder|
    iterations = 0
    loop do
      yielder << enumerator.next
      iterations += 1
      raise StopIteration if iterations == max
    end
  end
end

Instance Method Details

#each(match: '*', count: 10, max_iterations: 10_000, batch_size: 1, **options, &block) ⇒ Enumerator

Iterates over the keys of this factory using one of the redis scan commands (scan, zscan, hscan, sscan) For more about the scan command, see redis.io/commands/scan

Parameters:

  • match (String) (defaults to: '*')

    will prepend the factory namespace to the match string; see the redis documentation for the syntax

  • count (Integer) (defaults to: 10)

    maximum number of items returned per scan command (see Redis internals)

  • max_iterations (Integer) (defaults to: 10_000)

    maximum number of iterations; if nil given, could potentially never terminate

  • batch_size (Integer) (defaults to: 1)

    if greater than 1, will yield arrays of keys of size between 1 and batch_size

Returns:

  • (Enumerator)

    if no block given, returns an enumerator that you can chain with others



14
15
16
17
18
19
20
21
# File 'lib/redstruct/utils/iterable.rb', line 14

def each(match: '*', count: 10, max_iterations: 10_000, batch_size: 1, **options, &block) # rubocop: disable Metrics/ParameterLists
  enumerator = to_enum(match: match, count: count, **options)
  enumerator = enumerator.each_slice(batch_size) if batch_size > 1
  enumerator = Redstruct::Utils::Iterable.bound_enumerator(enumerator, max: max_iterations) unless max_iterations.nil?

  return enumerator unless block_given?
  return enumerator.each(&block)
end

#to_enum(match: '*', count: 10) ⇒ Object

Including classes should overload this class to provide an initial enumerator NOTE: to namespace the matcher (which you should), use ‘@factory.prefix(match)`

Parameters:

  • match (String) (defaults to: '*')

    see the redis documentation for the syntax

  • count (Integer) (defaults to: 10)

    number of keys fetched from redis per scan command (NOTE the enum still passes each keys 1 by 1)

Raises:

  • (NotImplementedError.new)


27
28
29
# File 'lib/redstruct/utils/iterable.rb', line 27

def to_enum(match: '*', count: 10) # rubocop: disable Lint/UnusedMethodArgument
  raise NotImplementedError.new, 'including classes should overload to_enum'
end