queue_to_the_future 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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