provides tools for transforming Ruby enumerators that produce data slowly and unpredictably
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib
scripts
spec
.gitignore
.rspec
.rubocop.yml
.travis.yml
CODE_OF_CONDUCT.md
Gemfile
LICENSE.txt
NEWS.md
README.md
Rakefile
slow_enumerator_tools.gemspec

README.md

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/ddfreyne/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.