umbrellio-sequel-plugins 0.17.2 → 0.19.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 +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/.github/workflows/release.yml +54 -0
- data/.rubocop.yml +1 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +6 -1
- data/lib/clickhouse/migrator.rb +2 -2
- data/lib/sequel/extensions/concurrent_thread_pool.rb +201 -0
- data/lib/sequel/extensions/migration_transaction_options.rb +5 -5
- data/lib/sequel/extensions/synchronize.rb +2 -2
- data/lib/sequel/plugins/concurrent_thread_pool_eager_loading.rb +74 -0
- data/lib/sequel/plugins/upsert.rb +7 -7
- data/lib/sequel/plugins/with_lock.rb +1 -1
- data/lib/tasks/sequel/archive_migrations.rake +1 -1
- data/lib/tasks/sequel/rollback_archived_migrations.rake +1 -1
- data/lib/tasks/sequel/rollback_missing_migrations.rake +1 -1
- data/umbrellio-sequel-plugins.gemspec +3 -2
- metadata +21 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f247c8695f1d06e2ada379cf25e1b387871ff0249816099ff9dd9aaebec32fc8
|
|
4
|
+
data.tar.gz: 12cc3acf1bb7106fd70a8e4d89ba243e09c766316e2cdd60297e67f3bfafd887
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 90bf1d35960c9464c3a55e045e91952d0722fd189102e3d4f7b2890cc7c5942ed97f98c4c9000c24f4ed30f44cc2f7c05223ca8f43a6af30253baba48bc9ae28
|
|
7
|
+
data.tar.gz: a8f770ea411c1dc6688c0136d67106652f08c836f3fb2622a10200d02cae90345cb013ece33577010a41a08dcf55ca34152ec1522bf147956caf41787cdc981d
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Extract version
|
|
17
|
+
id: version
|
|
18
|
+
run: |
|
|
19
|
+
version=$(grep -oP '(?<=version = ")[^"]+' umbrellio-sequel-plugins.gemspec)
|
|
20
|
+
echo "tag=v$version" >> "$GITHUB_OUTPUT"
|
|
21
|
+
|
|
22
|
+
- name: Check if release already exists
|
|
23
|
+
id: check
|
|
24
|
+
run: |
|
|
25
|
+
if gh release view "${{ steps.version.outputs.tag }}" &>/dev/null; then
|
|
26
|
+
echo "exists=true" >> "$GITHUB_OUTPUT"
|
|
27
|
+
else
|
|
28
|
+
echo "exists=false" >> "$GITHUB_OUTPUT"
|
|
29
|
+
fi
|
|
30
|
+
env:
|
|
31
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
+
|
|
33
|
+
- uses: ruby/setup-ruby@v1
|
|
34
|
+
if: steps.check.outputs.exists == 'false'
|
|
35
|
+
with:
|
|
36
|
+
ruby-version: "3.4"
|
|
37
|
+
bundler-cache: true
|
|
38
|
+
|
|
39
|
+
- name: Build gem
|
|
40
|
+
if: steps.check.outputs.exists == 'false'
|
|
41
|
+
run: gem build umbrellio-sequel-plugins.gemspec
|
|
42
|
+
|
|
43
|
+
- name: Push gem to RubyGems
|
|
44
|
+
if: steps.check.outputs.exists == 'false'
|
|
45
|
+
run: gem push *.gem
|
|
46
|
+
env:
|
|
47
|
+
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
|
|
48
|
+
|
|
49
|
+
- uses: softprops/action-gh-release@v3
|
|
50
|
+
if: steps.check.outputs.exists == 'false'
|
|
51
|
+
with:
|
|
52
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
53
|
+
files: "*.gem"
|
|
54
|
+
generate_release_notes: true
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
umbrellio-sequel-plugins (0.
|
|
4
|
+
umbrellio-sequel-plugins (0.19.0)
|
|
5
|
+
concurrent-ruby
|
|
5
6
|
sequel
|
|
6
7
|
|
|
7
8
|
GEM
|
|
@@ -40,12 +41,15 @@ GEM
|
|
|
40
41
|
concurrent-ruby (~> 1.0)
|
|
41
42
|
json (2.7.2)
|
|
42
43
|
language_server-protocol (3.17.0.3)
|
|
44
|
+
logger (1.7.0)
|
|
43
45
|
method_source (1.1.0)
|
|
44
46
|
minitest (5.25.1)
|
|
45
47
|
money (6.19.0)
|
|
46
48
|
i18n (>= 0.6.4, <= 2)
|
|
47
49
|
mutex_m (0.2.0)
|
|
48
50
|
nio4r (2.7.3)
|
|
51
|
+
opentelemetry-api (1.10.0)
|
|
52
|
+
logger
|
|
49
53
|
parallel (1.26.3)
|
|
50
54
|
parser (3.3.5.0)
|
|
51
55
|
ast (~> 2.4.1)
|
|
@@ -139,6 +143,7 @@ PLATFORMS
|
|
|
139
143
|
DEPENDENCIES
|
|
140
144
|
async
|
|
141
145
|
money
|
|
146
|
+
opentelemetry-api
|
|
142
147
|
pg
|
|
143
148
|
pry
|
|
144
149
|
rake
|
data/lib/clickhouse/migrator.rb
CHANGED
|
@@ -18,13 +18,13 @@ module Clickhouse
|
|
|
18
18
|
migrator(target: target.to_i).run
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def migrator(**
|
|
21
|
+
def migrator(**)
|
|
22
22
|
Sequel::TimestampMigrator.new(
|
|
23
23
|
DB,
|
|
24
24
|
Rails.root.join("db/migrate/clickhouse"),
|
|
25
25
|
table: :clickhouse_migrations,
|
|
26
26
|
use_transactions: false,
|
|
27
|
-
|
|
27
|
+
**,
|
|
28
28
|
)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent"
|
|
4
|
+
|
|
5
|
+
module Sequel
|
|
6
|
+
# https://github.com/jeremyevans/sequel/blob/master/lib/sequel/extensions/async_thread_pool.rb
|
|
7
|
+
module Database::ConcurrentThreadPool
|
|
8
|
+
# Base proxy: delegates all method calls to the resolved async value.
|
|
9
|
+
class BaseProxy < BasicObject
|
|
10
|
+
def method_missing(...)
|
|
11
|
+
__value.public_send(...)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def respond_to_missing?(*)
|
|
15
|
+
__value.respond_to?(*)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
[:!, :==, :!=, :instance_eval, :instance_exec].each do |method|
|
|
19
|
+
define_method(method) do |*args, &block|
|
|
20
|
+
__value.public_send(method, *args, &block)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Default proxy: schedules block via Concurrent::Future, blocks on first access.
|
|
26
|
+
class Proxy < BaseProxy
|
|
27
|
+
def initialize(executor, &)
|
|
28
|
+
super()
|
|
29
|
+
|
|
30
|
+
@future = Concurrent::Promises.future_on(executor, &)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def __value
|
|
34
|
+
@future.value!
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Preemptable proxy: calling thread runs the block if the pool hasn't started it yet.
|
|
39
|
+
class PreemptableProxy < BaseProxy
|
|
40
|
+
def initialize(executor, &block)
|
|
41
|
+
super()
|
|
42
|
+
|
|
43
|
+
@mutex = Mutex.new
|
|
44
|
+
@block = block
|
|
45
|
+
@done = false
|
|
46
|
+
@result = nil
|
|
47
|
+
@error = nil
|
|
48
|
+
|
|
49
|
+
executor.post { __run }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def __value
|
|
53
|
+
error, result = @mutex.synchronize do
|
|
54
|
+
__execute unless @done
|
|
55
|
+
[@error, @result]
|
|
56
|
+
end
|
|
57
|
+
::Kernel.raise error if error
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def __run
|
|
64
|
+
@mutex.synchronize { __execute unless @done }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def __execute
|
|
68
|
+
@result = @block.call
|
|
69
|
+
rescue StandardError => error
|
|
70
|
+
@error = error
|
|
71
|
+
ensure
|
|
72
|
+
@done = true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
module DatabaseMethods
|
|
77
|
+
class << self
|
|
78
|
+
def make_finalizer(executor) = proc { executor.shutdown }
|
|
79
|
+
|
|
80
|
+
def extended(db)
|
|
81
|
+
db.instance_exec do
|
|
82
|
+
case pool.pool_type
|
|
83
|
+
when :single, :sharded_single
|
|
84
|
+
raise Error, "cannot load concurrent_thread_pool extension " \
|
|
85
|
+
"if using single or sharded_single connection pool"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
executor, owned = choose_executor(opts)
|
|
89
|
+
proxy_klass =
|
|
90
|
+
typecast_value_boolean(opts[:preempt_async_thread]) ? PreemptableProxy : Proxy
|
|
91
|
+
|
|
92
|
+
define_singleton_method(:async_job_class) { proxy_klass }
|
|
93
|
+
define_singleton_method(:async_thread_executor) { executor }
|
|
94
|
+
|
|
95
|
+
finalizer =
|
|
96
|
+
Sequel::Database::ConcurrentThreadPool::DatabaseMethods.make_finalizer(executor)
|
|
97
|
+
ObjectSpace.define_finalizer(db, finalizer) if owned
|
|
98
|
+
|
|
99
|
+
extend_datasets(DatasetMethods)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def choose_executor(opts)
|
|
107
|
+
if opts[:async_thread_executor]
|
|
108
|
+
[opts[:async_thread_executor], false]
|
|
109
|
+
else
|
|
110
|
+
num = opts[:num_async_threads] ? typecast_value_integer(opts[:num_async_threads]) :
|
|
111
|
+
Integer(opts[:max_connections] || 4)
|
|
112
|
+
raise Error, "must have positive number for num_async_threads" if num <= 0
|
|
113
|
+
[Concurrent::ThreadPoolExecutor.new(
|
|
114
|
+
min_threads: num,
|
|
115
|
+
max_threads: num,
|
|
116
|
+
max_queue: 0,
|
|
117
|
+
fallback_policy: :abort,
|
|
118
|
+
), true]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def async_run(&)
|
|
123
|
+
otel_context = OpenTelemetry::Context.current if defined?(OpenTelemetry::Context)
|
|
124
|
+
|
|
125
|
+
if otel_context && !otel_context.equal?(OpenTelemetry::Context::ROOT)
|
|
126
|
+
async_job_class.new(async_thread_executor) do
|
|
127
|
+
OpenTelemetry::Context.with_current(otel_context, &)
|
|
128
|
+
end
|
|
129
|
+
else
|
|
130
|
+
async_job_class.new(async_thread_executor, &)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
ASYNC_METHODS = ((
|
|
136
|
+
[:all?, :any?, :drop, :entries, :grep_v, :include?, :inject, :member?, :minmax,
|
|
137
|
+
:none?, :one?, :reduce, :sort, :take, :tally, :to_a, :to_h, :uniq, :zip] &
|
|
138
|
+
Enumerable.instance_methods
|
|
139
|
+
) + (Dataset::ACTION_METHODS - [:map, :paged_each])).freeze
|
|
140
|
+
|
|
141
|
+
ASYNC_BLOCK_METHODS = ((
|
|
142
|
+
[:collect, :collect_concat, :detect, :drop_while, :each_cons, :each_entry, :each_slice,
|
|
143
|
+
:each_with_index, :each_with_object, :filter_map, :find, :find_all, :find_index,
|
|
144
|
+
:flat_map, :max_by, :min_by, :minmax_by, :partition, :reject, :reverse_each,
|
|
145
|
+
:sort_by, :take_while] & Enumerable.instance_methods
|
|
146
|
+
) + [:paged_each]).freeze
|
|
147
|
+
|
|
148
|
+
ASYNC_ARGS_OR_BLOCK_METHODS = [:map].freeze
|
|
149
|
+
|
|
150
|
+
module DatasetMethods
|
|
151
|
+
def self.define_async_method(mod, method)
|
|
152
|
+
mod.send(:define_method, method) do |*args, &block|
|
|
153
|
+
if @opts[:async]
|
|
154
|
+
ds = sync
|
|
155
|
+
db.send(:async_run) { ds.send(method, *args, &block) }
|
|
156
|
+
else
|
|
157
|
+
super(*args, &block)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def self.define_async_block_method(mod, method)
|
|
163
|
+
mod.send(:define_method, method) do |*args, &block|
|
|
164
|
+
if block && @opts[:async]
|
|
165
|
+
ds = sync
|
|
166
|
+
db.send(:async_run) { ds.send(method, *args, &block) }
|
|
167
|
+
else
|
|
168
|
+
super(*args, &block)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.define_async_args_or_block_method(mod, method)
|
|
174
|
+
mod.send(:define_method, method) do |*args, &block|
|
|
175
|
+
if (block || !args.empty?) && @opts[:async]
|
|
176
|
+
ds = sync
|
|
177
|
+
db.send(:async_run) { ds.send(method, *args, &block) }
|
|
178
|
+
else
|
|
179
|
+
super(*args, &block)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
ASYNC_METHODS.each { |m| define_async_method(self, m) }
|
|
185
|
+
ASYNC_BLOCK_METHODS.each { |m| define_async_block_method(self, m) }
|
|
186
|
+
ASYNC_ARGS_OR_BLOCK_METHODS.each { |m| define_async_args_or_block_method(self, m) }
|
|
187
|
+
|
|
188
|
+
def async
|
|
189
|
+
cached_dataset(:_async) { clone(async: true) }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def sync
|
|
193
|
+
cached_dataset(:_sync) { clone(async: false) }
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
Database.register_extension(
|
|
199
|
+
:concurrent_thread_pool, Database::ConcurrentThreadPool::DatabaseMethods
|
|
200
|
+
)
|
|
201
|
+
end
|
|
@@ -11,9 +11,9 @@ module SimpleMigrationExtension
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
module MigratorExtension
|
|
14
|
-
def checked_transaction(migration, &
|
|
14
|
+
def checked_transaction(migration, &)
|
|
15
15
|
if _use_transaction?(migration)
|
|
16
|
-
_transaction(migration, &
|
|
16
|
+
_transaction(migration, &)
|
|
17
17
|
else
|
|
18
18
|
yield
|
|
19
19
|
end
|
|
@@ -38,11 +38,11 @@ module MigratorExtension
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def _transaction(migration, &
|
|
41
|
+
def _transaction(migration, &)
|
|
42
42
|
if migration.transaction_opts.nil?
|
|
43
|
-
db.transaction(&
|
|
43
|
+
db.transaction(&)
|
|
44
44
|
else
|
|
45
|
-
db.transaction(migration.transaction_opts, &
|
|
45
|
+
db.transaction(migration.transaction_opts, &)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -24,9 +24,9 @@ module Sequel
|
|
|
24
24
|
def synchronize_with(*args, timeout: 10, savepoint: false, skip_if_locked: false)
|
|
25
25
|
key = lock_key_for(args)
|
|
26
26
|
|
|
27
|
-
transaction(savepoint:
|
|
27
|
+
transaction(savepoint:) do
|
|
28
28
|
hash = key_hash(key)
|
|
29
|
-
if get_lock(key, hash, timeout
|
|
29
|
+
if get_lock(key, hash, timeout:, skip_if_locked:)
|
|
30
30
|
log_info("locked with #{key} (#{hash})")
|
|
31
31
|
yield
|
|
32
32
|
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Plugins
|
|
5
|
+
# Concurrent eager loading using concurrent_thread_pool extension.
|
|
6
|
+
# Adapted from Sequel's built-in concurrent_eager_loading plugin but uses
|
|
7
|
+
# our concurrent_thread_pool extension instead of async_thread_pool.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
#
|
|
11
|
+
# DB.extension(:concurrent_thread_pool)
|
|
12
|
+
# Album.plugin :concurrent_thread_pool_eager_loading
|
|
13
|
+
# Album.eager_load_concurrently.eager(:artist, :genre, :tracks).all
|
|
14
|
+
#
|
|
15
|
+
# # Always concurrent by default:
|
|
16
|
+
# Album.plugin :concurrent_thread_pool_eager_loading, always: true
|
|
17
|
+
module ConcurrentThreadPoolEagerLoading
|
|
18
|
+
def self.configure(mod, opts = OPTS)
|
|
19
|
+
if opts.key?(:always)
|
|
20
|
+
mod.instance_variable_set(:@always_eager_load_concurrently, opts[:always])
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ClassMethods
|
|
25
|
+
Plugins.inherited_instance_variables(self, :@always_eager_load_concurrently => nil)
|
|
26
|
+
Plugins.def_dataset_methods(self, [:eager_load_concurrently, :eager_load_serially])
|
|
27
|
+
|
|
28
|
+
def always_eager_load_concurrently?
|
|
29
|
+
@always_eager_load_concurrently
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module DatasetMethods
|
|
34
|
+
def eager_load_concurrently
|
|
35
|
+
cached_dataset(:_eager_load_concurrently) do
|
|
36
|
+
clone(eager_load_concurrently: true)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def eager_load_serially
|
|
41
|
+
cached_dataset(:_eager_load_serially) do
|
|
42
|
+
clone(eager_load_concurrently: false)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def eager_load_concurrently?
|
|
49
|
+
v = @opts[:eager_load_concurrently]
|
|
50
|
+
v.nil? ? model.always_eager_load_concurrently? : v
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def perform_eager_loads(eager_load_data)
|
|
54
|
+
return super if !eager_load_concurrently? || eager_load_data.length < 2
|
|
55
|
+
|
|
56
|
+
mutex = Mutex.new
|
|
57
|
+
eager_load_data.each_value do |elo|
|
|
58
|
+
elo[:mutex] = mutex
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
super.each do |v|
|
|
62
|
+
if Sequel::Database::ConcurrentThreadPool::BaseProxy === v # rubocop:disable Style/CaseEquality
|
|
63
|
+
v.__value
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def perform_eager_load(loader, elo)
|
|
69
|
+
elo[:mutex] ? db.send(:async_run) { super } : super
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -16,7 +16,7 @@ module Sequel::Plugins::Upsert
|
|
|
16
16
|
where_spec = cols.map { |x| Sequel::Plugins::Upsert.distinct_expr(table_name, x) }.reduce(:|)
|
|
17
17
|
|
|
18
18
|
dataset.insert_conflict(
|
|
19
|
-
target
|
|
19
|
+
target:,
|
|
20
20
|
update: update_spec,
|
|
21
21
|
update_where: where_spec,
|
|
22
22
|
)
|
|
@@ -25,21 +25,21 @@ module Sequel::Plugins::Upsert
|
|
|
25
25
|
# Executes the upsert request
|
|
26
26
|
#
|
|
27
27
|
# @param row [Hash] values
|
|
28
|
-
# @param
|
|
28
|
+
# @param target [Symbol] target column
|
|
29
29
|
#
|
|
30
30
|
# @example
|
|
31
|
-
# User.upsert(name: "John", email: "jd@test.com", target: :email)
|
|
31
|
+
# User.upsert({name: "John", email: "jd@test.com"}, target: :email)
|
|
32
32
|
# @return [Sequel::Model]
|
|
33
|
-
def upsert(row, **
|
|
34
|
-
upsert_dataset(**
|
|
33
|
+
def upsert(row, **)
|
|
34
|
+
upsert_dataset(**).insert(sequel_values(row))
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Executes the upsert request for multiple rows
|
|
38
38
|
# @see #upsert
|
|
39
39
|
# @see #upsert_dataset
|
|
40
|
-
def multi_upsert(rows, **
|
|
40
|
+
def multi_upsert(rows, **)
|
|
41
41
|
rows = rows.map { |row| sequel_values(row) }
|
|
42
|
-
upsert_dataset(**
|
|
42
|
+
upsert_dataset(**).multi_insert(rows)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Returns formatted row values
|
|
@@ -15,7 +15,7 @@ namespace :sequel do
|
|
|
15
15
|
|
|
16
16
|
migrations = Rails.root.glob(migrations_path).map do |file|
|
|
17
17
|
filename = file.basename.to_s
|
|
18
|
-
{ version: filename.to_i, filename
|
|
18
|
+
{ version: filename.to_i, filename:, source: file.read }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
conflict_options = {
|
|
@@ -21,7 +21,7 @@ namespace :sequel do
|
|
|
21
21
|
|
|
22
22
|
migrator_args = {
|
|
23
23
|
table: args[:migration_table],
|
|
24
|
-
use_transactions
|
|
24
|
+
use_transactions:,
|
|
25
25
|
allow_missing_migration_files: false,
|
|
26
26
|
}.compact
|
|
27
27
|
migrator = Sequel::TimestampMigrator.new(DB, tmpdir, migrator_args)
|
|
@@ -23,7 +23,7 @@ namespace :sequel do
|
|
|
23
23
|
path = Rails.root.join("db/migrate")
|
|
24
24
|
migrator_args = {
|
|
25
25
|
table: args[:table],
|
|
26
|
-
use_transactions
|
|
26
|
+
use_transactions:,
|
|
27
27
|
allow_missing_migration_files: false,
|
|
28
28
|
}.compact
|
|
29
29
|
migrator = Sequel::TimestampMigrator.new(DB, path, migrator_args)
|
|
@@ -5,8 +5,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "umbrellio-sequel-plugins"
|
|
8
|
-
spec.version = "0.
|
|
9
|
-
spec.required_ruby_version = ">= 3.
|
|
8
|
+
spec.version = "0.19.0"
|
|
9
|
+
spec.required_ruby_version = ">= 3.3"
|
|
10
10
|
|
|
11
11
|
spec.authors = ["Team Umbrellio"]
|
|
12
12
|
spec.email = ["oss@umbrellio.biz"]
|
|
@@ -18,5 +18,6 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
+
spec.add_runtime_dependency "concurrent-ruby"
|
|
21
22
|
spec.add_runtime_dependency "sequel"
|
|
22
23
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: umbrellio-sequel-plugins
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.19.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Team Umbrellio
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: concurrent-ruby
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
13
26
|
- !ruby/object:Gem::Dependency
|
|
14
27
|
name: sequel
|
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -32,6 +45,7 @@ extensions: []
|
|
|
32
45
|
extra_rdoc_files: []
|
|
33
46
|
files:
|
|
34
47
|
- ".github/workflows/ci.yml"
|
|
48
|
+
- ".github/workflows/release.yml"
|
|
35
49
|
- ".gitignore"
|
|
36
50
|
- ".rspec"
|
|
37
51
|
- ".rubocop.yml"
|
|
@@ -43,6 +57,7 @@ files:
|
|
|
43
57
|
- bin/console
|
|
44
58
|
- bin/setup
|
|
45
59
|
- lib/clickhouse/migrator.rb
|
|
60
|
+
- lib/sequel/extensions/concurrent_thread_pool.rb
|
|
46
61
|
- lib/sequel/extensions/currency_rates.rb
|
|
47
62
|
- lib/sequel/extensions/deferrable_foreign_keys.rb
|
|
48
63
|
- lib/sequel/extensions/fibered_connection_pool.rb
|
|
@@ -54,6 +69,7 @@ files:
|
|
|
54
69
|
- lib/sequel/extensions/synchronize.rb
|
|
55
70
|
- lib/sequel/plugins/attr_encrypted.rb
|
|
56
71
|
- lib/sequel/plugins/attr_encrypted/simple_crypt.rb
|
|
72
|
+
- lib/sequel/plugins/concurrent_thread_pool_eager_loading.rb
|
|
57
73
|
- lib/sequel/plugins/duplicate.rb
|
|
58
74
|
- lib/sequel/plugins/get_column_value.rb
|
|
59
75
|
- lib/sequel/plugins/money_accessors.rb
|
|
@@ -77,7 +93,6 @@ homepage: https://github.com/umbrellio/umbrellio-sequel-plugins
|
|
|
77
93
|
licenses:
|
|
78
94
|
- MIT
|
|
79
95
|
metadata: {}
|
|
80
|
-
post_install_message:
|
|
81
96
|
rdoc_options: []
|
|
82
97
|
require_paths:
|
|
83
98
|
- lib
|
|
@@ -85,15 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
85
100
|
requirements:
|
|
86
101
|
- - ">="
|
|
87
102
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '3.
|
|
103
|
+
version: '3.3'
|
|
89
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
105
|
requirements:
|
|
91
106
|
- - ">="
|
|
92
107
|
- !ruby/object:Gem::Version
|
|
93
108
|
version: '0'
|
|
94
109
|
requirements: []
|
|
95
|
-
rubygems_version: 3.
|
|
96
|
-
signing_key:
|
|
110
|
+
rubygems_version: 3.6.9
|
|
97
111
|
specification_version: 4
|
|
98
112
|
summary: Sequel plugins
|
|
99
113
|
test_files: []
|