active_record-write 1.0.0
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 +7 -0
- data/lib/active_record-write.rb +1 -0
- data/lib/active_record.rb +6 -0
- data/lib/active_record/base.rb +7 -0
- data/lib/active_record/write.rb +99 -0
- data/lib/active_record/write/version.rb +5 -0
- data/spec/lib/active_record/write/version_spec.rb +7 -0
- data/spec/lib/active_record/write_spec.rb +7 -0
- data/spec/spec_helper.rb +26 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e37a5dd2f5438b1e90d1b99d251547754c6e8741
|
4
|
+
data.tar.gz: 4ef8d7bbd787b497939061f6e4ae102e25688b65
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17012e8e1335f4c654ac3e4dbe54a53b3d8748c50c5426eaeaf2a80b4b0bca922e3d7417d6643f4e689f0b2c19a2780921a956683fc2f4c181a7cd9ea1f60a0c
|
7
|
+
data.tar.gz: d09d836529d88a6b9faee71dbbd6f77d821417b29f631310578c32a8e0f68ec65fcb71d56c026ff6d598e91c63d6a3c02e6bb02ef7a1291af83c747cc6efa01e
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'active_record'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
def self.write(columns:, query: self, target: self.table_name, size: Write::DEFAULT_SIZE, serializer: Write::DEFAULT_SERIALIZER, &iteration)
|
4
|
+
ActiveRecord::Write.new(columns: columns, query: query, target: target, size: size, serializer: serializer, &iteration).pool
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Write
|
3
|
+
require_relative "write/version"
|
4
|
+
|
5
|
+
DEFAULT_SIZE = 24
|
6
|
+
DEFAULT_SERIALIZER = ::JSON
|
7
|
+
EMPTY_HASH = {}
|
8
|
+
|
9
|
+
# `query` is either an ActiveRecord query object or arel
|
10
|
+
# `columns` is a list of columns you want to have during the transaction
|
11
|
+
# `target` is the table you want to talk to
|
12
|
+
# `size` is the maximum number of running iterations in the pool, default: 24
|
13
|
+
# `serializer` is the #dump duck for Array & Hash values, default: JSON
|
14
|
+
# `transaction` is the process you want to run against your database
|
15
|
+
def initialize(query:, columns:, target:, size:, serializer:, &transaction)
|
16
|
+
@query = query
|
17
|
+
@columns = columns
|
18
|
+
@target = target
|
19
|
+
@size = size
|
20
|
+
@serializer = serializer
|
21
|
+
@transaction = transaction
|
22
|
+
@table = Arel::Table.new(@target)
|
23
|
+
@queue = case
|
24
|
+
when activerecord?
|
25
|
+
@query.pluck(*@columns)
|
26
|
+
when arel?
|
27
|
+
ActiveRecord::Base.connection.execute(@query.to_sql).map(&:values)
|
28
|
+
when tuple?
|
29
|
+
@query.map(&:values)
|
30
|
+
when twodimensional?
|
31
|
+
@query
|
32
|
+
else
|
33
|
+
raise ArgumentError, 'query wasn\'t recognizable, please use some that looks like a: ActiveRecord::Base, Arel::SelectManager, Array<*Hash>, Array<*Array>'
|
34
|
+
end
|
35
|
+
puts "Migrating #{@queue.count} #{@target} records"
|
36
|
+
end
|
37
|
+
|
38
|
+
def pool(qutex = Mutex.new)
|
39
|
+
# Spin up a number of threads based on the `maximum` given
|
40
|
+
1.upto(@size).map do
|
41
|
+
Thread.new do
|
42
|
+
loop do
|
43
|
+
# Try to get a new queue item
|
44
|
+
item = qutex.synchronize { @queue.shift }
|
45
|
+
|
46
|
+
if item.nil?
|
47
|
+
# There is no more work
|
48
|
+
break
|
49
|
+
else
|
50
|
+
# Wait for a free connection
|
51
|
+
ActiveRecord::Base.connection_pool.with_connection do
|
52
|
+
ActiveRecord::Base.transaction do
|
53
|
+
# Execute each statement coming back
|
54
|
+
Array[instance_exec(*item, &@transaction)].each do |instruction|
|
55
|
+
ActiveRecord::Base.connection.execute(instruction.to_sql)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end.map(&:join)
|
63
|
+
end
|
64
|
+
|
65
|
+
private def activerecord?
|
66
|
+
@query.kind_of?(ActiveRecord::Base) || @query.kind_of?(ActiveRecord::Relation)
|
67
|
+
end
|
68
|
+
|
69
|
+
private def arel?
|
70
|
+
@query.kind_of?(Arel::SelectManager)
|
71
|
+
end
|
72
|
+
|
73
|
+
private def tuple?
|
74
|
+
@query.kind_of?(Array) && @query.first.kind_of?(Hash)
|
75
|
+
end
|
76
|
+
|
77
|
+
private def twodimensional?
|
78
|
+
@query.kind_of?(Array) && @query.first.kind_of?(Array)
|
79
|
+
end
|
80
|
+
|
81
|
+
private def update(id, data)
|
82
|
+
Arel::UpdateManager.new(ActiveRecord::Base).table(@table).where(@table[:id].eq(id)).set(serialize(data))
|
83
|
+
end
|
84
|
+
|
85
|
+
private def insert(data)
|
86
|
+
Arel::InsertManager.new(ActiveRecord::Base).tap { |m| m.insert(serialize(data)) }
|
87
|
+
end
|
88
|
+
|
89
|
+
private def serialize(data)
|
90
|
+
data.inject(EMPTY_HASH) do |state, (key, value)|
|
91
|
+
if value.is_a?(Array) || value.is_a?(Hash)
|
92
|
+
state.merge(@table[key] => JSON.dump(value))
|
93
|
+
else
|
94
|
+
state.merge(@table[key] => value)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "codeclimate-test-reporter"
|
2
|
+
require "pry"
|
3
|
+
require "rspec"
|
4
|
+
require "write"
|
5
|
+
|
6
|
+
RSpec.configure do |let|
|
7
|
+
let.before("suite") do
|
8
|
+
CodeClimate::TestReporter.start
|
9
|
+
end
|
10
|
+
|
11
|
+
# Exit the spec after the first failure
|
12
|
+
let.fail_fast = true
|
13
|
+
|
14
|
+
# Only run a specific file, using the ENV variable
|
15
|
+
# Example: FILE=spec/write/version_spec.rb bundle exec rake spec
|
16
|
+
let.pattern = ENV["FILE"]
|
17
|
+
|
18
|
+
# Show the slowest examples in the suite
|
19
|
+
let.profile_examples = true
|
20
|
+
|
21
|
+
# Colorize the output
|
22
|
+
let.color = true
|
23
|
+
|
24
|
+
# Output as a document string
|
25
|
+
let.default_formatter = "doc"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_record-write
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kurtis Rainbolt-Greene
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.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.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.9'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.9'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-doc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.4'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.4'
|
111
|
+
description: A library for doing pooled writes to a SQL Datbase
|
112
|
+
email:
|
113
|
+
- me@kurtisrainboltgreene.name
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- lib/active_record-write.rb
|
119
|
+
- lib/active_record.rb
|
120
|
+
- lib/active_record/base.rb
|
121
|
+
- lib/active_record/write.rb
|
122
|
+
- lib/active_record/write/version.rb
|
123
|
+
- spec/lib/active_record/write/version_spec.rb
|
124
|
+
- spec/lib/active_record/write_spec.rb
|
125
|
+
- spec/spec_helper.rb
|
126
|
+
homepage: http://krainboltgreene.github.io/active_record-write
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata: {}
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 2.4.5.1
|
147
|
+
signing_key:
|
148
|
+
specification_version: 4
|
149
|
+
summary: A library for doing pooled writes to a SQL Datbase
|
150
|
+
test_files:
|
151
|
+
- spec/lib/active_record/write/version_spec.rb
|
152
|
+
- spec/lib/active_record/write_spec.rb
|
153
|
+
- spec/spec_helper.rb
|
154
|
+
has_rdoc:
|