queue_classic 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3137935dc373e4d8af179e93422961d1a5c07e89
4
+ data.tar.gz: 709e4565ef2dcf4635094391558942c02c44e113
5
+ SHA512:
6
+ metadata.gz: 0141f28277f3f8e26422c77c0787f3cbc84986504a97a762a62119a0036237feea1fc43ee7cc081e2483737d524aa3576d553a1a8601bf15688cf11fc0576f81
7
+ data.tar.gz: 4abb6f06e3ab1e7ad39e410cea0ff277a4b0948faf923797cec4e193131f1c54d69b36a90fba06c43b9ef6f0ed1f69ad7a9acde266c48f3566fe3a72f9e05ed1
@@ -0,0 +1,22 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'active_record'
4
+
5
+ module QC
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ namespace "queue_classic:install"
10
+ self.source_paths << File.join(File.dirname(__FILE__), 'templates')
11
+ desc 'Generates (but does not run) a migration to add a queue_classic table.'
12
+
13
+ def self.next_migration_number(dirname)
14
+ next_migration_number = current_migration_number(dirname) + 1
15
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
16
+ end
17
+
18
+ def create_migration_file
19
+ migration_template 'add_queue_classic.rb', 'db/migrate/add_queue_classic.rb'
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ class AddQueueClassic < ActiveRecord::Migration
2
+ def self.up
3
+ QC::Setup.create
4
+ end
5
+
6
+ def self.down
7
+ QC::Setup.drop
8
+ end
9
+ end
data/lib/queue_classic.rb CHANGED
@@ -1,24 +1,12 @@
1
- require "pg"
2
- require "uri"
3
- require "json"
4
-
5
- require "queue_classic/conn"
6
- require "queue_classic/queries"
7
- require "queue_classic/queue"
8
- require "queue_classic/worker"
9
- require "queue_classic/setup"
10
-
11
1
  module QC
12
- Root = File.expand_path("..", File.dirname(__FILE__))
13
- SqlFunctions = File.join(QC::Root, "/sql/ddl.sql")
14
- DropSqlFunctions = File.join(QC::Root, "/sql/drop_ddl.sql")
15
- CreateTable = File.join(QC::Root, "/sql/create_table.sql")
16
-
17
2
  # You can use the APP_NAME to query for
18
3
  # postgres related process information in the
19
4
  # pg_stat_activity table.
20
5
  APP_NAME = ENV["QC_APP_NAME"] || "queue_classic"
21
6
 
7
+ # Number of seconds to block on the listen chanel for new jobs.
8
+ WAIT_TIME = (ENV["QC_LISTEN_TIME"] || 5).to_i
9
+
22
10
  # Why do you want to change the table name?
23
11
  # Just deal with the default OK?
24
12
  # If you do want to change this, you will
@@ -35,11 +23,6 @@ module QC
35
23
  # There is nothing special about 9....
36
24
  TOP_BOUND = (ENV["QC_TOP_BOUND"] || 9).to_i
37
25
 
38
- # If you are using PostgreSQL > 9
39
- # then you will have access to listen/notify with payload.
40
- # Set this value if you wish to make your worker more efficient.
41
- LISTENING_WORKER = !ENV["QC_LISTENING_WORKER"].nil?
42
-
43
26
  # Set this variable if you wish for
44
27
  # the worker to fork a UNIX process for
45
28
  # each locked job. Remember to re-establish
@@ -47,11 +30,6 @@ module QC
47
30
  # for more details.
48
31
  FORK_WORKER = !ENV["QC_FORK_WORKER"].nil?
49
32
 
50
- # The worker uses an exponential back-off
51
- # algorithm to lock a job. This value will be used
52
- # as the max exponent.
53
- MAX_LOCK_ATTEMPTS = (ENV["QC_MAX_LOCK_ATTEMPTS"] || 5).to_i
54
-
55
33
  # Defer method calls on the QC module to the
56
34
  # default queue. This facilitates QC.enqueue()
57
35
  def self.method_missing(sym, *args, &block)
@@ -101,3 +79,8 @@ module QC
101
79
  return result
102
80
  end
103
81
  end
82
+
83
+ require "queue_classic/queue"
84
+ require "queue_classic/worker"
85
+ require "queue_classic/setup"
86
+ require "queue_classic/railtie" if defined?(Rails)
@@ -1,4 +1,6 @@
1
1
  require 'thread'
2
+ require 'uri'
3
+ require 'pg'
2
4
 
3
5
  module QC
4
6
  module Conn
@@ -22,15 +24,10 @@ module QC
22
24
  end
23
25
  end
24
26
 
25
- def notify(chan)
26
- log(:at => "NOTIFY")
27
- execute('NOTIFY "' + chan + '"') #quotes matter
28
- end
29
-
30
- def wait(chan, t)
31
- listen(chan)
32
- wait_for_notify(t)
33
- unlisten(chan)
27
+ def wait(chan)
28
+ execute('LISTEN "' + chan + '"')
29
+ wait_for_notify(WAIT_TIME)
30
+ execute('UNLISTEN "' + chan + '"')
34
31
  drain_notify
35
32
  end
36
33
 
@@ -106,19 +103,9 @@ module QC
106
103
  QC.log(msg)
107
104
  end
108
105
 
109
- def listen(chan)
110
- log(:at => "LISTEN")
111
- execute('LISTEN "' + chan + '"') #quotes matter
112
- end
113
-
114
- def unlisten(chan)
115
- log(:at => "UNLISTEN")
116
- execute('UNLISTEN "' + chan + '"') #quotes matter
117
- end
118
-
119
106
  def wait_for_notify(t)
120
- connection.wait_for_notify(t) do |event, pid, msg|
121
- log(:at => "received_notification")
107
+ Array.new.tap do |msgs|
108
+ connection.wait_for_notify(t) {|event, pid, msg| msgs << msg}
122
109
  end
123
110
  end
124
111
 
@@ -1,30 +1,53 @@
1
+ require 'queue_classic'
2
+ require 'queue_classic/conn'
3
+ require 'json'
4
+
1
5
  module QC
2
6
  class Queue
3
7
 
4
- attr_reader :name, :chan
5
- def initialize(name, notify=QC::LISTENING_WORKER)
8
+ attr_reader :name, :top_bound
9
+ def initialize(name, top_bound=nil)
6
10
  @name = name
7
- @chan = @name if notify
11
+ @top_bound = top_bound || QC::TOP_BOUND
8
12
  end
9
13
 
10
14
  def enqueue(method, *args)
11
- Queries.insert(name, method, args, chan)
15
+ QC.log_yield(:measure => 'queue.enqueue') do
16
+ s="INSERT INTO #{TABLE_NAME} (q_name, method, args) VALUES ($1, $2, $3)"
17
+ res = Conn.execute(s, name, method, JSON.dump(args))
18
+ end
12
19
  end
13
20
 
14
- def lock(top_bound=TOP_BOUND)
15
- Queries.lock_head(name, top_bound)
21
+ def lock
22
+ QC.log_yield(:measure => 'queue.lock') do
23
+ s = "SELECT * FROM lock_head($1, $2)"
24
+ if r = Conn.execute(s, name, top_bound)
25
+ {:id => r["id"],
26
+ :method => r["method"],
27
+ :args => JSON.parse(r["args"])}
28
+ end
29
+ end
16
30
  end
17
31
 
18
32
  def delete(id)
19
- Queries.delete(id)
33
+ QC.log_yield(:measure => 'queue.delete') do
34
+ Conn.execute("DELETE FROM #{TABLE_NAME} where id = $1", id)
35
+ end
20
36
  end
21
37
 
22
38
  def delete_all
23
- Queries.delete_all(name)
39
+ QC.log_yield(:measure => 'queue.delete_all') do
40
+ s = "DELETE FROM #{TABLE_NAME} WHERE q_name = $1"
41
+ Conn.execute(s, name)
42
+ end
24
43
  end
25
44
 
26
45
  def count
27
- Queries.count(name)
46
+ QC.log_yield(:measure => 'queue.count') do
47
+ s = "SELECT COUNT(*) FROM #{TABLE_NAME} WHERE q_name = $1"
48
+ r = Conn.execute(s, name)
49
+ r["count"].to_i
50
+ end
28
51
  end
29
52
 
30
53
  end
@@ -0,0 +1,9 @@
1
+ require 'rails/railtie'
2
+
3
+ module QC
4
+ class Railtie < ::Rails::Railtie
5
+ rake_tasks do
6
+ load 'queue_classic/tasks.rb'
7
+ end
8
+ end
9
+ end
@@ -1,40 +1,18 @@
1
1
  module QC
2
2
  module Setup
3
- extend self
3
+ Root = File.expand_path("../..", File.dirname(__FILE__))
4
+ SqlFunctions = File.join(Root, "/sql/ddl.sql")
5
+ CreateTable = File.join(Root, "/sql/create_table.sql")
6
+ DropSqlFunctions = File.join(Root, "/sql/drop_ddl.sql")
4
7
 
5
- def create
6
- create_table
7
- create_functions
8
+ def self.create
9
+ Conn.execute(File.read(CreateTable))
10
+ Conn.execute(File.read(SqlFunctions))
8
11
  end
9
12
 
10
- def drop
11
- drop_functions
12
- drop_table
13
+ def self.drop
14
+ Conn.execute("DROP TABLE IF EXISTS queue_classic_jobs CASCADE")
15
+ Conn.execute(File.read(DropSqlFunctions))
13
16
  end
14
-
15
- def create_table
16
- Conn.transaction do
17
- Conn.execute(File.read(CreateTable))
18
- end
19
- end
20
-
21
- def drop_table
22
- Conn.transaction do
23
- Conn.execute("DROP TABLE IF EXISTS queue_classic_jobs")
24
- end
25
- end
26
-
27
- def create_functions
28
- Conn.transaction do
29
- Conn.execute(File.read(SqlFunctions))
30
- end
31
- end
32
-
33
- def drop_functions
34
- Conn.transaction do
35
- Conn.execute(File.read(DropSqlFunctions))
36
- end
37
- end
38
-
39
17
  end
40
18
  end
@@ -1,3 +1,7 @@
1
+ require 'queue_classic'
2
+ require 'queue_classic/queue'
3
+ require 'queue_classic/conn'
4
+
1
5
  module QC
2
6
  class Worker
3
7
 
@@ -5,15 +9,10 @@ module QC
5
9
  # In the case no arguments are passed to the initializer,
6
10
  # the defaults are pulled from the environment variables.
7
11
  def initialize(args={})
8
- @q_name = args[:q_name] ||= QC::QUEUE
9
- @top_bound = args[:top_bound] ||= QC::TOP_BOUND
10
- @fork_worker = args[:fork_worker] ||= QC::FORK_WORKER
11
- @listening_worker = args[:listening_worker] ||= QC::LISTENING_WORKER
12
- @max_attempts = args[:max_attempts] ||= QC::MAX_LOCK_ATTEMPTS
13
-
14
- @running = true
15
- @queue = Queue.new(@q_name, @listening_worker)
12
+ @fork_worker = args[:fork_worker] || QC::FORK_WORKER
13
+ @queue = QC::Queue.new((args[:q_name] || QC::QUEUE), args[:top_bound])
16
14
  log(args.merge(:at => "worker_initialized"))
15
+ @running = true
17
16
  end
18
17
 
19
18
  # Start a loop and work jobs indefinitely.
@@ -36,9 +35,9 @@ module QC
36
35
  # Define setup_child to hook into the forking process.
37
36
  # Using setup_child is good for re-establishing database connections.
38
37
  def fork_and_work
39
- @cpid = fork {setup_child; work}
40
- log(:at => :fork, :pid => @cpid)
41
- Process.wait(@cpid)
38
+ cpid = fork {setup_child; work}
39
+ log(:at => :fork, :pid => cpid)
40
+ Process.wait(cpid)
42
41
  end
43
42
 
44
43
  # This method will lock a job & process the job.
@@ -50,33 +49,15 @@ module QC
50
49
  end
51
50
  end
52
51
 
53
- # lock_job will attempt to lock a job in the queue's table. It uses an
54
- # exponential backoff in the event that a job was not locked. This method
55
- # will return a hash when a job is obtained.
56
- #
57
- # This method will terminate early if the stop method is called or
58
- # @max_attempts has been reached.
59
- #
60
- # It is important that callers delete the job when finished.
61
- # *@queue.delete(job[:id])*
52
+ # Attempt to lock a job in the queue's table.
53
+ # Return a hash when a job is locked.
54
+ # Caller responsible for deleting the job when finished.
62
55
  def lock_job
63
56
  log(:at => "lock_job")
64
- attempts = 0
65
57
  job = nil
66
- until !@running || job
67
- job = @queue.lock(@top_bound)
68
- if job.nil?
69
- log(:at => "failed_lock", :attempts => attempts)
70
- if attempts < @max_attempts
71
- wait(2**attempts)
72
- attempts += 1
73
- next
74
- else
75
- break
76
- end
77
- else
78
- log(:at => "finished_lock", :job => job[:id])
79
- end
58
+ while @running
59
+ break if job = @queue.lock
60
+ Conn.wait(@queue.name)
80
61
  end
81
62
  job
82
63
  end
@@ -106,21 +87,6 @@ module QC
106
87
  klass.send(message, *args)
107
88
  end
108
89
 
109
- # If @listening_worker is set, the worker will use the database
110
- # to sleep. The database approach preferred over a syscall since
111
- # the database will break the sleep when new jobs are inserted into
112
- # the queue.
113
- def wait(t)
114
- if @listening_worker
115
- log(:at => "listen_wait", :wait => t)
116
- Conn.wait(@queue.chan)
117
- else
118
- log(:at => "sleep_wait", :wait => t)
119
- Kernel.sleep(t)
120
- end
121
- log(:at => "finished_listening")
122
- end
123
-
124
90
  # This method will be called when an exception
125
91
  # is raised during the execution of the job.
126
92
  def handle_failure(job,e)
data/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # queue_classic
2
2
 
3
- v2.2.0
3
+ v2.2.1
4
4
 
5
5
  queue_classic provides a simple interface to a PostgreSQL-backed message queue. queue_classic specializes in concurrent locking and minimizing database load while providing a simple, intuitive developer experience. queue_classic assumes that you are already using PostgreSQL in your production environment and that adding another dependency (e.g. redis, beanstalkd, 0mq) is undesirable.
6
6
 
@@ -14,7 +14,7 @@ Features:
14
14
 
15
15
  Contents:
16
16
 
17
- * [Documentation](http://rubydoc.info/gems/queue_classic/2.2.0/frames)
17
+ * [Documentation](http://rubydoc.info/gems/queue_classic/2.2.1/frames)
18
18
  * [Usage](#usage)
19
19
  * [Setup](#setup)
20
20
  * [Configuration](#configuration)
@@ -95,7 +95,7 @@ class MyWorker < QC::Worker
95
95
  end
96
96
  end
97
97
 
98
- worker = MyWorker.new(max_attempts: 10, listening_worker: true)
98
+ worker = MyWorker.new
99
99
 
100
100
  trap('INT') {exit}
101
101
  trap('TERM') {worker.stop}
@@ -129,14 +129,7 @@ Declare dependencies in Gemfile.
129
129
 
130
130
  ```ruby
131
131
  source "http://rubygems.org"
132
- gem "queue_classic", "2.2.0"
133
- ```
134
-
135
- Require these files in your Rakefile so that you can run `rake qc:work`.
136
-
137
- ```ruby
138
- require "queue_classic"
139
- require "queue_classic/tasks"
132
+ gem "queue_classic", "2.2.1"
140
133
  ```
141
134
 
142
135
  By default, queue_classic will use the QC_DATABASE_URL falling back on DATABASE_URL. The URL must be in the following format: `postgres://username:password@localhost/database_name`. If you use Heroku's PostgreSQL service, this will already be set. If you don't want to set this variable, you can set the connection in an initializer. **QueueClassic will maintain its own connection to the database.** This may double the number of connections to your database. Set QC::Conn.connection to share the connection between Rails & QueueClassic
@@ -146,21 +139,15 @@ require 'queue_classic'
146
139
  QC::Conn.connection = ActiveRecord::Base.connection.raw_connection
147
140
  ```
148
141
 
149
- **Note on using ActiveRecord migrations:** If you use the migration, and you wish to use commands that reset the database from the stored schema (e.g. `rake db:reset`), your application must be configured with `config.active_record.schema_format = :sql` in `config/application.rb`. If you don't do this, the PL/pgSQL function that queue_classic creates will be lost when you reset the database.
142
+ Next you need to run the queue classic generator to create the database
143
+ migration. This will setup the necessary table to use queue classic.
150
144
 
151
- ```ruby
152
- require 'queue_classic'
153
-
154
- class AddQueueClassic < ActiveRecord::Migration
155
- def self.up
156
- QC::Setup.create
157
- end
158
-
159
- def self.down
160
- QC::Setup.drop
161
- end
162
- end
163
145
  ```
146
+ rails generate queue_classic:install
147
+ rake db:migrate
148
+ ```
149
+
150
+ **Note on using ActiveRecord migrations:** If you use the migration, and you wish to use commands that reset the database from the stored schema (e.g. `rake db:reset`), your application must be configured with `config.active_record.schema_format = :sql` in `config/application.rb`. If you don't do this, the PL/pgSQL function that queue_classic creates will be lost when you reset the database.
164
151
 
165
152
  ### Rake Task Setup
166
153
 
data/sql/create_table.sql CHANGED
@@ -16,4 +16,14 @@ end if;
16
16
 
17
17
  end $$ language plpgsql;
18
18
 
19
+ create function queue_classic_notify() returns trigger as $$ begin
20
+ perform pg_notify(new.q_name, '');
21
+ return null;
22
+ end $$ language plpgsql;
23
+
24
+ create trigger queue_classic_notify
25
+ after insert on queue_classic_jobs
26
+ for each row
27
+ execute procedure queue_classic_notify();
28
+
19
29
  CREATE INDEX idx_qc_on_name_only_unlocked ON queue_classic_jobs (q_name, id) WHERE locked_at IS NULL;
data/sql/drop_ddl.sql CHANGED
@@ -1,2 +1,3 @@
1
1
  DROP FUNCTION IF EXISTS lock_head(tname varchar);
2
- DROP FUNCTION IF EXISTS lock_head(q_name varchar, top_boundary integer)
2
+ DROP FUNCTION IF EXISTS lock_head(q_name varchar, top_boundary integer);
3
+ DROP FUNCTION IF EXISTS queue_classic_notify() cascade;
data/test/helper.rb CHANGED
@@ -17,36 +17,11 @@ class QCTest < Minitest::Test
17
17
  QC.delete_all
18
18
  end
19
19
 
20
- def init_db(table_name="queue_classic_jobs")
20
+ def init_db
21
21
  QC::Conn.execute("SET client_min_messages TO 'warning'")
22
22
  QC::Setup.drop
23
23
  QC::Setup.create
24
- QC::Conn.execute(<<EOS)
25
- DO $$
26
- -- Set initial sequence to a large number to test the entire toolchain
27
- -- works on integers with higher bits set.
28
- DECLARE
29
- quoted_name text;
30
- quoted_size text;
31
- BEGIN
32
- -- Find the name of the relevant sequence.
33
- --
34
- -- pg_get_serial_sequence quotes identifiers as part of its
35
- -- behavior.
36
- SELECT name
37
- INTO STRICT quoted_name
38
- FROM pg_get_serial_sequence('queue_classic_jobs', 'id') AS name;
39
-
40
- -- Don't quote, because ALTER SEQUENCE RESTART doesn't like
41
- -- general literals, only unquoted numeric literals.
42
- SELECT pow(2, 34)::text AS size
43
- INTO STRICT quoted_size;
44
-
45
- EXECUTE 'ALTER SEQUENCE ' || quoted_name ||
46
- ' RESTART ' || quoted_size || ';';
47
- END;
48
- $$;
49
- EOS
24
+ QC::Conn.execute(File.read('./test/helper.sql'))
50
25
  end
51
26
 
52
27
  def capture_debug_output
data/test/queue_test.rb CHANGED
@@ -56,7 +56,7 @@ class QueueTest < QCTest
56
56
  end
57
57
 
58
58
  def test_queue_instance
59
- queue = QC::Queue.new("queue_classic_jobs", false)
59
+ queue = QC::Queue.new("queue_classic_jobs")
60
60
  queue.enqueue("Klass.method")
61
61
  assert_equal(1, queue.count)
62
62
  queue.delete(queue.lock[:id])
@@ -64,7 +64,7 @@ class QueueTest < QCTest
64
64
  end
65
65
 
66
66
  def test_repair_after_error
67
- queue = QC::Queue.new("queue_classic_jobs", false)
67
+ queue = QC::Queue.new("queue_classic_jobs")
68
68
  queue.enqueue("Klass.method")
69
69
  assert_equal(1, queue.count)
70
70
  connection = QC::Conn.connection
@@ -100,4 +100,17 @@ class QueueTest < QCTest
100
100
  ensure
101
101
  QC.default_queue = nil
102
102
  end
103
+
104
+ def test_enqueue_triggers_notify
105
+ QC::Conn.execute('LISTEN "' + QC::QUEUE + '"')
106
+ QC::Conn.send(:drain_notify)
107
+
108
+ msgs = QC::Conn.send(:wait_for_notify, 0.25)
109
+ assert_equal(0, msgs.length)
110
+
111
+ QC.enqueue("Klass.method")
112
+ msgs = QC::Conn.send(:wait_for_notify, 0.25)
113
+ assert_equal(1, msgs.length)
114
+ end
115
+
103
116
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queue_classic
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
5
- prerelease:
4
+ version: 2.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ryan Smith (♠ ace hacker)
@@ -14,7 +13,6 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: pg
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -39,9 +36,11 @@ files:
39
36
  - sql/create_table.sql
40
37
  - sql/ddl.sql
41
38
  - sql/drop_ddl.sql
39
+ - lib/generators/queue_classic/install_generator.rb
40
+ - lib/generators/queue_classic/templates/add_queue_classic.rb
42
41
  - lib/queue_classic/conn.rb
43
- - lib/queue_classic/queries.rb
44
42
  - lib/queue_classic/queue.rb
43
+ - lib/queue_classic/railtie.rb
45
44
  - lib/queue_classic/setup.rb
46
45
  - lib/queue_classic/tasks.rb
47
46
  - lib/queue_classic/worker.rb
@@ -54,27 +53,26 @@ files:
54
53
  homepage: http://github.com/ryandotsmith/queue_classic
55
54
  licenses:
56
55
  - MIT
56
+ metadata: {}
57
57
  post_install_message:
58
58
  rdoc_options: []
59
59
  require_paths:
60
60
  - lib
61
61
  required_ruby_version: !ruby/object:Gem::Requirement
62
- none: false
63
62
  requirements:
64
- - - ! '>='
63
+ - - '>='
65
64
  - !ruby/object:Gem::Version
66
65
  version: '0'
67
66
  required_rubygems_version: !ruby/object:Gem::Requirement
68
- none: false
69
67
  requirements:
70
- - - ! '>='
68
+ - - '>='
71
69
  - !ruby/object:Gem::Version
72
70
  version: '0'
73
71
  requirements: []
74
72
  rubyforge_project:
75
- rubygems_version: 1.8.23
73
+ rubygems_version: 2.0.3
76
74
  signing_key:
77
- specification_version: 3
75
+ specification_version: 4
78
76
  summary: postgres backed queue
79
77
  test_files:
80
78
  - test/benchmark_test.rb
@@ -1,42 +0,0 @@
1
- module QC
2
- module Queries
3
- extend self
4
-
5
- def insert(q_name, method, args, chan=nil)
6
- QC.log_yield(:action => "insert_job") do
7
- s = "INSERT INTO #{TABLE_NAME} (q_name, method, args) VALUES ($1, $2, $3)"
8
- res = Conn.execute(s, q_name, method, JSON.dump(args))
9
- Conn.notify(chan) if chan
10
- end
11
- end
12
-
13
- def lock_head(q_name, top_bound)
14
- s = "SELECT * FROM lock_head($1, $2)"
15
- if r = Conn.execute(s, q_name, top_bound)
16
- {
17
- :id => r["id"],
18
- :method => r["method"],
19
- :args => JSON.parse(r["args"])
20
- }
21
- end
22
- end
23
-
24
- def count(q_name=nil)
25
- s = "SELECT COUNT(*) FROM #{TABLE_NAME}"
26
- s << " WHERE q_name = $1" if q_name
27
- r = Conn.execute(*[s, q_name].compact)
28
- r["count"].to_i
29
- end
30
-
31
- def delete(id)
32
- Conn.execute("DELETE FROM #{TABLE_NAME} where id = $1", id)
33
- end
34
-
35
- def delete_all(q_name=nil)
36
- s = "DELETE FROM #{TABLE_NAME}"
37
- s << " WHERE q_name = $1" if q_name
38
- Conn.execute(*[s, q_name].compact)
39
- end
40
-
41
- end
42
- end