perfectqueue 0.9.1 → 0.9.2
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 +4 -4
- data/ChangeLog +4 -0
- data/lib/perfectqueue/backend/rdb_compat.rb +98 -72
- data/lib/perfectqueue/version.rb +1 -1
- data/spec/rdb_compat_backend_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7274d143afaecb7d6ee09cac6d4e287813dcf1bc
|
4
|
+
data.tar.gz: 25c4271e2bbcb2734c92234a73c59121e383834c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc0acb6de0b1771606a5a8047f48d6c6e904722af0416291951cb87cfca8a65bd16b501099a1540e0f55ab7f9a41c650321b6cc87add520ead66b69acf61def2
|
7
|
+
data.tar.gz: 1b85520494ad5059f0dc5dc187eeab5810a51bd707e6931b21e1663c0425b0fcf05921ebb424f7aa1102e744a3f1e317cda7d0fe55d3fd36e947f895ba0420e3
|
data/ChangeLog
CHANGED
@@ -78,55 +78,7 @@ module PerfectQueue
|
|
78
78
|
# connection test
|
79
79
|
}
|
80
80
|
|
81
|
-
|
82
|
-
# server's internal thread ID counter. It is unique while the MySQL
|
83
|
-
# server is running.
|
84
|
-
# https://bugs.mysql.com/bug.php?id=19806
|
85
|
-
#
|
86
|
-
# An acquired task is marked with next_timeout and CONNECTION_ID().
|
87
|
-
# Therefore while alive_time is not changed and we don't restart
|
88
|
-
# the server in 1 second, they won't conflict.
|
89
|
-
if config[:disable_resource_limit]
|
90
|
-
@update_sql = <<SQL
|
91
|
-
UPDATE `#{@table}`
|
92
|
-
JOIN (
|
93
|
-
SELECT id
|
94
|
-
FROM `#{@table}` FORCE INDEX (`index_#{@table}_on_timeout`)
|
95
|
-
WHERE #{EVENT_HORIZON} < timeout AND timeout <= :now
|
96
|
-
ORDER BY timeout ASC
|
97
|
-
LIMIT :max_acquire) AS t1 USING(id)
|
98
|
-
SET timeout=:next_timeout, owner=CONNECTION_ID()
|
99
|
-
SQL
|
100
|
-
@sql = <<SQL
|
101
|
-
SELECT id, timeout, data, created_at, resource
|
102
|
-
FROM `#{@table}`
|
103
|
-
WHERE timeout = ? AND owner = CONNECTION_ID()
|
104
|
-
SQL
|
105
|
-
else
|
106
|
-
@update_sql = <<SQL
|
107
|
-
UPDATE `#{@table}`
|
108
|
-
JOIN (
|
109
|
-
SELECT id, IFNULL(max_running, 1) / (IFNULL(running, 0) + 1) AS weight
|
110
|
-
FROM `#{@table}`
|
111
|
-
LEFT JOIN (
|
112
|
-
SELECT resource, COUNT(1) AS running
|
113
|
-
FROM `#{@table}` AS t1
|
114
|
-
WHERE timeout > :now AND resource IS NOT NULL
|
115
|
-
GROUP BY resource
|
116
|
-
) AS t2 USING(resource)
|
117
|
-
WHERE #{EVENT_HORIZON} < timeout AND timeout <= :now AND IFNULL(max_running - running, 1) > 0
|
118
|
-
ORDER BY weight DESC, timeout ASC
|
119
|
-
LIMIT :max_acquire
|
120
|
-
) AS t3 USING (id)
|
121
|
-
SET timeout = :next_timeout, owner = CONNECTION_ID()
|
122
|
-
SQL
|
123
|
-
@sql = <<SQL
|
124
|
-
SELECT id, timeout, data, created_at, resource, max_running
|
125
|
-
FROM `#{@table}`
|
126
|
-
WHERE timeout = ? AND owner = CONNECTION_ID()
|
127
|
-
SQL
|
128
|
-
end
|
129
|
-
|
81
|
+
@disable_resource_limit = config[:disable_resource_limit]
|
130
82
|
@cleanup_interval = config[:cleanup_interval] || DEFAULT_DELETE_INTERVAL
|
131
83
|
# If cleanup_interval > max_request_per_child / max_acquire,
|
132
84
|
# some processes won't run DELETE query.
|
@@ -240,7 +192,6 @@ SQL
|
|
240
192
|
def acquire(alive_time, max_acquire, options)
|
241
193
|
now = (options[:now] || Time.now).to_i
|
242
194
|
next_timeout = now + alive_time
|
243
|
-
tasks = nil
|
244
195
|
t0 = nil
|
245
196
|
|
246
197
|
if @cleanup_interval_count <= 0
|
@@ -252,27 +203,11 @@ SQL
|
|
252
203
|
}
|
253
204
|
end
|
254
205
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
end
|
261
|
-
@table_unlock.call
|
262
|
-
|
263
|
-
tasks = []
|
264
|
-
@db.fetch(@sql, next_timeout) {|row|
|
265
|
-
attributes = create_attributes(nil, row)
|
266
|
-
task_token = Token.new(row[:id])
|
267
|
-
task = AcquiredTask.new(@client, row[:id], attributes, task_token)
|
268
|
-
tasks.push task
|
269
|
-
}
|
270
|
-
@cleanup_interval_count -= 1
|
271
|
-
|
272
|
-
return tasks
|
273
|
-
}
|
274
|
-
ensure
|
275
|
-
STDERR.puts "PQ:acquire from #{@table}:%6f sec (%d tasks)" % [Process.clock_gettime(Process::CLOCK_MONOTONIC)-t0,tasks.size] if tasks
|
206
|
+
if @disable_resource_limit
|
207
|
+
return acquire_without_resource(next_timeout, now, max_acquire)
|
208
|
+
else
|
209
|
+
return acquire_with_resource(next_timeout, now, max_acquire)
|
210
|
+
end
|
276
211
|
end
|
277
212
|
|
278
213
|
def force_finish(key, retention_time, options)
|
@@ -454,7 +389,98 @@ SQL
|
|
454
389
|
}
|
455
390
|
end
|
456
391
|
|
392
|
+
def acquire_without_resource(next_timeout, now, max_acquire)
|
393
|
+
# MySQL's CONNECTION_ID() is a 64bit unsigned integer from the
|
394
|
+
# server's internal thread ID counter. It is unique while the MySQL
|
395
|
+
# server is running.
|
396
|
+
# https://bugs.mysql.com/bug.php?id=19806
|
397
|
+
#
|
398
|
+
# An acquired task is marked with next_timeout and CONNECTION_ID().
|
399
|
+
# Therefore while alive_time is not changed and we don't restart
|
400
|
+
# the server in 1 second, they won't conflict.
|
401
|
+
update_sql = <<SQL
|
402
|
+
UPDATE `#{@table}`
|
403
|
+
JOIN (
|
404
|
+
SELECT id
|
405
|
+
FROM `#{@table}` FORCE INDEX (`index_#{@table}_on_timeout`)
|
406
|
+
WHERE #{EVENT_HORIZON} < timeout AND timeout <= :now
|
407
|
+
ORDER BY timeout ASC
|
408
|
+
LIMIT :max_acquire) AS t1 USING(id)
|
409
|
+
SET timeout=:next_timeout, owner=CONNECTION_ID()
|
410
|
+
SQL
|
411
|
+
select_sql = <<SQL
|
412
|
+
SELECT id, timeout, data, created_at, resource
|
413
|
+
FROM `#{@table}`
|
414
|
+
WHERE timeout = ? AND owner = CONNECTION_ID()
|
415
|
+
SQL
|
416
|
+
t0 = 0
|
417
|
+
connect_locked do
|
418
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
419
|
+
n = @db[update_sql, next_timeout: next_timeout, now: now, max_acquire: max_acquire].update
|
420
|
+
@table_unlock.call
|
421
|
+
STDERR.puts "PQ:acquire from #{@table}:%6f sec (%d tasks)" % [Process.clock_gettime(Process::CLOCK_MONOTONIC)-t0,n]
|
422
|
+
return nil if n <= 0
|
423
|
+
|
424
|
+
tasks = []
|
425
|
+
@db.fetch(select_sql, next_timeout) do |row|
|
426
|
+
attributes = create_attributes(nil, row)
|
427
|
+
task_token = Token.new(row[:id])
|
428
|
+
task = AcquiredTask.new(@client, row[:id], attributes, task_token)
|
429
|
+
tasks.push task
|
430
|
+
end
|
431
|
+
@cleanup_interval_count -= 1
|
432
|
+
return tasks
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
def acquire_with_resource(next_timeout, now, max_acquire)
|
437
|
+
t0 = nil
|
438
|
+
tasks = nil
|
439
|
+
sql = <<SQL
|
440
|
+
SELECT id, timeout, data, created_at, resource, max_running, IFNULL(max_running, 1) / (IFNULL(running, 0) + 1) AS weight
|
441
|
+
FROM `#{@table}`
|
442
|
+
LEFT JOIN (
|
443
|
+
SELECT resource AS res, COUNT(1) AS running
|
444
|
+
FROM `#{@table}` AS T
|
445
|
+
WHERE timeout > ? AND created_at IS NOT NULL AND resource IS NOT NULL
|
446
|
+
GROUP BY resource
|
447
|
+
) AS R ON resource = res
|
448
|
+
WHERE #{EVENT_HORIZON} < timeout AND timeout <= ?
|
449
|
+
AND created_at IS NOT NULL
|
450
|
+
AND (max_running-running IS NULL OR max_running-running > 0)
|
451
|
+
ORDER BY weight DESC, timeout ASC
|
452
|
+
LIMIT ?
|
453
|
+
SQL
|
454
|
+
connect_locked do
|
455
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
456
|
+
tasks = []
|
457
|
+
@db.fetch(sql, now, now, max_acquire) do |row|
|
458
|
+
attributes = create_attributes(nil, row)
|
459
|
+
task_token = Token.new(row[:id])
|
460
|
+
task = AcquiredTask.new(@client, row[:id], attributes, task_token)
|
461
|
+
tasks.push task
|
462
|
+
end
|
463
|
+
return nil if tasks.empty?
|
464
|
+
|
465
|
+
sql = "UPDATE `#{@table}` FORCE INDEX (PRIMARY) SET timeout=? WHERE timeout <= ? AND id IN ("
|
466
|
+
params = [sql, next_timeout, now]
|
467
|
+
params.concat tasks.map(&:key)
|
468
|
+
sql << '?,' * tasks.size
|
469
|
+
sql.chop!
|
470
|
+
sql << ") AND created_at IS NOT NULL"
|
471
|
+
|
472
|
+
n = @db[*params].update
|
473
|
+
if n != tasks.size
|
474
|
+
# preempted
|
475
|
+
return nil
|
476
|
+
end
|
477
|
+
end
|
478
|
+
@cleanup_interval_count -= 1
|
479
|
+
return tasks
|
480
|
+
ensure
|
481
|
+
STDERR.puts "PQ:acquire from #{@table}:%6f sec (%d tasks)" % \
|
482
|
+
[Process.clock_gettime(Process::CLOCK_MONOTONIC)-t0, tasks.size] if tasks
|
483
|
+
end
|
457
484
|
end
|
458
485
|
end
|
459
486
|
end
|
460
|
-
|
data/lib/perfectqueue/version.rb
CHANGED
@@ -96,7 +96,7 @@ describe Backend::RDBCompatBackend do
|
|
96
96
|
end
|
97
97
|
it 'supports mysql' do
|
98
98
|
expect(Backend::RDBCompatBackend.new(client, config)).to be_an_instance_of(Backend::RDBCompatBackend)
|
99
|
-
expect(db.instance_variable_get(:@
|
99
|
+
expect(db.instance_variable_get(:@disable_resource_limit)).to be_falsey
|
100
100
|
end
|
101
101
|
it 'doesn\'t support postgres' do
|
102
102
|
config = {url: 'postgres://localhost', table: table}
|
@@ -110,7 +110,7 @@ describe Backend::RDBCompatBackend do
|
|
110
110
|
it 'disable_resource_limit' do
|
111
111
|
config = {url: 'mysql2://root:@localhost/perfectqueue_test', table: table, disable_resource_limit: true}
|
112
112
|
db = Backend::RDBCompatBackend.new(client, config)
|
113
|
-
expect(db.instance_variable_get(:@
|
113
|
+
expect(db.instance_variable_get(:@disable_resource_limit)).to be_truthy
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
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.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|