• Stars
    star
    209
  • Rank 188,325 (Top 4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 11 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Yet another Futures implementation in Ruby

Futuroscope

Gem Version Build Status Code Climate Coverage Status Dependency Status

Join a live discussion on Gitter: Gitter chat

Futursocope is a simple library that implements futures in ruby. Futures are a concurrency pattern meant to help you deal with threads in a simple, transparent way.

It's specially useful in situations where you have calls to an expensive resource that could be done in parallel (they are not chained), but you don't wanna deal with low-level threads. HTTP calls are a good example.

Also useful when you want to spin up a process that runs in the background, do some stuff in the middle, and wait for that process to return.

The awesome Futuroscope park

You can learn more about futures here in this excellent article from @jpignata: Concurrency Patterns in Ruby: Futures

In Futuroscope, futures are instantiated with a simple ruby block. The future's execution will immediately start in a different thread and when you call a method on in it will be forwarded to the block's return value.

If the thread didn't finish yet, it will block the program's execution until it's finished. Otherwise, it will immediately return its value.

Futuroscope is tested on MRI 1.9.3, MRI 2.0.0, MRI 2.1.0, Rubinius (2.2.3) and JRuby (1.9).

Check out futuroscope's post on Codegram's blog to get started.

Installation

Add this line to your application's Gemfile:

gem "futuroscope"

And then execute:

$ bundle

Or install it yourself as:

$ gem install futuroscope

Usage

Simple futures

require "futuroscope"

x = Futuroscope::Future.new{ sleep(1); 1 }
y = Futuroscope::Future.new{ sleep(1); 2 }
z = Futuroscope::Future.new{ sleep(1); 3 }

# This execution will actually take just one second and not three like you
# would expect.

puts x + y + z
=> 6

Since a future is actually delegating everything to the future's value, there might be some cases where you want to get the actual future's value. You can do it just by calling the future_value method on the future:

string = "Ed Balls"
x = future{ string }
x.future_value === string
# => true

Future map

require "futuroscope"

map = Futuroscope::Map.new([1, 2, 3]).map do |i|
  sleep(1)
  i + 1
end

puts map.first
=> 2

puts map[1]
=> 3

puts map.last
=> 4

# This action will actually only take 1 second.

Convenience methods

If you don't mind polluting the Kernel module, you can also require futuroscope's convenience future method:

require "futuroscope/convenience"

x = future{ sleep(1); 1 }
y = future{ sleep(1); 2 }
z = future{ sleep(1); 3 }

puts x + y + z
=> 6

Same for a map:

require "futuroscope/convenience"

items = [1, 2, 3].future_map do |i|
  sleep(i)
  i + 1
end

Considerations

You should never add side-effects to a future. They have to be thought of like they were a local variable, with the only outcome that they're returning a value.

You have to take into account that they really run in a different thread, so you'll be potentially accessing code in parallel that could not be thread-safe.

If you're looking for other ways to improve your code performance via concurrency, you should probably deal directly with Ruby's threads.

Worker Pool

Futures are scheduled in a worker pool that helps managing concurrency in a way that doesn't get out of hands. Also comes with great benefits since their threads are spawned at load time (and not in runtime).

The default thread pool comes with a concurrency of 8 Workers, which seems reasonable for the most use cases. It will elastically expand to the default of 16 threads and will kill them when they're not needed.

The default thread pool can be configured like this:

Futuroscope.default_pool.min_workers = 2
Futuroscope.default_pool.max_workers = 16

Also, each future can be scheduled to a different pool like this:

pool = Futuroscope::Pools::WorkerPool.new(16..32)

future = Future.new(pool){ :edballs }

# Or with the convenience method
future = future(pool){ :edballs }

Disabling concurrency

Sometimes you may want to run futures in the main thread, instead of worker threads, e.g. for simpler testing. Therefore you can use the Futuroscope::Pools::NoPool, that runs futures directly instead of queueing them.

# Globally
Futuroscope.default_pool = Futuroscope::Pools::NoPool.new

Futuroscope::Future.new { puts "No concurrency here" }

# Locally
pool = Futuroscope::Pools::NoPool.new

Futuroscope::Future.new(pool) do
  puts "No concurrency here"
end

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am "Add some feature")
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Bitdeli Badge

More Repositories

1

spinach

Spinach is a BDD framework on top of Gherkin.
Ruby
580
star
2

date_validator

A simple, ORM agnostic, Ruby >=2.2 compatible date validator for Rails, based on ActiveModel.
Ruby
493
star
3

pelusa

Static analysis Lint-type tool to improve your OO Ruby code
Ruby
438
star
4

rack-webconsole

Rack-based interactive console (à la Rails console) for your web application's front-end
Ruby
251
star
5

vim-codereview

GItHub Pull Request-based Code Reviews
Ruby
239
star
6

hyperclient

HyperClient is a Ruby Hypermedia API client.
Ruby
153
star
7

resort

Positionless model sorting for Rails
Ruby
103
star
8

spinach-rails

Spinach-rails is a compatibility layer on top of Spinach to provide rails support.
Ruby
62
star
9

vimfiles

Codegram vimfiles
Vim Script
44
star
10

ember-forms

Easy forms for ember.js
JavaScript
36
star
11

gherkin-ruby

gherkin-ruby is a Gherkin parser in pure Ruby using Parslet.
Ruby
33
star
12

markdownizer

Render any text as markdown, with code highlighting and all!
Ruby
30
star
13

colorblind

Extend your ActiveSupport logger with trendy colorschemes from the 90's!
Ruby
27
star
14

live-rust

Rust
27
star
15

haml-jekyll-extension

Jekyll extension to easly use HAML instead of plain HTML
Ruby
21
star
16

jamstack-cfp

Run your call for papers using JAMStack + GitHub Actions
Vue
20
star
17

simple_currency

A really simple currency converter using XavierMedia API. Compatible with Ruby 1.8, 1.9, JRuby 1.5.3 and Rubinius 1.1
Ruby
17
star
18

colorant

A small utility to get the colors of an image.
Ruby
15
star
19

bankr

A bank accoount data gathering gem
Ruby
14
star
20

sass-images

Sass extensions to deal with images
Ruby
14
star
21

cheezburger

BDD for lolcats!
Ruby
13
star
22

guard-spinach

Guard-spinach is a guard plugin for spinach
Ruby
13
star
23

calbert

Catalan ALBERT (A Lite BERT for self-supervised learning of language representations)
Python
13
star
24

dialog-example

Repository with Angular project to show how we use Dialogs and Templates at Empresaula
TypeScript
12
star
25

rpg

RPG game to learn Ruby.
Ruby
9
star
26

dotfiles

Dotfiles used by Codegram team!
Emacs Lisp
8
star
27

spinach-rails-demo

Ruby
8
star
28

vim-todo

Easy peasy TODO list manager for VIM!
Vim Script
8
star
29

acts_as_decimal

Rails 3 plugin to store decimal numbers in the database as integers.
Ruby
7
star
30

pinky

[EXPERIMENTAL] Composable promises for Elixir.
Elixir
7
star
31

useful-github-workflows

Useful GitHub Workflows we use at Codegram
6
star
32

trace

Trace Ruby method calls inside a block of code
Ruby
6
star
33

urania.ex

Efficient and elegant data access for Elixir
Elixir
6
star
34

robinhood

Robin hood leverages celluloid actors to distribute long-lived processes across multiple servers using redis as a locking mechanism.
Ruby
6
star
35

timetable

Timetable is a tool to organize structured content (sections of a workshop, or due tasks), schedule it along time and let you know about current and next sections/tasks.
Ruby
6
star
36

tasca-spinach-demo

Simple todo application as a Spinach demo
Ruby
5
star
37

hypermodel

Rails Responder to generate an automagic JSON HAL representation for your models
Ruby
5
star
38

lastfm

A rather minimal Last.fm client for Ruby.
Ruby
5
star
39

talks

Monday Talks at Codegram
JavaScript
5
star
40

spex

Validate your Elixir values against value-based schemas
Elixir
5
star
41

status-notify-slack

A simple docker image to check if an application status is 200 OK
Shell
3
star
42

hey-mate

A Slack bot to recognize and reward your team's work 🧉
Elixir
3
star
43

vim-haml2slim

A small VIm plugin that helps you convert your Haml views to Slim
Vim Script
3
star
44

phoenix_starter

Elixir
3
star
45

heroku-nginx-proxy

Herouk application that runs a proxy
HTML
3
star
46

dm-machinist

dm-machinist is a datamapper adapter for machinist 2.0
Ruby
3
star
47

course_scraper

A course scraper that gets all the vocational training courses in Catalonia and Spain.
Ruby
2
star
48

full_stack_bot

Full Stack Fest's amazing bot.
Elixir
2
star
49

spinach-sinatra-demo

Spinach working with sinatra
Ruby
2
star
50

deepspain

Deep Spain is a language model fine-tuned on the Spanish state's official bulletin documents
Python
2
star
51

webservice-clj

Example webservice in Clojure for a talk.
Clojure
2
star
52

decidim-barcelona-graphql-api

Simple GraphQL API for decidim.barcelona using Absinthe
Elixir
2
star
53

decidim-deploy-heroku

Opinionated Rails generator for `decidim` apps.
Ruby
2
star
54

decidim-monitor

A tool to monitor instances of decidim.
Elixir
2
star
55

serve-template

Ruby
2
star
56

spinach_helpers

Support helpers to include in Spinach
2
star
57

faye-websockets-heroku-test

Websockets test (a realtime auction app).
JavaScript
2
star
58

codegram.github.io

Codegram Blog
Clojure
2
star
59

gram

Gram is an internal administration tool for Codegram
Ruby
1
star
60

decidim-staging

Demo application to try Codegram's unreleased features of Decidim
HTML
1
star
61

rubocop-decidim

Rubocop custom cops for decidim/decidim
Ruby
1
star
62

spinach-presentation

Showoff presentation for Spinach
1
star
63

button_form

button_form replaces all <input type="submit"/> tags with <button/> in your forms
Ruby
1
star
64

sonic-client

Sonic Client for Elixir
Elixir
1
star
65

serverless-ruby-circleci

A CircleCI orb to build and deploy serverless ruby apps
1
star
66

wasm-tree

HTML
1
star
67

codeborg

A Hubot for Codegram
CoffeeScript
1
star
68

docker-images

A collection of useful docker images for development
Shell
1
star
69

elixir_starter

Elixir
1
star
70

full-stack-fest-sponsor-handbook

Full Stack Fest's sponsor handbook
CSS
1
star
71

rails-templates

Ruby
1
star
72

vim-numberlock

Map your numbers to their corresponding Shift+Number symbol for faster typing.
Vim Script
1
star
73

nuxt-starter

JavaScript
1
star
74

autility

Download utility invoices from some of the popular utility vendors in Spain (Endesa, Vodafone).
Ruby
1
star
75

decidim-electionguard

Python
1
star
76

globalize2_home_page_redirect-radiant-extension

self explanatory
Ruby
1
star
77

hackershout

Shout your hackerness to the world!
Ruby
1
star
78

sass-compass-exercises

Exercises for the sass-compass workshop
Ruby
1
star
79

awesome-mixins

Awesome compass mixins
1
star
80

confs-client

Client for Codegram Conferences
Ruby
1
star