postqueue 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 922c5d4f8d07a93c7e889709d136de7159014599
4
+ data.tar.gz: fb6d7ac28ed62728a688a4e1cf8f7b6120626b55
5
+ SHA512:
6
+ metadata.gz: d9371b02973a1ff7776daa9f0f2dac442723acc42d52c4745497438d261fbdd5956178af4d56aea962d9cd5f040a112f9be834c25d7602b4c01b913bf417b3d8
7
+ data.tar.gz: 0172ea33447642ca43b836b662a52401bae80810940dfd54e24d423600b7462d5b2a9f9376ce35e0b6a46598cd438de3989f4b6d6ea228c7c494aa8f651c5ae7
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Postqueue
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/postqueue`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'postqueue'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install postqueue
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/postqueue.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
@@ -0,0 +1,23 @@
1
+ module Postqueue
2
+ module Enqueue
3
+ Item = ::Postqueue::Item
4
+
5
+ def enqueue(op:, entity_type:, entity_id:)
6
+ # An optimized code path, as laid out below, is 4 times as fast.
7
+ # However, exec_query changed from Rails 4 to Rails 5.
8
+
9
+ # sql = "INSERT INTO postqueue (op, entity_type, entity_id) VALUES($1, $2, $3)"
10
+ # binds = [ ]
11
+ #
12
+ # binds << ActiveRecord::Attribute.from_user("name", op, ::ActiveRecord::Type::String.new)
13
+ # binds << ActiveRecord::Attribute.from_user("entity_type", entity_type, ::ActiveRecord::Type::String.new)
14
+ # binds << ActiveRecord::Attribute.from_user("entity_id", entity_id, ::ActiveRecord::Type::Integer.new)
15
+ # # Note: Rails 4 does not understand prepare: true
16
+ # db.exec_query(sql, 'SQL', binds, prepare: true)
17
+
18
+ Item.create!(op: op, entity_type: entity_type, entity_id: entity_id)
19
+ end
20
+ end
21
+
22
+ extend Enqueue
23
+ end
@@ -0,0 +1,30 @@
1
+ require "active_record"
2
+
3
+ module Postqueue
4
+ class Item < ActiveRecord::Base
5
+ self.table_name = :postqueue
6
+ end
7
+
8
+ def self.unmigrate!
9
+ Item.connection.execute <<-SQL
10
+ DROP TABLE IF EXISTS postqueue;
11
+ SQL
12
+ end
13
+
14
+ def self.migrate!
15
+ Item.connection.execute <<-SQL
16
+ CREATE TABLE postqueue (
17
+ id SERIAL PRIMARY KEY,
18
+ op VARCHAR,
19
+ entity_type VARCHAR,
20
+ entity_id INTEGER NOT NULL DEFAULT 0,
21
+ created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'),
22
+ next_run_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'),
23
+ failed_attempts INTEGER NOT NULL DEFAULT 0
24
+ );
25
+
26
+ CREATE INDEX postqueue_idx1 ON postqueue(entity_id);
27
+ CREATE INDEX postqueue_idx2 ON postqueue(next_run_at);
28
+ SQL
29
+ end
30
+ end
@@ -0,0 +1,97 @@
1
+ module Postqueue
2
+ MAX_ATTEMPTS = 3
3
+
4
+ module Processing
5
+ # Processes many entries
6
+ #
7
+ # process limit: 100, skip_duplicates: true
8
+ def process(options = {}, &block)
9
+ limit = options.fetch(:limit, 100)
10
+ skip_duplicates = options.fetch(:skip_duplicates, true)
11
+ options.delete :limit
12
+ options.delete :skip_duplicates
13
+
14
+ status, result = Item.transaction do
15
+ process_inside_transaction options, limit: limit, skip_duplicates: skip_duplicates, &block
16
+ end
17
+
18
+ raise result if status == :err
19
+ result
20
+ end
21
+
22
+ # Process a single entry from the queue
23
+ #
24
+ # Example:
25
+ #
26
+ # process_one do |op, entity_type
27
+ # end
28
+ def process_one(options = {}, &block)
29
+ options = options.merge(limit: 1, skip_duplicates: false)
30
+ process options, &block
31
+ end
32
+
33
+ private
34
+
35
+ def select_and_lock(relation, limit:)
36
+ relation = relation.where("failed_attempts < ? AND next_run_at < ?", MAX_ATTEMPTS, Time.now).order(:next_run_at, :id)
37
+
38
+ sql = relation.to_sql + " FOR UPDATE SKIP LOCKED"
39
+ sql += " LIMIT #{limit}" if limit
40
+ items = Item.find_by_sql(sql)
41
+
42
+ items
43
+ end
44
+
45
+ # The actual processing. Returns [ :ok, number-of-items ] or [ :err, exception ]
46
+ def process_inside_transaction(options, limit:, skip_duplicates:, &block)
47
+ relation = Item.all
48
+ relation = relation.where(options[:where]) if options[:where]
49
+
50
+ first_match = select_and_lock(relation, limit: 1).first
51
+ return [ :ok, nil ] unless first_match
52
+
53
+ # find all matching entries with the same entity_type/op value
54
+ if limit > 1
55
+ batch_relation = relation.where(entity_type: first_match.entity_type, op: first_match.op)
56
+ matches = select_and_lock(batch_relation, limit: limit)
57
+ else
58
+ matches = [ first_match ]
59
+ end
60
+
61
+ entity_ids = matches.map(&:entity_id)
62
+
63
+ # When skipping dupes we'll find and lock all entries that match entity_type,
64
+ # op, and one of the entity_ids in the first batch of matches
65
+ if skip_duplicates
66
+ entity_ids.uniq!
67
+ process_relations = relation.where(entity_type: first_match.entity_type, op: first_match.op, entity_id: entity_ids)
68
+ process_items = select_and_lock process_relations, limit: nil
69
+ else
70
+ process_items = matches
71
+ end
72
+
73
+ # Actually process the queue items
74
+ result = [ first_match.op, first_match.entity_type, entity_ids ]
75
+ result = yield *result if block_given?
76
+
77
+ if result == false
78
+ postpone process_items
79
+ else
80
+ Item.where(id: process_items.map(&:id)).delete_all
81
+ end
82
+
83
+ [ :ok, result ]
84
+ rescue => e
85
+ postpone process_items
86
+ [ :err, e ]
87
+ end
88
+
89
+ def postpone(items)
90
+ ids = items.map(&:id)
91
+ sql = "UPDATE postqueue SET failed_attempts = failed_attempts+1, next_run_at = next_run_at + interval '10 second' WHERE id IN (#{ids.join(",")})"
92
+ Item.connection.exec_query(sql)
93
+ end
94
+ end
95
+
96
+ extend Processing
97
+ end
@@ -0,0 +1,3 @@
1
+ module Postqueue
2
+ VERSION = '0.0.1'
3
+ end
data/lib/postqueue.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'postqueue/item'
2
+ require 'postqueue/enqueue'
3
+ require 'postqueue/processing'
4
+ require 'postqueue/version'
5
+
6
+ module Postqueue
7
+ end
8
+
9
+ # require 'postqueue/railtie' if defined?(Rails)
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Postqueue::Enqueue do
4
+ before do
5
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
6
+ end
7
+
8
+ let(:item) { Postqueue::Item.first }
9
+
10
+ it 'enqueues items' do
11
+ expect(item.op).to eq("myop")
12
+ expect(item.entity_type).to eq("mytype")
13
+ expect(item.entity_id).to eq(12)
14
+ end
15
+
16
+ it 'sets defaults' do
17
+ expect(item.created_at).to be > (Time.now - 1.second)
18
+ expect(item.next_run_at).to be > (Time.now - 1.second)
19
+ expect(item.failed_attempts).to eq(0)
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe "::Postqueue" do
4
+ it "reports a version" do
5
+ expect(Postqueue::VERSION).to satisfy { |s| s =~ /\d\.\d+\.\d+/ }
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe "::Postqueue.process_one" do
4
+ class E < RuntimeError; end
5
+
6
+ before do
7
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
8
+ end
9
+
10
+ it "fails when block raises an exception and reraises the exception" do
11
+ expect { Postqueue.process_one do |op, type, ids| raise E end }.to raise_error(E)
12
+ expect(items.map(&:entity_id)).to contain_exactly(12)
13
+ end
14
+
15
+ it "fails when block returns false" do
16
+ Postqueue.process_one do |op, type, ids| false end
17
+ expect(items.map(&:entity_id)).to contain_exactly(12)
18
+ end
19
+
20
+ it "keeps item in the queue after failure, with an increased failed_attempt count" do
21
+ called_block = 0
22
+ Postqueue.process_one do called_block += 1; false end
23
+ expect(called_block).to eq(1)
24
+
25
+ expect(items.map(&:entity_id)).to contain_exactly(12)
26
+ expect(items.first.failed_attempts).to eq(1)
27
+ end
28
+
29
+ it "ignores items with a failed_attempt count > MAX_ATTEMPTS" do
30
+ expect(Postqueue::MAX_ATTEMPTS).to be >= 3
31
+ items.update_all(failed_attempts: 3)
32
+
33
+ called_block = 0
34
+ r = Postqueue.process_one do called_block += 1; false end
35
+ expect(r).to eq(nil)
36
+ expect(called_block).to eq(0)
37
+
38
+ expect(items.map(&:entity_id)).to contain_exactly(12)
39
+ expect(items.first.failed_attempts).to eq(3)
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe "::Postqueue.process_one" do
4
+ before do
5
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
6
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 13
7
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 14
8
+ end
9
+
10
+ it "processes one entry" do
11
+ r = Postqueue.process_one
12
+ expect(r).to eq(["myop", "mytype", [12]])
13
+ expect(items.map(&:entity_id)).to contain_exactly(13, 14)
14
+ end
15
+
16
+ it "honors search conditions" do
17
+ Postqueue.enqueue op: "otherop", entity_type: "mytype", entity_id: 112
18
+
19
+ r = Postqueue.process_one(where: { op: "otherop" })
20
+ expect(r).to eq(["otherop", "mytype", [112]])
21
+ expect(items.map(&:entity_id)).to contain_exactly(12, 13, 14)
22
+ end
23
+
24
+ it "yields a block and returns it" do
25
+ Postqueue.enqueue op: "otherop", entity_type: "mytype", entity_id: 112
26
+ r = Postqueue.process_one(where: { op: "otherop" }) do |op, type, ids|
27
+ expect(op).to eq("otherop")
28
+ expect(type).to eq("mytype")
29
+ expect(ids).to eq([112])
30
+ "yihaa"
31
+ end
32
+
33
+ expect(r).to eq("yihaa")
34
+ expect(items.map(&:entity_id)).to contain_exactly(12, 13, 14)
35
+ end
36
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe "::Postqueue.process" do
4
+ context 'when having entries with the same entity_type and op' do
5
+ before do
6
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
7
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 13
8
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 14
9
+ end
10
+
11
+ it "processes one entries" do
12
+ r = Postqueue.process limit: 1
13
+ expect(r).to eq(["myop", "mytype", [12]])
14
+ expect(items.map(&:entity_id)).to contain_exactly(13, 14)
15
+ end
16
+
17
+ it "processes two entries" do
18
+ r = Postqueue.process limit: 2
19
+ expect(r).to eq(["myop", "mytype", [12, 13]])
20
+ expect(items.map(&:entity_id)).to contain_exactly(14)
21
+ end
22
+
23
+ it "processes many entries" do
24
+ r = Postqueue.process
25
+ expect(r).to eq(["myop", "mytype", [12, 13, 14]])
26
+ expect(items.map(&:entity_id)).to contain_exactly()
27
+ end
28
+ end
29
+
30
+ context 'when having entries with different entity_type and op' do
31
+ before do
32
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
33
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 13
34
+ Postqueue.enqueue op: "otherop", entity_type: "mytype", entity_id: 14
35
+ Postqueue.enqueue op: "myop", entity_type: "othertype", entity_id: 15
36
+ Postqueue.enqueue op: "otherop", entity_type: "othertype", entity_id: 16
37
+ end
38
+
39
+ it "processes one entries" do
40
+ r = Postqueue.process limit: 1
41
+ expect(r).to eq(["myop", "mytype", [12]])
42
+ expect(items.map(&:entity_id)).to contain_exactly(13, 14, 15, 16)
43
+ end
44
+
45
+ it "processes two entries" do
46
+ r = Postqueue.process limit: 2
47
+ expect(r).to eq(["myop", "mytype", [12, 13]])
48
+ expect(items.map(&:entity_id)).to contain_exactly(14, 15, 16)
49
+ end
50
+
51
+ it "processes only matching entries when asked for more" do
52
+ r = Postqueue.process
53
+ expect(r).to eq(["myop", "mytype", [12, 13]])
54
+ expect(items.map(&:entity_id)).to contain_exactly(14, 15, 16)
55
+ end
56
+
57
+ it "honors search conditions" do
58
+ r = Postqueue.process(where: { op: "otherop" })
59
+ expect(r).to eq(["otherop", "mytype", [14]])
60
+ expect(items.map(&:entity_id)).to contain_exactly(12, 13, 15, 16)
61
+ end
62
+ end
63
+
64
+ context 'when having duplicate entries' do
65
+ before do
66
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
67
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 13
68
+ Postqueue.enqueue op: "myop", entity_type: "mytype", entity_id: 12
69
+ end
70
+
71
+ it "removes duplicates from the queue" do
72
+ r = Postqueue.process limit: 1
73
+ expect(r).to eq(["myop", "mytype", [12]])
74
+ expect(items.map(&:entity_id)).to contain_exactly(13)
75
+ end
76
+
77
+ it "does not remove duplicates when skip_duplicates is set to false" do
78
+ r = Postqueue.process limit: 1, skip_duplicates: false
79
+ expect(r).to eq(["myop", "mytype", [12]])
80
+ expect(items.map(&:entity_id)).to contain_exactly(13, 12)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,29 @@
1
+ path = File.expand_path('../../mpx/lib', __FILE__)
2
+ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
3
+
4
+ ENV['RACK_ENV'] = 'test'
5
+
6
+ require 'rspec'
7
+ require 'pry'
8
+ require 'simplecov'
9
+
10
+ SimpleCov.start do
11
+ minimum_coverage 94
12
+ end
13
+
14
+ require 'postqueue'
15
+ require './spec/support/configure_active_record'
16
+
17
+ def items
18
+ Postqueue::Item.all
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.run_all_when_everything_filtered = true
23
+ config.filter_run focus: (ENV['CI'] != 'true')
24
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
25
+ config.order = 'random'
26
+
27
+ config.before(:all) { }
28
+ config.after { }
29
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_record'
2
+ require_relative './models'
3
+
4
+ $LOAD_PATH << File.dirname(__FILE__)
5
+
6
+ ActiveRecord::Base.establish_connection(adapter: 'postgresql',
7
+ database: 'postqueue_test',
8
+ username: 'postqueue',
9
+ password: 'postqueue')
10
+
11
+ require_relative 'schema.rb'
12
+ require_relative 'models.rb'
13
+
14
+ Postqueue.unmigrate!
15
+ Postqueue.migrate!
16
+
17
+ RSpec.configure do |config|
18
+ config.around(:each) do |example|
19
+ ActiveRecord::Base.connection.transaction do
20
+ example.run
21
+ raise ActiveRecord::Rollback, 'Clean up'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,123 @@
1
+ __END__
2
+
3
+ require 'ostruct'
4
+
5
+ class MockAssocationInfo < OpenStruct
6
+ def virtual?; mode == :virtual; end
7
+ def belongs_to?; mode == :belongs_to; end
8
+ def habtm?; mode == :has_and_belongs_to_many; end
9
+ end
10
+
11
+ module AnalyticsReflectionStub
12
+ attr :analytics_reflection
13
+ def set_analytics_reflection(hsh)
14
+ @analytics_reflection = OpenStruct.new(hsh)
15
+ end
16
+
17
+ attr :analytics_parent
18
+ def set_analytics_parent(analytics_parent)
19
+ @analytics_parent = analytics_parent
20
+ end
21
+ end
22
+
23
+ class Unicorn < ActiveRecord::Base
24
+ extend AnalyticsReflectionStub
25
+
26
+ def self.name_without_prefix
27
+ 'UnicornWithoutPrefix'
28
+ end
29
+
30
+ validates_presence_of :name
31
+
32
+ set_analytics_reflection associations_by_foreign_keys: {}, analytics_keys: [:name]
33
+ end
34
+
35
+ class Manticore < ActiveRecord::Base
36
+ def self.name_without_prefix
37
+ 'ManticoreWithoutPrefix'
38
+ end
39
+ end
40
+
41
+ class Rider < ActiveRecord::Base
42
+ end
43
+
44
+ class Foal < ActiveRecord::Base
45
+ extend AnalyticsReflectionStub
46
+
47
+ belongs_to :parent, class_name: 'Unicorn'
48
+ has_and_belongs_to_many :riders, class_name: 'Rider'
49
+
50
+ set_analytics_reflection associations_by_foreign_keys:
51
+ {
52
+ parent_id: MockAssocationInfo.new(mode: :belongs_to, klass: Unicorn, name: :parent),
53
+ rider_ids: MockAssocationInfo.new(mode: :has_and_belongs_to_many, klass: Rider, name: :riders),
54
+ stable_ids: MockAssocationInfo.new(mode: :virtual, name: :stables)
55
+ },
56
+ analytics_keys: [:nick_name, :age, :parent]
57
+ set_analytics_parent :parent
58
+ end
59
+
60
+ class Pegasus < ActiveRecord::Base
61
+ extend AnalyticsReflectionStub
62
+
63
+ belongs_to :parent, class_name: 'Foal'
64
+
65
+ set_analytics_reflection associations_by_foreign_keys: { :parent_id => OpenStruct.new(klass: Foal, name: :parent) },
66
+ analytics_keys: [:nick_name, :age, :parent]
67
+ set_analytics_parent :parent
68
+
69
+ attr_reader :affiliation_id
70
+ end
71
+
72
+ class Dragon < ActiveRecord::Base
73
+ def self.name_without_prefix
74
+ 'DragonWithoutPrefix'
75
+ end
76
+
77
+ def describe
78
+ 'yihaa'
79
+ end
80
+
81
+ extend AnalyticsReflectionStub
82
+ end
83
+
84
+ class Asset < ActiveRecord::Base
85
+ extend AnalyticsReflectionStub
86
+ attr_reader :affiliation_id
87
+ end
88
+
89
+ class Product < ActiveRecord::Base
90
+ extend AnalyticsReflectionStub
91
+ attr_reader :affiliation_id
92
+ end
93
+
94
+ class User < ActiveRecord::Base
95
+ extend AnalyticsReflectionStub
96
+ attr_reader :affiliation_id
97
+
98
+ def analytics_title
99
+ "my analytics_title"
100
+ end
101
+ end
102
+
103
+ class Grouping < ActiveRecord::Base
104
+ extend AnalyticsReflectionStub
105
+ attr_reader :affiliation_id
106
+ end
107
+
108
+ class Group < Grouping
109
+ end
110
+
111
+ class MockProductAsset < ActiveRecord::Base
112
+ has_one :asset
113
+ has_one :product
114
+
115
+ attr_accessor :asset, :product
116
+ end
117
+
118
+ class MockGroupUser < ActiveRecord::Base
119
+ has_one :group
120
+ has_one :user
121
+
122
+ attr_accessor :group, :user
123
+ end
@@ -0,0 +1,88 @@
1
+ __END__
2
+
3
+ ActiveRecord::Schema.define do
4
+ self.verbose = false
5
+
6
+ create_table :unicorns, force: true do |t|
7
+ t.string :name, null: false
8
+ t.string :affiliation_id
9
+ end
10
+
11
+ create_table :foals, force: true do |t|
12
+ t.integer :parent_id, null: false
13
+ t.string :nick_name
14
+ t.integer :age
15
+ t.datetime :created_at
16
+ end
17
+
18
+ create_table :riders, force: true do |t|
19
+ t.string :nick_name
20
+ end
21
+
22
+ create_table :foal_riders, force: true do |t|
23
+ t.integer :rider_id
24
+ t.integer :foal_id
25
+ end
26
+
27
+ create_table :pegasus, force: true do |t|
28
+ t.integer :parent_id, null: false
29
+ t.string :nick_name
30
+ t.integer :age
31
+ t.datetime :created_at
32
+ end
33
+
34
+ create_table :mock_product_assets, force: true do |t|
35
+ t.integer :asset_id
36
+ t.string :access_level
37
+ t.integer :product_id
38
+ end
39
+
40
+ create_table :mock_group_users, force: true do |t|
41
+ t.integer :user_id
42
+ t.string :access_level
43
+ t.integer :group_id
44
+ end
45
+
46
+ create_table :assets, force: true
47
+
48
+ create_table :products, force: true
49
+
50
+ create_table :users, force: true do |t|
51
+ t.string :title
52
+ end
53
+
54
+ create_table :groupings, force: true
55
+
56
+ create_table :manticores, force: true do |t|
57
+ t.string :dummy_field
58
+ end
59
+
60
+ create_table :dragons, force: true do |t|
61
+ t.string :full_name
62
+ end
63
+
64
+ execute "INSERT INTO unicorns(affiliation_id, id, name) VALUES('mpx', 1, 'Faith')"
65
+ execute "INSERT INTO unicorns(affiliation_id, id, name) VALUES('mpx', 2, 'Faery')"
66
+ execute "INSERT INTO unicorns(affiliation_id, id, name) VALUES('mpx', 3, 'Yaser')"
67
+
68
+ execute "INSERT INTO foals(id, parent_id, nick_name, age, created_at) VALUES(1, 1, 'Little Faith', 12, 0)"
69
+ execute "INSERT INTO foals(id, parent_id, nick_name, age, created_at) VALUES(2, 1, 'Faith Nick', 9, 0)"
70
+
71
+ execute "INSERT INTO riders(id, nick_name) VALUES(1, 'Storm Rider')"
72
+ execute "INSERT INTO riders(id, nick_name) VALUES(2, 'Desert Rider')"
73
+
74
+ execute "INSERT INTO foal_riders(rider_id, foal_id) VALUES(1, 1)"
75
+ execute "INSERT INTO foal_riders(rider_id, foal_id) VALUES(2, 1)"
76
+
77
+ execute "INSERT INTO pegasus(parent_id, nick_name, age, created_at) VALUES(1, 'Derpy', 12, 0)"
78
+
79
+ execute "INSERT INTO dragons(full_name) VALUES('Chrysophylax Dives')"
80
+ execute "INSERT INTO dragons(full_name) VALUES('Nepomuk')"
81
+ execute "INSERT INTO dragons(full_name) VALUES('Smaug')"
82
+
83
+ execute "INSERT INTO manticores(dummy_field) VALUES('Dumb Manticore')"
84
+
85
+ execute "INSERT INTO users(id, title) VALUES(67, 'sixtyseven')"
86
+
87
+ execute "INSERT INTO groupings(id) VALUES(42)"
88
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postqueue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - radiospiel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.4.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.4.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 10.5.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 10.5.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: activerecord
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: timecop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pg
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: a postgres based queue implementation
126
+ email:
127
+ - radiospiel@open-lab.org
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - README.md
133
+ - lib/postqueue.rb
134
+ - lib/postqueue/enqueue.rb
135
+ - lib/postqueue/item.rb
136
+ - lib/postqueue/processing.rb
137
+ - lib/postqueue/version.rb
138
+ - spec/postqueue/enqueue_spec.rb
139
+ - spec/postqueue/postqueue_spec.rb
140
+ - spec/postqueue/process_errors_spec.rb
141
+ - spec/postqueue/process_one_spec.rb
142
+ - spec/postqueue/process_spec.rb
143
+ - spec/spec_helper.rb
144
+ - spec/support/configure_active_record.rb
145
+ - spec/support/models.rb
146
+ - spec/support/schema.rb
147
+ homepage: https://github.com/radiospiel/postqueue
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.5.1
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: a postgres based queue implementation
171
+ test_files: []