q 0.0.0 → 0.0.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.
- checksums.yaml +7 -0
 - data/.gitignore +4 -4
 - data/CHANGELOG.md +11 -0
 - data/Gemfile +2 -3
 - data/QUEUE_AUTHORS.md +444 -0
 - data/README.md +179 -24
 - data/Rakefile +13 -0
 - data/lib/q.rb +79 -2
 - data/lib/q/errors.rb +32 -0
 - data/lib/q/helpers.rb +25 -0
 - data/lib/q/methods.rb +30 -0
 - data/lib/q/methods/base.rb +53 -0
 - data/lib/q/methods/delayed_job.rb +76 -0
 - data/lib/q/methods/resque.rb +73 -0
 - data/lib/q/methods/sidekiq.rb +123 -0
 - data/lib/q/methods/threaded_in_memory_queue.rb +66 -0
 - data/lib/q/tasks.rb +14 -0
 - data/lib/q/version.rb +1 -1
 - data/q.gemspec +25 -19
 - data/test/methods/base_test.rb +103 -0
 - data/test/methods/delayed_job_test.rb +35 -0
 - data/test/methods/resque_test.rb +37 -0
 - data/test/methods/sidekiq_test.rb +37 -0
 - data/test/methods/threaded_test.rb +89 -0
 - data/test/methods_test.rb +63 -0
 - data/test/q_test.rb +12 -0
 - data/test/support/delayed_job.rb +66 -0
 - data/test/support/resque.rb +25 -0
 - data/test/support/sidekiq.rb +38 -0
 - data/test/support/threaded_in_memory_queue.rb +5 -0
 - data/test/test_helper.rb +22 -0
 - metadata +174 -120
 - data/.rvmrc +0 -2
 - data/bin/q +0 -7
 - data/spec/.gitignore +0 -0
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,24 +1,179 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
              
     | 
| 
       21 
     | 
    
         
            -
              
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            ## Q
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Forget queue boilerplate: focus on your code.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Install
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            In your `Gemfile` add:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 10 
     | 
    
         
            +
            gem 'q'
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Then run `$ bundle install`
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ## What
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            Q is an interface for your background queues. Are you using Resque, Sidekiq, delayed_job, queue_classic, or some other queue? Awesome sauce, because with `Q` you can write your queuing code once and re-use against different backends.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 20 
     | 
    
         
            +
            Q.setup do |config|
         
     | 
| 
      
 21 
     | 
    
         
            +
              config.queue = :resque
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
            ```
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            Now in your code when you need to enqueue something first you need to add the `Q::Methods` module:
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 28 
     | 
    
         
            +
            class Poro
         
     | 
| 
      
 29 
     | 
    
         
            +
              include Q::Methods
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
      
 31 
     | 
    
         
            +
            ```
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            Now you can define tasks using the `queue` class method like this:
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 36 
     | 
    
         
            +
            class Poro
         
     | 
| 
      
 37 
     | 
    
         
            +
              include Q::Methods
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              queue(:send_issues) do |id, state|
         
     | 
| 
      
 40 
     | 
    
         
            +
                user   = User.find(id)
         
     | 
| 
      
 41 
     | 
    
         
            +
                issues = user.issues.where(state: state).all
         
     | 
| 
      
 42 
     | 
    
         
            +
                UserMailer.send_issues(user: user, issues: issues).deliver
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
      
 45 
     | 
    
         
            +
            ```
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            Here we're building a background task called `send_issues` that will send out an email when executed.
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            Now that the task is defined, you can enqueue a `send_issues` job to be executed later by calling `queue` and then `send_issues` like this:
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 52 
     | 
    
         
            +
            user  = User.last
         
     | 
| 
      
 53 
     | 
    
         
            +
            state = 'open'
         
     | 
| 
      
 54 
     | 
    
         
            +
            Poro.queue.send_issues(user.id, state)
         
     | 
| 
      
 55 
     | 
    
         
            +
            ```
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            The Q interface expects json-able objects, numbers, arrays, hashes, etc. This is important if you want your code to be re-usable across multiple queue backends.
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            ## No Queue? No Problem
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            The `Q` library comes with a threaded queue that does not need a backend (such as Redis) by default, so you can write your code today and figure out what queue you want to use tomorrow.
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            Note: that this threaded queue is very basic and should not be used in production. If you stop your Ruby process while there are jobs in memory you will lose your jobs see [threaded_in_memory_queue](https://github.com/schneems/threaded_in_memory_queue) for more information.
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            ## Starting your Queue
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            Most background queue libraries must be run in a seperate process. The `Q` library makes starting these background tasks easy.
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            Make sure there is a Rake task named `:environment` that loads your app (Rails provides one by default). Then add this line to your `Procfile`:
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            ```
         
     | 
| 
      
 72 
     | 
    
         
            +
            worker: bundle exec rake q:work
         
     | 
| 
      
 73 
     | 
    
         
            +
            ```
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            Now if you are running on Heroku the background task will automatically be run. Locally you can run the task manually by executing:
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 78 
     | 
    
         
            +
            $ bundle exec rake q:work
         
     | 
| 
      
 79 
     | 
    
         
            +
            ```
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            Or through your `Procfile` with foreman:
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 84 
     | 
    
         
            +
            $ foreman start
         
     | 
| 
      
 85 
     | 
    
         
            +
            ```
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            If your queueing library supports any custom environment variables or flags you can add them to your `rake q:work` command and they will be passed to the supporting background queue's task.
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            Note: the default threaded queue does not need to be started as it runs in your web process
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            ## Config
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
            You can configure the behavior of your background queue using `Q.queue_config`. For example if you are using Resque and want to run commands inline you could execute:
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 96 
     | 
    
         
            +
            Q.queue_config.inline = true
         
     | 
| 
      
 97 
     | 
    
         
            +
            ```
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            Now any calls to `enqueue` will bypass resque and be run immediately. Different queues will have different configuration options so you will need to see their docs for configuration options.
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
            You can access this config in the setup command:
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 104 
     | 
    
         
            +
            Q.setup do |config|
         
     | 
| 
      
 105 
     | 
    
         
            +
              config.queue = :resque
         
     | 
| 
      
 106 
     | 
    
         
            +
              config.queue_config.inline = true
         
     | 
| 
      
 107 
     | 
    
         
            +
            end
         
     | 
| 
      
 108 
     | 
    
         
            +
            ```
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            It also accepts a block:
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 113 
     | 
    
         
            +
            Q.queue_config do |config|
         
     | 
| 
      
 114 
     | 
    
         
            +
              config.inline = true
         
     | 
| 
      
 115 
     | 
    
         
            +
            end
         
     | 
| 
      
 116 
     | 
    
         
            +
            ```
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            Don't confuse `queue_config` which will configure your background queue (such as Resque) with `setup` which configures the `Q` library itself.
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            ## Diverging Backends
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            As much as we try to make all front end code similar, you'll still need to setup your queue. To make sqitching back and forth easier, we provide a `Q.env` object that responds to the backend you are using such as `Q.env.resque?`.
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
            That way you could keep multiple queue configurations in your app and it won't raise any errors if you're running a different backend.
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 127 
     | 
    
         
            +
            if Q.env.resque?
         
     | 
| 
      
 128 
     | 
    
         
            +
              # config resque here
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            if Q.env.sidekiq?
         
     | 
| 
      
 132 
     | 
    
         
            +
              # configure sidekiq here
         
     | 
| 
      
 133 
     | 
    
         
            +
            else
         
     | 
| 
      
 134 
     | 
    
         
            +
            ```
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            ## Supported Queue Backends
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            ```
         
     | 
| 
      
 139 
     | 
    
         
            +
            config.queue = :sidekiq
         
     | 
| 
      
 140 
     | 
    
         
            +
            config.queue = :resque
         
     | 
| 
      
 141 
     | 
    
         
            +
            config.queue = :threaded
         
     | 
| 
      
 142 
     | 
    
         
            +
            ```
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            Coming soon:
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            ```
         
     | 
| 
      
 147 
     | 
    
         
            +
            config.queue = :delayed_job
         
     | 
| 
      
 148 
     | 
    
         
            +
            ```
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
            ## Blocks
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            You can set default values in blocks like this:
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 157 
     | 
    
         
            +
            queue(:foo) do |id, state = 'open', username = 'schneems'|
         
     | 
| 
      
 158 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 159 
     | 
    
         
            +
            end
         
     | 
| 
      
 160 
     | 
    
         
            +
            ```
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            You can have an unlimited amount of args using a splat:
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 165 
     | 
    
         
            +
            queue(:foo) do |id, *args|
         
     | 
| 
      
 166 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 167 
     | 
    
         
            +
            end
         
     | 
| 
      
 168 
     | 
    
         
            +
            ```
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
            ## Q Authors
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
            Did you write a background queuing library? Want to add support for the `Q` interface? Check out the [QUEUE_AUTHORS.md](QUEUE_AUTHORS.md) file to get started.
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
            Brought to you by [@schneems](http://twitter.com/schneems)
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
            MIT
         
     | 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -1 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
       1 
2 
     | 
    
         
             
            require 'bundler/gem_tasks'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            task :default => [:test]
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            test_task = Rake::TestTask.new(:test) do |t|
         
     | 
| 
      
 10 
     | 
    
         
            +
              t.libs << 'lib'
         
     | 
| 
      
 11 
     | 
    
         
            +
              t.libs << 'test'
         
     | 
| 
      
 12 
     | 
    
         
            +
              t.pattern = 'test/**/*_test.rb'
         
     | 
| 
      
 13 
     | 
    
         
            +
              t.verbose = false
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/q.rb
    CHANGED
    
    | 
         @@ -1,5 +1,82 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            require 'proc_to_lambda'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module Q
         
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
      
 4 
     | 
    
         
            +
              class Queue
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
       5 
6 
     | 
    
         
             
            end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require 'q/version'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'q/helpers'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'q/errors'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'q/methods/base'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'q/methods'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'q/tasks'
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            module Q
         
     | 
| 
      
 16 
     | 
    
         
            +
              extend Q::Helpers
         
     | 
| 
      
 17 
     | 
    
         
            +
              DEFAULT_QUEUE = ->{ @env = :threaded; Q::Methods::Threaded }
         
     | 
| 
      
 18 
     | 
    
         
            +
              FALSEY_HASH   = Hash.new(false)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def self.queue
         
     | 
| 
      
 21 
     | 
    
         
            +
                @queue_method || DEFAULT_QUEUE.call
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              def self.setup(&block)
         
     | 
| 
      
 25 
     | 
    
         
            +
                yield self
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def self.env
         
     | 
| 
      
 29 
     | 
    
         
            +
                name = queue.to_s.split("::").last
         
     | 
| 
      
 30 
     | 
    
         
            +
                @env ||= Q.underscore(name)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                OpenStruct.new(FALSEY_HASH.merge("#{@env}?" => true))
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def self.reset_queue!
         
     | 
| 
      
 36 
     | 
    
         
            +
                @queue_method = nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                @env          = nil
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def self.module_from_klass_name(name)
         
     | 
| 
      
 41 
     | 
    
         
            +
                unless defined?(Q::Methods.const_get(name))
         
     | 
| 
      
 42 
     | 
    
         
            +
                  require "q/methods/#{name}"
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
                return Q::Methods.const_get(name)
         
     | 
| 
      
 45 
     | 
    
         
            +
              rescue LoadError => e
         
     | 
| 
      
 46 
     | 
    
         
            +
                raise LoadError, "Could not find queue: #{name}, expected to be defined in q/methods/#{name}\n" + e.message
         
     | 
| 
      
 47 
     | 
    
         
            +
              rescue NameError => e
         
     | 
| 
      
 48 
     | 
    
         
            +
                raise NameError, "Could not load queue: #{name}, expected to be defined in q/methods/#{name}\n" + e.message
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              def self.module_from_queue_name(queue_name)
         
     | 
| 
      
 52 
     | 
    
         
            +
                module_from_klass_name(camelize(queue_name))
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              def self.queue_lookup
         
     | 
| 
      
 56 
     | 
    
         
            +
                @queue_lookup ||= Hash.new do |hash, key|
         
     | 
| 
      
 57 
     | 
    
         
            +
                  hash[key] = -> {
         
     | 
| 
      
 58 
     | 
    
         
            +
                    require "q/methods/#{key}"
         
     | 
| 
      
 59 
     | 
    
         
            +
                    const = Q.camelize(key)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    ::Q::Methods.const_get(const)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  }
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
                @queue_lookup
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              def self.queue=(queue)
         
     | 
| 
      
 67 
     | 
    
         
            +
                if queue.is_a?(Module)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @queue_method = queue
         
     | 
| 
      
 69 
     | 
    
         
            +
                else
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @env = queue
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @queue_method = queue_lookup[queue].call
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              def self.queue_config(&block)
         
     | 
| 
      
 76 
     | 
    
         
            +
                @config_class ||= queue::QueueConfig.call
         
     | 
| 
      
 77 
     | 
    
         
            +
                yield @config_class if block_given?
         
     | 
| 
      
 78 
     | 
    
         
            +
                @config_class
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            require 'q/methods/threaded_in_memory_queue'
         
     | 
    
        data/lib/q/errors.rb
    ADDED
    
    | 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Q
         
     | 
| 
      
 2 
     | 
    
         
            +
              class StandardError < ::StandardError; end
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              class MissingClassError < StandardError
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(base, missing_klass)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  msg = "#{base} must define '#{missing_klass}' class with a call method"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  super(msg)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              class InstanceQueueDefinitionError < StandardError
         
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(obj)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  msg = "Cannot define a queue on an instance: #{obj}. Try defining it directly on the class #{obj.class}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  super(msg)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              class DuplicateQueueClassError < StandardError
         
     | 
| 
      
 19 
     | 
    
         
            +
                def initialize(base, duplicate_klass)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  msg = "Cannot create queue class: '#{duplicate_klass}' because #{duplicate_klass} is already defined on #{base}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  super(msg)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              class DuplicateQueueMethodError < StandardError
         
     | 
| 
      
 26 
     | 
    
         
            +
                def initialize(base, method)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  msg = "Cannot create queue method: '#{method}'. Method already exists on #{base}.queue, cannot overwrite"
         
     | 
| 
      
 28 
     | 
    
         
            +
                  msg << "Originally defined at #{base.queue.method(method).source_location}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  super(msg)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/q/helpers.rb
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Q
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                def camelize(term)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  string = term.to_s
         
     | 
| 
      
 5 
     | 
    
         
            +
                  string = string.sub(/^[a-z\d]*/) { $&.capitalize }
         
     | 
| 
      
 6 
     | 
    
         
            +
                  string = string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$2.capitalize}" }.gsub('/', '::')
         
     | 
| 
      
 7 
     | 
    
         
            +
                  string
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def underscore(term)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  string = term.to_s
         
     | 
| 
      
 12 
     | 
    
         
            +
                  string = string.sub(/^[a-z\d]*/) { "#{$&.downcase}_" }
         
     | 
| 
      
 13 
     | 
    
         
            +
                  string = string.gsub(/^_/, '')
         
     | 
| 
      
 14 
     | 
    
         
            +
                  string
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def const_defined_on?(on, const)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  on.constants.include?(const.to_sym)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def proc_to_lambda(block = nil, &proc)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  ::ProcToLambda.to_lambda(block || proc)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/q/methods.rb
    ADDED
    
    | 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Q
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Methods
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Q::Methods::Base
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                class QueueConfig
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.call
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Q.queue::QueueConfig
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                class QueueTask
         
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.call(*rake_args)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    Q.queue::QueueTask.call(rake_args)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                class QueueBuild
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def self.call(options={}, &job)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    Q.queue::QueueBuild.call(options, &job)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                class QueueMethod
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def self.call(options = {})
         
     | 
| 
      
 25 
     | 
    
         
            +
                    Q.queue::QueueMethod.call(options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
            Q::Method = Q::Methods
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Q
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Methods
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def self.included(base)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    base.const_set("Queue", Class.new(::Q::Queue)) unless base.const_get("Queue") != ::Queue
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    included = base.method(:included) if base.respond_to?(:included)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    base.define_singleton_method(:included) do |target|
         
     | 
| 
      
 9 
     | 
    
         
            +
                      included.call(target) unless included.nil?
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      raise Q::MissingClassError.new(base, :QueueMethod) unless Q.const_defined_on?(base, :QueueMethod)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      raise Q::MissingClassError.new(base, :QueueBuild)  unless Q.const_defined_on?(base, :QueueBuild)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      raise Q::MissingClassError.new(base, :QueueTask)   unless Q.const_defined_on?(base, :QueueTask)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      raise Q::MissingClassError.new(base, :QueueConfig) unless Q.const_defined_on?(base, :QueueConfig)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                      target.extend(ClassMethods)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      target.send(:include, InstanceMethods)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                      target.class_variable_set(:@@_q_klass, base)            unless target.class_variable_defined?(:@@_q_klass)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      target.class_variable_set(:@@_q_queue, base::Queue.new) unless target.class_variable_defined?(:@@_q_queue)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  module InstanceMethods
         
     | 
| 
      
 25 
     | 
    
         
            +
                    def queue
         
     | 
| 
      
 26 
     | 
    
         
            +
                      raise Q::InstanceQueueDefinitionError.new(self) if block_given?
         
     | 
| 
      
 27 
     | 
    
         
            +
                      self.class.queue
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  module ClassMethods
         
     | 
| 
      
 32 
     | 
    
         
            +
                    def queue(*args, &block)
         
     | 
| 
      
 33 
     | 
    
         
            +
                      queue = self.class_variable_get(:@@_q_queue)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                      return queue unless block_given?
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      queue_name   = args.shift
         
     | 
| 
      
 38 
     | 
    
         
            +
                      job          = Q.proc_to_lambda(&block)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                      raise "first argument #{queue_name.inspect} must be a symbol to define a queue" unless queue_name.is_a?(Symbol)
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      options = { base:             self,
         
     | 
| 
      
 43 
     | 
    
         
            +
                                  queue_name:       queue_name,
         
     | 
| 
      
 44 
     | 
    
         
            +
                                  queue_klass_name: Q.camelize(queue_name) }
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      queue_klass = self.class_variable_get(:@@_q_klass)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      queue_klass::QueueBuild.call(options, &job)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      queue_klass::QueueMethod.call(options)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     |