Gem version Gem downloads Build status Code Climate Code Coverage

SlowEnumeratorTools

SlowEnumeratorTools provides tools for transforming Ruby enumerators that produce data slowly and unpredictably (e.g. from a network source):

  • SlowEnumeratorTools.merge: given a collection of enumerables, creates a new enumerator that yields elements from any of these enumerables as soon as they become available.

  • SlowEnumeratorTools.batch: given an enumerable, creates a new enumerable that yields batches containing all elements currently available.

  • SlowEnumeratorTools.buffer: given an enumerable and a number, will create a buffer of that number of elements and try to fill it up with as many elements from that enumerable, so that they can be yielded immediately.

Installation

Add this line to your application's Gemfile:

gem 'slow_enumerator_tools'

And then execute:

$ bundle

Or install it yourself as:

$ gem install slow_enumerator_tools

Usage

SlowEnumeratorTools.merge

Given a collection of enumerables, creates a new enumerator that yields elements from any of these enumerables as soon as they become available.

This is useful for combining multiple event streams into a single one.

# Generate some slow enums
enums = []
enums << 5.times.lazy.map { |i| sleep(0.1 + rand * 0.2); [:a, i] }
enums << 5.times.lazy.map { |i| sleep(0.1 + rand * 0.2); [:b, i] }
enums << 5.times.lazy.map { |i| sleep(0.1 + rand * 0.2); [:c, i] }

# Merge and print
merged_enum = SlowEnumeratorTools.merge(enums)
merged_enum.each { |e| p e }

Example output:

[:b, 0]
[:a, 0]
[:b, 1]
[:c, 0]
[:a, 1]
[:b, 2]
[:c, 1]
[:c, 2]
[:a, 2]
[:b, 3]
[:c, 3]
[:b, 4]
[:a, 3]
[:c, 4]
[:a, 4]

SlowEnumeratorTools.batch

Given an enumerable, creates a new enumerable that yields batches containing all elements currently available.

This is useful for fetching all outstanding events on an event stream, without blocking.

# Generate a slow enum
enum = 4.times.lazy.map { |i| sleep(0.1); i }

# Batch
batch_enum = SlowEnumeratorTools.batch(enum)

# Wait until first batch is available
# … prints [0]
p batch_enum.next

# Give it enough time for the second batch to have accumulated more elements,
# … prints [1, 2]
sleep 0.25
p batch_enum.next

# Wait until final batch is available
# … prints [3]
p batch_enum.next

SlowEnumeratorTools.buffer

Given an enumerable and a number, will create a buffer of that number of elements and try to fill it up with as many elements from that enumerable.

This is particularly useful when reading from a slow source and writing to a slow sink, because the two will be able to work concurrently.

# Create (fake) articles enumerator
articles =
  Enumerator.new do |y|
    5.times do |i|
      sleep 1
      y << "Article #{i}"
    end
  end

# Buffer
articles = SlowEnumeratorTools.buffer(articles, 5)

# Print each article
# This takes 6 seconds, rather than 10!
articles.each do |a|
  sleep 1
end

Development

Install dependencies:

$ bundle

Run tests:

$ bundle exec rake

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/slow_enumerator_tools. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the SlowEnumeratorTools project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.