queue_to_the_future 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,19 +1,19 @@
1
- = queue_to_the_future
1
+ = Queue to the Future!
2
2
 
3
3
  An easy way to create asynchronous execution paths in an unobtrusive way. Queue to the Future uses a managed pool of workers
4
4
  to keep overhead to a minimum.
5
5
 
6
6
  == Synopsis
7
- f = Future(list, of, args) do |list, of, args|
8
- sleep(1)
9
- "done."
10
- end
7
+ require "queue_to_the_future"
11
8
 
12
9
  # returns immediately
13
- puts f.inspect #=> #<QueueToTheFuture::Job:0x7ffa641c ... >
10
+ result = Future("list", "of", "args") do |*args|
11
+ sleep(1)
12
+ args.join(" ")
13
+ end
14
14
 
15
15
  # blocks until completed
16
- puts f #=> done.
16
+ puts result #=> "list of args"
17
17
 
18
18
  == Copyright
19
19
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -5,24 +5,42 @@ require 'queue_to_the_future/worker'
5
5
  require 'queue_to_the_future/job'
6
6
 
7
7
  module QueueToTheFuture
8
- @@maximum_workers = 15
9
-
8
+ # The maximum number of workers to create for processing jobs.
9
+ #
10
+ # @return [Fixnum] Default is 15
10
11
  def self.maximum_workers
11
- @@maximum_workers
12
+ @@maximum_workers ||= 15
12
13
  end
13
14
 
15
+ # Setter method for {maximum_workers}
16
+ #
17
+ # @param [Fixnum] number Any integer greater than 0
18
+ # @return [Fixnum] number given
19
+ # @raise [StandardError] If the number given is less than 1
14
20
  def self.maximum_workers=(number)
15
21
  raise StandardError.new("Bad workforce size: #{number}. Must be at least 1.") unless (number = number.to_i) >= 1
16
22
  @@maximum_workers = number
17
23
  end
18
-
19
- def self.schedule(job)
20
- Coordinator.instance.schedule(job)
21
- end
22
24
  end
23
25
 
24
26
  module Kernel
27
+ # Main interface for asynchronous job scheduling. (Where the magick begins)
28
+ #
29
+ # @example
30
+ # http = Net::HTTP.new("ia.media-imdb.com")
31
+ # image_path = "/images/M/MV5BMTkzNDQyMjc0OV5BMl5BanBnXkFtZTcwNDQ4MDYyMQ@@._V1._SX100_SY133_.jpg"
32
+ #
33
+ # image = Future(image_path) do |path|
34
+ # http.request(Net::HTTP::Get.new(path)).body
35
+ # end
36
+ #
37
+ # # do other things
38
+ #
39
+ # puts image.size # => 6636
40
+ #
41
+ # @param (see QueueToTheFuture::Job#initialize)
42
+ # @return [QueueToTheFuture::Job] Your proxy into the future
25
43
  def Future(*args, &block)
26
- QueueToTheFuture.schedule(QueueToTheFuture::Job.new(*args, &block))
44
+ QueueToTheFuture::Job.new(*args, &block)
27
45
  end
28
46
  end
@@ -1,31 +1,53 @@
1
1
  require 'singleton'
2
2
 
3
- module QueueToTheFuture
3
+ module QueueToTheFuture
4
+ # The coordinator schedules jobs and maintains the workforce size to match. As jobs
5
+ # get added the coordinator creates workers to complete them. The number of
6
+ # workers created will never exceed {QueueToTheFuture::maximum_workers}.
4
7
  class Coordinator
5
8
  include Singleton
6
9
 
10
+ # Creates the coordinator.
11
+ #
12
+ # Note: This is a singleton class. To access the instance use
13
+ # {http://ruby-doc.org/stdlib/libdoc/singleton/rdoc/index.html Coordinator::instance}.
7
14
  def initialize
8
15
  @job_queue = []
9
16
  @workforce = []
10
17
  @lock = Mutex.new
11
18
  end
12
19
 
20
+ # The next scheduled job.
21
+ #
22
+ # @return [QueueToTheFuture::Job] Next job
13
23
  def next_job
14
24
  synchronize { @job_queue.shift }
15
25
  end
16
26
 
27
+ # The number of jobs waiting to be completed.
28
+ #
29
+ # @return [Fixnum] Size of job queue
17
30
  def job_count
18
31
  synchronize { @job_queue.size }
19
32
  end
20
33
 
34
+ # The number of workers being utilized to complete jobs.
35
+ #
36
+ # @return [Fixnum] Number of workers
21
37
  def workforce_size
22
38
  synchronize { @workforce.size }
23
39
  end
24
40
 
41
+ # Removes a worker from the workforce.
42
+ #
43
+ # @param [QueueToTheFuture::Worker] worker
25
44
  def relieve(worker)
26
45
  synchronize { @workforce -= [worker] }
27
46
  end
28
47
 
48
+ # Append a job to the job queue.
49
+ #
50
+ # @param [QueueToTheFuture::Job] job
29
51
  def schedule(job)
30
52
  synchronize do
31
53
  @job_queue.push(job)
@@ -1,16 +1,30 @@
1
1
  module QueueToTheFuture
2
+ # A proxy object for the future return value of a block.
2
3
  class Job
3
4
  (instance_methods - %w[__send__ __id__ object_id inspect]).each { |meth| undef_method(meth) }
4
5
 
6
+ # Creates a job and schedules it by calling {Coordinator#schedule}.
7
+ #
8
+ # @param [List] *args The list of arguments to pass to the given block
9
+ # @param [Proc] &block The block to be executed
5
10
  def initialize(*args, &block)
6
11
  @args = args
7
12
  @block = block
13
+ Coordinator::instance.schedule(self)
8
14
  end
9
15
 
16
+ # Execute the job.
17
+ #
18
+ # This is called by the worker the job gets assigned to.
19
+ # @return [nil]
10
20
  def __execute__
11
- @result = @block.call(*@args)
21
+ @result = @block.call(*@args); nil
12
22
  end
13
23
 
24
+ # Allows the job to behave as the return value of the block.
25
+ #
26
+ # Accessing any method on the job will cause code to block
27
+ # until the job is completed.
14
28
  def method_missing(*args, &block)
15
29
  Thread.pass while !defined?(@result)
16
30
  @result.send(*args, &block)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queue_to_the_future
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devin Christensen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-12 00:00:00 -07:00
12
+ date: 2010-01-18 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency