perfectqueue 0.8.43 → 0.8.44

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ac7d746168b57f93e874c437b9daeeb304091f9
4
- data.tar.gz: 2a2685af20791bad69f41301edc418c9bd1b0ee8
3
+ metadata.gz: a6f5457263e6492b228864dbc72be480b28ea20f
4
+ data.tar.gz: d83d97c23703a464f88db7343615dd856cd925ca
5
5
  SHA512:
6
- metadata.gz: c680e72695794d25e0ccc5ef89c10e9ebe6b75ed576e639e23d9145dc1ad9d43baf8f4005c51c2b478bb03efb9db1fbdaf22332bf22238440a68be32d5ac59fd
7
- data.tar.gz: fe80f8cbae924c1c832bb158c32a9ec66708793f17077075e5ba17f6466293a96c467a27748df2ad537e3b08fd2cc41b797738e453a42480030dc0ce51b99310
6
+ metadata.gz: d9cdd377afec8f82f13162b92073864e8d2deac00cf705a51409f3fe1343ab5a5d6716d2ed4a11daa50cd76c15bb4a9fbdbdba565003fe7673ead6fc979d2043
7
+ data.tar.gz: fbf7ef421de36a66fa9a1712f3fa0dcb59d9b7d648a77dd052bbb6f8c0006549165c0a8f04be4e3894dbb78c15badba37eb381a8bcf5822e9ae3bfabd948b164
data/.travis.yml CHANGED
@@ -6,3 +6,11 @@ rvm:
6
6
  - ruby-head
7
7
 
8
8
  script: "bundle exec rake spec"
9
+
10
+ before_script:
11
+ - mysql -e 'create database perfectqueue_test;'
12
+
13
+ sudo: false
14
+
15
+ notifications:
16
+ webhooks: http://td-beda.herokuapp.com/travisci_callback
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ == 2015-10-07 version 0.8.44
2
+
3
+ * rdb_compat: Fix fair scheduling.
4
+ * rdb_compat: Use `GET_LOCK` instead of `LOCK TABLES` in MySQL.
5
+
1
6
  == 2015-06-30 version 0.8.43
2
7
 
3
8
  * child_process: stop after running
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem 'coveralls', require: false
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # PerfectQueue
2
2
 
3
3
  [![Build Status](https://travis-ci.org/treasure-data/perfectqueue.svg?branch=master)](https://travis-ci.org/treasure-data/perfectqueue)
4
+ [![Coverage Status](https://coveralls.io/repos/treasure-data/perfectqueue/badge.svg?branch=master&service=github)](https://coveralls.io/github/treasure-data/perfectqueue?branch=master)
4
5
 
5
6
  PerfectQueue is a highly available distributed queue built on top of RDBMS.
6
7
  PerfectQueue provides similar API to Amazon SQS, while PerfectQueue focues on reliability and flexible scheduling rather than scalability.
@@ -246,3 +247,13 @@ options for run:
246
247
 
247
248
  $ perfectqueue run -I. -Ilib -rconfig/boot.rb -rapps/workers/task_dispatch.rb TaskDispatch
248
249
 
250
+ ## Test
251
+
252
+ Running spec utilize 'mysql2://root:@localhost/perfectqueue_test' as the connection string.
253
+ Please install MySQL server at localhost then run;
254
+
255
+ $ mysql -h localhost -u root -e 'create database perfectqueue_test;'
256
+
257
+ You can run spec.
258
+
259
+ $ bundle exec rake spec
data/circle.yml ADDED
@@ -0,0 +1,7 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.2.2
4
+
5
+ database:
6
+ pre:
7
+ - mysql -e 'create database perfectqueue_test;'
@@ -81,7 +81,7 @@ LIMIT ?
81
81
  SQL
82
82
  else
83
83
  @sql = <<SQL
84
- SELECT id, timeout, data, created_at, resource, max_running, max_running/running AS weight
84
+ SELECT id, timeout, data, created_at, resource, max_running, IFNULL(max_running, 1) / (IFNULL(running, 0) + 1) AS weight
85
85
  FROM `#{@table}`
86
86
  LEFT JOIN (
87
87
  SELECT resource AS res, COUNT(1) AS running
@@ -90,7 +90,7 @@ LEFT JOIN (
90
90
  GROUP BY resource
91
91
  ) AS R ON resource = res
92
92
  WHERE timeout <= ? AND created_at IS NOT NULL AND (max_running-running IS NULL OR max_running-running > 0)
93
- ORDER BY weight IS NOT NULL, weight DESC, timeout ASC
93
+ ORDER BY weight DESC, timeout ASC
94
94
  LIMIT ?
95
95
  SQL
96
96
  end
@@ -101,14 +101,22 @@ SQL
101
101
  @table_lock = nil
102
102
  @table_unlock = nil
103
103
  when /mysql/i
104
- if config[:disable_resource_limit]
105
- @table_lock = "LOCK TABLES `#{@table}` WRITE"
106
- else
107
- @table_lock = "LOCK TABLES `#{@table}` WRITE, `#{@table}` AS T WRITE"
108
- end
109
- @table_unlock = "UNLOCK TABLES"
104
+ @table_lock = lambda {
105
+ locked = nil
106
+ loop do
107
+ @db.fetch("SELECT GET_LOCK('#{@table}', #{LOCK_WAIT_TIMEOUT}) locked") do |row|
108
+ locked = true if row[:locked] == 1
109
+ end
110
+ break if locked
111
+ end
112
+ }
113
+ @table_unlock = lambda {
114
+ @db.run("SELECT RELEASE_LOCK('#{@table}')")
115
+ }
110
116
  else
111
- @table_lock = "LOCK TABLE `#{@table}`"
117
+ @table_lock = lambda {
118
+ @db.run("LOCK TABLE `#{@table}`")
119
+ }
112
120
  @table_unlock = nil
113
121
  end
114
122
 
@@ -122,21 +130,26 @@ SQL
122
130
 
123
131
  KEEPALIVE = 10
124
132
  MAX_RETRY = 10
133
+ LOCK_WAIT_TIMEOUT = 60
125
134
  DEFAULT_DELETE_INTERVAL = 20
126
135
 
127
136
  def init_database(options)
128
- sql = %[
129
- CREATE TABLE IF NOT EXISTS `#{@table}` (
130
- id VARCHAR(256) NOT NULL,
131
- timeout INT NOT NULL,
132
- data BLOB NOT NULL,
133
- created_at INT,
134
- resource VARCHAR(256),
135
- max_running INT,
136
- PRIMARY KEY (id)
137
- );]
137
+ sql = []
138
+ sql << "DROP TABLE IF EXISTS `#{@table}`" if options[:force]
139
+ sql << <<-SQL
140
+ CREATE TABLE IF NOT EXISTS `#{@table}` (
141
+ id VARCHAR(255) NOT NULL,
142
+ timeout INT NOT NULL,
143
+ data LONGBLOB NOT NULL,
144
+ created_at INT,
145
+ resource VARCHAR(255),
146
+ max_running INT,
147
+ PRIMARY KEY (id)
148
+ )
149
+ SQL
150
+ sql << "CREATE INDEX `index_#{@table}_on_timeout` ON `#{@table}` (`timeout`)"
138
151
  connect {
139
- @db.run sql
152
+ sql.each(&@db.method(:run))
140
153
  }
141
154
  end
142
155
 
@@ -164,8 +177,7 @@ SQL
164
177
  now = (options[:now] || Time.now).to_i
165
178
 
166
179
  connect {
167
- #@db.fetch("SELECT id, timeout, data, created_at, resource FROM `#{@table}` WHERE !(created_at IS NULL AND timeout <= ?) ORDER BY timeout ASC;", now) {|row|
168
- @db.fetch("SELECT id, timeout, data, created_at, resource, max_running FROM `#{@table}` ORDER BY timeout ASC", now) {|row|
180
+ @db.fetch("SELECT id, timeout, data, created_at, resource, max_running FROM `#{@table}` ORDER BY timeout ASC") {|row|
169
181
  attributes = create_attributes(now, row)
170
182
  task = TaskWithMetadata.new(@client, row[:id], attributes)
171
183
  yield task
@@ -203,7 +215,7 @@ SQL
203
215
 
204
216
  connect {
205
217
  begin
206
- n = @db[
218
+ @db[
207
219
  "INSERT INTO `#{@table}` (id, timeout, data, created_at, resource, max_running) VALUES (?, ?, ?, ?, ?, ?)",
208
220
  key, run_at, d, now, user, max_running
209
221
  ].insert
@@ -341,7 +353,7 @@ SQL
341
353
  begin
342
354
  @db.transaction do
343
355
  if @table_lock
344
- @db[@table_lock].update
356
+ @table_lock.call
345
357
  locked = true
346
358
  end
347
359
 
@@ -350,7 +362,7 @@ SQL
350
362
 
351
363
  ensure
352
364
  if @use_connection_pooling && locked
353
- @db[@table_unlock].update
365
+ @table_unlock.call
354
366
  end
355
367
  end
356
368
  }
@@ -437,7 +449,7 @@ SQL
437
449
  type = row[:id].split(/\./, 2)[0]
438
450
  end
439
451
 
440
- attributes = {
452
+ {
441
453
  :status => status,
442
454
  :created_at => created_at,
443
455
  :data => data,
@@ -1,3 +1,3 @@
1
1
  module PerfectQueue
2
- VERSION = "0.8.43"
2
+ VERSION = "0.8.44"
3
3
  end
data/perfectqueue.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency "sequel", "~> 3.48.0"
21
21
  gem.add_development_dependency "rake", "~> 0.9.2"
22
22
  gem.add_development_dependency "rspec", "~> 2.10.0"
23
- gem.add_development_dependency "simplecov", "~> 0.5.4"
23
+ gem.add_development_dependency "simplecov", "~> 0.10.0"
24
24
  gem.add_development_dependency "sqlite3", "~> 1.3.3"
25
+ gem.add_development_dependency "mysql2", "~> 0.3.20"
25
26
  end
@@ -2,12 +2,7 @@ require 'spec_helper'
2
2
  require 'perfectqueue/backend/rdb_compat'
3
3
 
4
4
  describe Backend::RDBCompatBackend do
5
- let :queue do
6
- FileUtils.rm_f 'spec/test.db'
7
- queue = PerfectQueue.open({:type=>'rdb_compat', :url=>'sqlite://spec/test.db', :table=>'test_tasks', :processor_type=>'thread'})
8
- queue.client.init_database
9
- queue
10
- end
5
+ include QueueTest
11
6
 
12
7
  let :client do
13
8
  queue.client
data/spec/spec_helper.rb CHANGED
@@ -11,19 +11,20 @@ if ENV['SIMPLE_COV']
11
11
  end
12
12
  end
13
13
 
14
+ if ENV["CI"]
15
+ require 'coveralls'
16
+ Coveralls.wear!
17
+ end
18
+
14
19
  require 'fileutils'
15
20
 
16
21
  module QueueTest
17
22
  def self.included(mod)
18
23
  mod.module_eval do
19
- let :database_path do
20
- 'spec/test.db'
21
- end
22
-
23
24
  let :queue_config do
24
25
  {
25
26
  :type => 'rdb_compat',
26
- :url => "sqlite://#{database_path}",
27
+ :url => "mysql2://root:@localhost/perfectqueue_test",
27
28
  :table => 'test_tasks',
28
29
  :processor_type => 'thread',
29
30
  :cleanup_interval => 0, # for test
@@ -36,8 +37,7 @@ module QueueTest
36
37
  end
37
38
 
38
39
  before do
39
- FileUtils.rm_f database_path
40
- queue.client.init_database
40
+ queue.client.init_database(:force => true)
41
41
  end
42
42
 
43
43
  after do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perfectqueue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.43
4
+ version: 0.8.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-30 00:00:00.000000000 Z
11
+ date: 2015-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.5.4
61
+ version: 0.10.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.5.4
68
+ version: 0.10.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.3.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: mysql2
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.3.20
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.3.20
83
97
  description: Highly available distributed cron built on RDBMS
84
98
  email: frsyuki@gmail.com
85
99
  executables:
@@ -96,6 +110,7 @@ files:
96
110
  - README.md
97
111
  - Rakefile
98
112
  - bin/perfectqueue
113
+ - circle.yml
99
114
  - lib/perfectqueue.rb
100
115
  - lib/perfectqueue/application.rb
101
116
  - lib/perfectqueue/application/base.rb
@@ -153,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
168
  version: '0'
154
169
  requirements: []
155
170
  rubyforge_project:
156
- rubygems_version: 2.4.5
171
+ rubygems_version: 2.4.5.1
157
172
  signing_key:
158
173
  specification_version: 4
159
174
  summary: Highly available distributed cron built on RDBMS