que 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd68dcc8f19097468e664cdd7a3777b9d1ce8b431fdb3a42a08ffcb75723f559
4
- data.tar.gz: e0191191fe9b64c436173a3f956b4d06b18c131f3de1bbbd71f5966b363db168
3
+ metadata.gz: 2be51744809f55950825aa7bbb6c3e4d7d4d0927a439dfdf2c1f3658f53cfc84
4
+ data.tar.gz: f1c7b10f27e57fd11288f50789cef31574e11a333733dfbae93e870841dabf28
5
5
  SHA512:
6
- metadata.gz: 37fd03216218cea290a92ecc3961aede25b5e5ed9a11d30dd2fd6ae8bd3b22c6f0a021f947f068836e00c28e1c75d3168330eec2169bf7fa394e3da40dd1a38f
7
- data.tar.gz: 16fe7c2452eff1b240854acba12227dc1f061bf9b7ab756656358886327a8ea6a48eea26e2b97c4376acfcdda5dc89ec10fa24341bfc03da49b043e4be07b748
6
+ metadata.gz: 93688d24737b750e85c1769bebc6d1344264a8b9757c855150c1dd022104a6400e205442db443bf12c8623325a8178b5379ff647faecd47ada873ead78d5ce7e
7
+ data.tar.gz: 7fc7c9e34adb2f779f947c0d8326da32c40ba47c7fe4501e343fc177d3115275a25e28b8b407aa62a3ce7d095760f4f392fb9f501892918fc5d2dc3802871f93
data/CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
+ ### 1.1.0 (2022-02-21)
2
+
3
+ - **Features**:
4
+ + Add backtrace to errors, by [@trammel](https://github.com/trammel) in [#328](https://github.com/que-rb/que/pull/328)
5
+ - **Internal**:
6
+ + Add Dockerised development environment, in [#324](https://github.com/que-rb/que/pull/324)
7
+
1
8
  ### 1.0.0 (2022-01-24)
9
+
2
10
  _This release does not add any changes on top of 1.0.0.beta5._
3
11
 
4
12
  ### 1.0.0.beta5 (2021-12-23)
data/Dockerfile ADDED
@@ -0,0 +1,20 @@
1
+ FROM ruby:2.7.5-slim-buster@sha256:4cbbe2fba099026b243200aa8663f56476950cc64ccd91d7aaccddca31e445b5 AS base
2
+
3
+ # Install libpq-dev in our base layer, as it's needed in all environments
4
+ RUN apt-get update \
5
+ && apt-get install -y libpq-dev \
6
+ && rm -rf /var/lib/apt/lists/*
7
+
8
+ ENV RUBY_BUNDLER_VERSION 2.3.7
9
+ RUN gem install bundler -v $RUBY_BUNDLER_VERSION
10
+
11
+ ENV BUNDLE_PATH /usr/local/bundle
12
+
13
+ ENV RUBYOPT=-W:deprecated
14
+
15
+ FROM base AS dev-environment
16
+
17
+ # Install build-essential and git, as we'd need them for building gems that have native code components
18
+ RUN apt-get update \
19
+ && apt-get install -y build-essential git \
20
+ && rm -rf /var/lib/apt/lists/*
data/README.md CHANGED
@@ -6,49 +6,54 @@
6
6
 
7
7
  Que ("keɪ", or "kay") is a queue for Ruby and PostgreSQL that manages jobs using [advisory locks](http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS), which gives it several advantages over other RDBMS-backed queues:
8
8
 
9
- * **Concurrency** - Workers don't block each other when trying to lock jobs, as often occurs with "SELECT FOR UPDATE"-style locking. This allows for very high throughput with a large number of workers.
10
- * **Efficiency** - Locks are held in memory, so locking a job doesn't incur a disk write. These first two points are what limit performance with other queues. Under heavy load, Que's bottleneck is CPU, not I/O.
11
- * **Safety** - If a Ruby process dies, the jobs it's working won't be lost, or left in a locked or ambiguous state - they immediately become available for any other worker to pick up.
9
+ - **Concurrency** - Workers don't block each other when trying to lock jobs, as often occurs with "SELECT FOR UPDATE"-style locking. This allows for very high throughput with a large number of workers.
10
+ - **Efficiency** - Locks are held in memory, so locking a job doesn't incur a disk write. These first two points are what limit performance with other queues. Under heavy load, Que's bottleneck is CPU, not I/O.
11
+ - **Safety** - If a Ruby process dies, the jobs it's working won't be lost, or left in a locked or ambiguous state - they immediately become available for any other worker to pick up.
12
12
 
13
13
  Additionally, there are the general benefits of storing jobs in Postgres, alongside the rest of your data, rather than in Redis or a dedicated queue:
14
14
 
15
- * **Transactional Control** - Queue a job along with other changes to your database, and it'll commit or rollback with everything else. If you're using ActiveRecord or Sequel, Que can piggyback on their connections, so setup is simple and jobs are protected by the transactions you're already using.
16
- * **Atomic Backups** - Your jobs and data can be backed up together and restored as a snapshot. If your jobs relate to your data (and they usually do), there's no risk of jobs falling through the cracks during a recovery.
17
- * **Fewer Dependencies** - If you're already using Postgres (and you probably should be), a separate queue is another moving part that can break.
18
- * **Security** - Postgres' support for SSL connections keeps your data safe in transport, for added protection when you're running workers on cloud platforms that you can't completely control.
15
+ - **Transactional Control** - Queue a job along with other changes to your database, and it'll commit or rollback with everything else. If you're using ActiveRecord or Sequel, Que can piggyback on their connections, so setup is simple and jobs are protected by the transactions you're already using.
16
+ - **Atomic Backups** - Your jobs and data can be backed up together and restored as a snapshot. If your jobs relate to your data (and they usually do), there's no risk of jobs falling through the cracks during a recovery.
17
+ - **Fewer Dependencies** - If you're already using Postgres (and you probably should be), a separate queue is another moving part that can break.
18
+ - **Security** - Postgres' support for SSL connections keeps your data safe in transport, for added protection when you're running workers on cloud platforms that you can't completely control.
19
19
 
20
20
  Que's primary goal is reliability. You should be able to leave your application running indefinitely without worrying about jobs being lost due to a lack of transactional support, or left in limbo due to a crashing process. Que does everything it can to ensure that jobs you queue are performed exactly once (though the occasional repetition of a job can be impossible to avoid - see the docs on [how to write a reliable job](/docs/README.md#writing-reliable-jobs)).
21
21
 
22
22
  Que's secondary goal is performance. The worker process is multithreaded, so that a single process can run many jobs simultaneously.
23
23
 
24
24
  Compatibility:
25
+
25
26
  - MRI Ruby 2.2+
26
27
  - PostgreSQL 9.5+
27
28
  - Rails 4.1+ (optional)
28
29
 
29
30
  **Please note** - Que's job table undergoes a lot of churn when it is under high load, and like any heavily-written table, is susceptible to bloat and slowness if Postgres isn't able to clean it up. The most common cause of this is long-running transactions, so it's recommended to try to keep all transactions against the database housing Que's job table as short as possible. This is good advice to remember for any high-activity database, but bears emphasizing when using tables that undergo a lot of writes.
30
31
 
31
-
32
32
  ## Installation
33
33
 
34
34
  Add this line to your application's Gemfile:
35
35
 
36
- gem 'que'
36
+ ```ruby
37
+ gem 'que'
38
+ ```
37
39
 
38
40
  And then execute:
39
41
 
40
- $ bundle
42
+ ```bash
43
+ bundle
44
+ ```
41
45
 
42
46
  Or install it yourself as:
43
47
 
44
- $ gem install que
45
-
48
+ ```bash
49
+ gem install que
50
+ ```
46
51
 
47
52
  ## Usage
48
53
 
49
54
  First, create the queue schema in a migration. For example:
50
55
 
51
- ``` ruby
56
+ ```ruby
52
57
  class CreateQueSchema < ActiveRecord::Migration[5.0]
53
58
  def up
54
59
  # Whenever you use Que in a migration, always specify the version you're
@@ -66,7 +71,7 @@ end
66
71
 
67
72
  Create a class for each type of job you want to run:
68
73
 
69
- ``` ruby
74
+ ```ruby
70
75
  # app/jobs/charge_credit_card.rb
71
76
  class ChargeCreditCard < Que::Job
72
77
  # Default settings for this job. These are optional - without them, jobs
@@ -101,7 +106,7 @@ end
101
106
 
102
107
  Queue your job. Again, it's best to do this in a transaction with other changes you're making. Also note that any arguments you pass will be serialized to JSON and back again, so stick to simple types (strings, integers, floats, hashes, and arrays).
103
108
 
104
- ``` ruby
109
+ ```ruby
105
110
  CreditCard.transaction do
106
111
  # Persist credit card information
107
112
  card = CreditCard.create(params[:credit_card])
@@ -111,17 +116,18 @@ end
111
116
 
112
117
  You can also add options to run the job after a specific time, or with a specific priority:
113
118
 
114
- ``` ruby
119
+ ```ruby
115
120
  ChargeCreditCard.enqueue card.id, user_id: current_user.id, run_at: 1.day.from_now, priority: 5
116
121
  ```
117
122
  ## Running the Que Worker
118
123
  In order to process jobs, you must start a separate worker process outside of your main server.
119
124
 
120
- ```
125
+ ```bash
121
126
  bundle exec que
122
127
  ```
123
128
 
124
129
  Try running `que -h` to get a list of runtime options:
130
+
125
131
  ```
126
132
  $ que -h
127
133
  usage: que [options] [file/to/require] ...
@@ -138,21 +144,24 @@ If you're using ActiveRecord to dump your database's schema, please [set your sc
138
144
 
139
145
  Pre-1.0, the default queue name needed to be configured in order for Que to work out of the box with Rails. In 1.0 the default queue name is now 'default', as Rails expects, but when Rails enqueues some types of jobs it may try to use another queue name that isn't worked by default. You can either:
140
146
 
141
- * [Configure Rails](https://guides.rubyonrails.org/configuring.html) to send all internal job types to the 'default' queue by adding the following to `config/application.rb`:
142
- ```ruby
143
- config.action_mailer.deliver_later_queue_name = :default
144
- config.action_mailbox.queues.incineration = :default
145
- config.action_mailbox.queues.routing = :default
146
- config.active_storage.queues.analysis = :default
147
- config.active_storage.queues.purge = :default
148
- ```
147
+ - [Configure Rails](https://guides.rubyonrails.org/configuring.html) to send all internal job types to the 'default' queue by adding the following to `config/application.rb`:
149
148
 
150
- * [Tell que](/docs#multiple-queues) to work all of these queues (less efficient because it requires polling all of them):
151
- ```
152
- que -q default -q mailers -q action_mailbox_incineration -q action_mailbox_routing -q active_storage_analysis -q active_storage_purge
153
- ```
149
+ ```ruby
150
+ config.action_mailer.deliver_later_queue_name = :default
151
+ config.action_mailbox.queues.incineration = :default
152
+ config.action_mailbox.queues.routing = :default
153
+ config.active_storage.queues.analysis = :default
154
+ config.active_storage.queues.purge = :default
155
+ ```
156
+
157
+ - [Tell que](/docs#multiple-queues) to work all of these queues (less efficient because it requires polling all of them):
158
+
159
+ ```bash
160
+ que -q default -q mailers -q action_mailbox_incineration -q action_mailbox_routing -q active_storage_analysis -q active_storage_purge
161
+ ```
154
162
 
155
163
  Also, if you would like to integrate Que with Active Job, you can do it by setting the adapter in `config/application.rb` or in a specific environment by setting it in `config/environments/production.rb`, for example:
164
+
156
165
  ```ruby
157
166
  config.active_job.queue_adapter = :que
158
167
  ```
@@ -183,9 +192,9 @@ If you have a project that uses or relates to Que, feel free to submit a PR addi
183
192
 
184
193
  ## Community and Contributing
185
194
 
186
- * For bugs in the library, please feel free to [open an issue](https://github.com/que-rb/que/issues/new).
187
- * For general discussion and questions/concerns that don't relate to obvious bugs, join our [Discord Server](https://discord.gg/B3EW32H).
188
- * For contributions, pull requests submitted via Github are welcome.
195
+ - For bugs in the library, please feel free to [open an issue](https://github.com/que-rb/que/issues/new).
196
+ - For general discussion and questions/concerns that don't relate to obvious bugs, join our [Discord Server](https://discord.gg/B3EW32H).
197
+ - For contributions, pull requests submitted via Github are welcome.
189
198
 
190
199
  Regarding contributions, one of the project's priorities is to keep Que as simple, lightweight and dependency-free as possible, and pull requests that change too much or wouldn't be useful to the majority of Que's users have a good chance of being rejected. If you're thinking of submitting a pull request that adds a new feature, consider starting a discussion in [que-talk](https://groups.google.com/forum/#!forum/que-talk) first about what it would do and how it would be implemented. If it's a sufficiently large feature, or if most of Que's users wouldn't find it useful, it may be best implemented as a standalone gem, like some of the related projects above.
191
200
 
@@ -193,12 +202,54 @@ Regarding contributions, one of the project's priorities is to keep Que as simpl
193
202
 
194
203
  A note on running specs - Que's worker system is multithreaded and therefore prone to race conditions. As such, if you've touched that code, a single spec run passing isn't a guarantee that any changes you've made haven't introduced bugs. One thing I like to do before pushing changes is rerun the specs many times and watching for hangs. You can do this from the command line with something like:
195
204
 
196
- for i in {1..1000}; do SEED=$i bundle exec rake; done
205
+ ```bash
206
+ for i in {1..1000}; do SEED=$i bundle exec rake; done
207
+ ```
197
208
 
198
209
  This will iterate the specs one thousand times, each with a different ordering. If the specs hang, note what the seed number was on that iteration. For example, if the previous specs finished with a "Randomized with seed 328", you know that there's a hang with seed 329, and you can narrow it down to a specific spec with:
199
210
 
200
- for i in {1..1000}; do LOG_SPEC=true SEED=328 bundle exec rake; done
211
+ ```bash
212
+ for i in {1..1000}; do LOG_SPEC=true SEED=328 bundle exec rake; done
213
+ ```
201
214
 
202
215
  Note that we iterate because there's no guarantee that the hang would reappear with a single additional run, so we need to rerun the specs until it reappears. The LOG_SPEC parameter will output the name and file location of each spec before it is run, so you can easily tell which spec is hanging, and you can continue narrowing things down from there.
203
216
 
204
217
  Another helpful technique is to replace an `it` spec declaration with `hit` - this will run that particular spec 100 times during the run.
218
+
219
+ #### With Docker
220
+
221
+ We've provided a Dockerised environment to avoid the need to manually: install Ruby, install the gem bundle, set up Postgres, and connect to the database.
222
+
223
+ To run the specs using this environment, run:
224
+
225
+ ```bash
226
+ ./auto/test
227
+ ```
228
+
229
+ To get a shell in the environment, run:
230
+
231
+ ```bash
232
+ ./auto/dev
233
+ ```
234
+
235
+ The [Docker Compose config](docker-compose.yml) provides a convenient way to inject your local shell aliases into the Docker container. Simply create a file containing your alias definitions (or which sources them from other files) at `~/.docker-rc.d/.docker-bashrc`, and they will be available inside the container.
236
+
237
+ #### Without Docker
238
+
239
+ You'll need to have Postgres running. Assuming you have it running on port 5697, with a `que-test` database, and a username & password of `que`, you can run:
240
+
241
+ ```bash
242
+ DATABASE_URL=postgres://que:que@localhost:5697/que-test bundle exec rake
243
+ ```
244
+
245
+ If you don't already have Postgres, you could use Docker Compose to run just the database:
246
+
247
+ ```bash
248
+ docker compose up -d db
249
+ ```
250
+
251
+ If you want to try a different version of Postgres, e.g. 12:
252
+
253
+ ```bash
254
+ export POSTGRES_VERSION=12
255
+ ```
data/auto/dev ADDED
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+ #
3
+ # Operate in development environment
4
+
5
+ set -Eeuo pipefail
6
+
7
+ cd "$(dirname "$0")/.."
8
+
9
+ docker compose build dev
10
+
11
+ # Delete containers and DB volume afterwards on CI
12
+ if [[ "${CI-}" == "true" ]]; then
13
+ trap '{
14
+ echo "Stopping containers..."
15
+ docker compose down
16
+ docker volume rm -f que_db-data
17
+ }' EXIT
18
+ fi
19
+
20
+ set -x
21
+ docker compose run --rm dev "${@-bash}"
data/auto/psql ADDED
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+ #
3
+ # Open a database shell
4
+
5
+ set -Eeuo pipefail
6
+
7
+ cd "$(dirname "$0")/.."
8
+
9
+ docker compose run --rm pg-dev psql "${@-}"
data/auto/test ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ set -Eeuo pipefail
4
+
5
+ "$(dirname "$0")"/dev ./scripts/test "$@"
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ set -Eeuo pipefail
4
+
5
+ export POSTGRES_VERSION=14
6
+
7
+ delete_db() {
8
+ docker compose down
9
+ docker volume rm -f que_db-data
10
+ }
11
+
12
+ trap delete_db EXIT
13
+
14
+ # pre-test cleanup is necessary as the existing db container will be used if it's running (potentially with the wrong PG version)
15
+ delete_db
16
+ "$(dirname "$0")"/test "$@"
17
+ delete_db
@@ -0,0 +1,46 @@
1
+ version: "3.7"
2
+
3
+ services:
4
+
5
+ dev:
6
+ build:
7
+ context: .
8
+ target: dev-environment
9
+ depends_on:
10
+ - db
11
+ volumes:
12
+ - .:/work
13
+ - ruby-2.7.5-gem-cache:/usr/local/bundle
14
+ - ~/.docker-rc.d/:/.docker-rc.d/:ro
15
+ working_dir: /work
16
+ entrypoint: /work/scripts/docker-entrypoint
17
+ command: bash
18
+ environment:
19
+ DATABASE_URL: postgres://que:que@db/que-test
20
+
21
+ db:
22
+ image: "postgres:${POSTGRES_VERSION-13}"
23
+ volumes:
24
+ - db-data:/var/lib/postgresql/data
25
+ environment:
26
+ POSTGRES_USER: que
27
+ POSTGRES_PASSWORD: que
28
+ POSTGRES_DB: que-test
29
+ ports:
30
+ - 5697:5432
31
+
32
+ pg-dev:
33
+ image: "postgres:${POSTGRES_VERSION-13}"
34
+ depends_on:
35
+ - db
36
+ entrypoint: []
37
+ command: psql
38
+ environment:
39
+ PGHOST: db
40
+ PGUSER: que
41
+ PGPASSWORD: que
42
+ PGDATABASE: que-test
43
+
44
+ volumes:
45
+ db-data: ~
46
+ ruby-2.7.5-gem-cache: ~
data/lib/que/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Que
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
data/lib/que/worker.rb CHANGED
@@ -137,6 +137,7 @@ module Que
137
137
  error: {
138
138
  class: error.class.to_s,
139
139
  message: error.message,
140
+ backtrace: (error.backtrace || []).join("\n").slice(0, 10000),
140
141
  },
141
142
  )
142
143
 
@@ -164,7 +165,7 @@ module Que
164
165
  Que.execute :set_error, [
165
166
  delay,
166
167
  "#{error.class}: #{error.message}".slice(0, 500),
167
- error.backtrace.join("\n").slice(0, 10000),
168
+ (error.backtrace || []).join("\n").slice(0, 10000),
168
169
  job.fetch(:id),
169
170
  ]
170
171
  end
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ set -Eeuo pipefail
4
+
5
+ # For using your own dotfiles within the Docker container
6
+ if [ -f /.docker-rc.d/.docker-bashrc ]; then
7
+ echo "source /.docker-rc.d/.docker-bashrc" >> ~/.bashrc
8
+ fi
9
+
10
+ gem list -i -e bundler -v "$RUBY_BUNDLER_VERSION" >/dev/null || gem install bundler -v "$RUBY_BUNDLER_VERSION"
11
+
12
+ bundle check --dry-run || bundle install
13
+
14
+ exec "${@-bash}"
data/scripts/test ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ set -Eeuo pipefail
4
+
5
+ bundle exec rake spec "$@"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: que
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Hanks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-24 00:00:00.000000000 Z
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -35,11 +35,17 @@ files:
35
35
  - ".github/workflows/tests.yml"
36
36
  - ".gitignore"
37
37
  - CHANGELOG.md
38
+ - Dockerfile
38
39
  - LICENSE.txt
39
40
  - README.md
40
41
  - Rakefile
42
+ - auto/dev
43
+ - auto/psql
44
+ - auto/test
45
+ - auto/test-postgres-14
41
46
  - bin/command_line_interface.rb
42
47
  - bin/que
48
+ - docker-compose.yml
43
49
  - docs/README.md
44
50
  - lib/que.rb
45
51
  - lib/que/active_job/extensions.rb
@@ -79,6 +85,8 @@ files:
79
85
  - lib/que/version.rb
80
86
  - lib/que/worker.rb
81
87
  - que.gemspec
88
+ - scripts/docker-entrypoint
89
+ - scripts/test
82
90
  homepage: https://github.com/que-rb/que
83
91
  licenses:
84
92
  - MIT
@@ -98,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
106
  - !ruby/object:Gem::Version
99
107
  version: '0'
100
108
  requirements: []
101
- rubygems_version: 3.1.4
109
+ rubygems_version: 3.3.6
102
110
  signing_key:
103
111
  specification_version: 4
104
112
  summary: A PostgreSQL-based Job Queue