pgtk 0.13.1 → 0.15.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/reuse.yml +0 -2
- data/.github/workflows/typos.yml +19 -0
- data/.gitignore +7 -5
- data/.rubocop.yml +5 -4
- data/.rultor.yml +1 -1
- data/Gemfile +7 -7
- data/Gemfile.lock +29 -133
- data/README.md +8 -8
- data/REUSE.toml +20 -2
- data/Rakefile +0 -1
- data/lib/pgtk/impatient.rb +91 -0
- data/lib/pgtk/liquibase_task.rb +35 -2
- data/lib/pgtk/pgsql_task.rb +43 -1
- data/lib/pgtk/pool.rb +34 -1
- data/lib/pgtk/spy.rb +50 -1
- data/lib/pgtk/version.rb +1 -1
- data/lib/pgtk/wire.rb +19 -7
- data/resources/pom.xml +1 -1
- data/test/test__helper.rb +53 -4
- data/test/test_impatient.rb +30 -0
- data/test/test_liquibase_task.rb +3 -2
- data/test/test_pgsql_task.rb +2 -2
- data/test/test_pool.rb +2 -31
- data/test-resources/2019/01-test.xml +1 -1
- data/test-resources/master.xml +1 -1
- metadata +7 -8
- data/.simplecov +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb389fe1825d50f64cd532e633a3dec67a4f928035159e750adc6e5efeec35d5
|
4
|
+
data.tar.gz: 96d345dbcb2215e77398394e4a15b0e96de53d9beb014860778920b69376355c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64eef80f0ceccb5da54db1705b58877519a6db87b6af8cc9ccce7314181abdd0715d10bbae34dc638a2f25c55a9622c6b4666ce18ce4d35e57ce2f3ae4c90693
|
7
|
+
data.tar.gz: 915a3ba9b2b9c30183a12fadb9e7cd7f91da96d7e1d5a9a5bc1ce145219231629bf574524e0c64f24928c5b7f83d9a428eb380bd8b8eacb11c25b9f144f2278d
|
data/.github/workflows/reuse.yml
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
---
|
4
|
+
# yamllint disable rule:line-length
|
5
|
+
name: typos
|
6
|
+
'on':
|
7
|
+
push:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
pull_request:
|
11
|
+
branches:
|
12
|
+
- master
|
13
|
+
jobs:
|
14
|
+
typos:
|
15
|
+
timeout-minutes: 15
|
16
|
+
runs-on: ubuntu-24.04
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v4
|
19
|
+
- uses: crate-ci/typos@v1.32.0
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -10,6 +10,10 @@ AllCops:
|
|
10
10
|
TargetRubyVersion: 2.3
|
11
11
|
SuggestExtensions: false
|
12
12
|
NewCops: enable
|
13
|
+
plugins:
|
14
|
+
- rubocop-rake
|
15
|
+
- rubocop-minitest
|
16
|
+
- rubocop-performance
|
13
17
|
Minitest/EmptyLineBeforeAssertionMethods:
|
14
18
|
Enabled: false
|
15
19
|
Style/ClassAndModuleChildren:
|
@@ -32,7 +36,4 @@ Metrics/PerceivedComplexity:
|
|
32
36
|
Max: 15
|
33
37
|
Metrics/ParameterLists:
|
34
38
|
Max: 6
|
35
|
-
|
36
|
-
- rubocop-rake
|
37
|
-
- rubocop-minitest
|
38
|
-
- rubocop-performance
|
39
|
+
require: []
|
data/.rultor.yml
CHANGED
data/Gemfile
CHANGED
@@ -6,17 +6,17 @@
|
|
6
6
|
source 'https://rubygems.org'
|
7
7
|
gemspec
|
8
8
|
|
9
|
-
gem 'minitest', '5.25
|
9
|
+
gem 'minitest', '~>5.25', require: false
|
10
10
|
gem 'minitest-reporters', '~>1.7', require: false
|
11
|
-
gem 'rack', '3.1
|
12
|
-
gem 'rake', '13.2
|
13
|
-
gem '
|
14
|
-
gem 'rubocop', '1.72.2', require: false
|
11
|
+
gem 'rack', '~>3.1', require: false
|
12
|
+
gem 'rake', '~>13.2', require: false
|
13
|
+
gem 'rubocop', '~>1.73', require: false
|
15
14
|
gem 'rubocop-minitest', '>0', require: false
|
16
15
|
gem 'rubocop-performance', '>0', require: false
|
17
16
|
gem 'rubocop-rake', '>0', require: false
|
18
17
|
gem 'rubocop-rspec', '>0', require: false
|
19
|
-
gem 'simplecov', '0.22
|
18
|
+
gem 'simplecov', '~>0.22', require: false
|
20
19
|
gem 'simplecov-cobertura', '~>2.1'
|
20
|
+
gem 'timeout', '>0'
|
21
21
|
gem 'xcop', '>0', require: false
|
22
|
-
gem 'yard', '0.9
|
22
|
+
gem 'yard', '~>0.9', require: false
|
data/Gemfile.lock
CHANGED
@@ -11,150 +11,52 @@ PATH
|
|
11
11
|
GEM
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
|
-
actionpack (8.0.1)
|
15
|
-
actionview (= 8.0.1)
|
16
|
-
activesupport (= 8.0.1)
|
17
|
-
nokogiri (>= 1.8.5)
|
18
|
-
rack (>= 2.2.4)
|
19
|
-
rack-session (>= 1.0.1)
|
20
|
-
rack-test (>= 0.6.3)
|
21
|
-
rails-dom-testing (~> 2.2)
|
22
|
-
rails-html-sanitizer (~> 1.6)
|
23
|
-
useragent (~> 0.16)
|
24
|
-
actionview (8.0.1)
|
25
|
-
activesupport (= 8.0.1)
|
26
|
-
builder (~> 3.1)
|
27
|
-
erubi (~> 1.11)
|
28
|
-
rails-dom-testing (~> 2.2)
|
29
|
-
rails-html-sanitizer (~> 1.6)
|
30
|
-
activesupport (8.0.1)
|
31
|
-
base64
|
32
|
-
benchmark (>= 0.3)
|
33
|
-
bigdecimal
|
34
|
-
concurrent-ruby (~> 1.0, >= 1.3.1)
|
35
|
-
connection_pool (>= 2.2.5)
|
36
|
-
drb
|
37
|
-
i18n (>= 1.6, < 2)
|
38
|
-
logger (>= 1.4.2)
|
39
|
-
minitest (>= 5.1)
|
40
|
-
securerandom (>= 0.3)
|
41
|
-
tzinfo (~> 2.0, >= 2.0.5)
|
42
|
-
uri (>= 0.13.1)
|
43
14
|
ansi (1.5.0)
|
44
|
-
ast (2.4.
|
15
|
+
ast (2.4.3)
|
45
16
|
backtrace (0.4.0)
|
46
|
-
base64 (0.2.0)
|
47
|
-
benchmark (0.4.0)
|
48
|
-
bigdecimal (3.1.9)
|
49
17
|
builder (3.3.0)
|
50
|
-
concurrent-ruby (1.3.5)
|
51
|
-
connection_pool (2.5.0)
|
52
|
-
crass (1.0.6)
|
53
|
-
date (3.4.1)
|
54
|
-
diff-lcs (1.6.0)
|
55
18
|
differ (0.1.2)
|
56
19
|
docile (1.4.1)
|
57
|
-
drb (2.2.1)
|
58
20
|
elapsed (0.0.1)
|
59
21
|
loog (> 0)
|
60
22
|
tago (> 0)
|
61
|
-
|
62
|
-
i18n (1.14.7)
|
63
|
-
concurrent-ruby (~> 1.0)
|
64
|
-
io-console (0.8.0)
|
65
|
-
irb (1.15.1)
|
66
|
-
pp (>= 0.6.0)
|
67
|
-
rdoc (>= 4.0.0)
|
68
|
-
reline (>= 0.4.2)
|
69
|
-
json (2.10.1)
|
23
|
+
json (2.11.3)
|
70
24
|
language_server-protocol (3.17.0.4)
|
71
25
|
lint_roller (1.1.0)
|
72
|
-
logger (1.6.6)
|
73
|
-
loofah (2.24.0)
|
74
|
-
crass (~> 1.0.2)
|
75
|
-
nokogiri (>= 1.12.0)
|
76
26
|
loog (0.6.0)
|
77
|
-
minitest (5.25.
|
27
|
+
minitest (5.25.5)
|
78
28
|
minitest-reporters (1.7.1)
|
79
29
|
ansi
|
80
30
|
builder
|
81
31
|
minitest (>= 5.0)
|
82
32
|
ruby-progressbar
|
83
|
-
nokogiri (1.18.
|
33
|
+
nokogiri (1.18.8-arm64-darwin)
|
84
34
|
racc (~> 1.4)
|
85
|
-
nokogiri (1.18.
|
35
|
+
nokogiri (1.18.8-x64-mingw-ucrt)
|
86
36
|
racc (~> 1.4)
|
87
|
-
nokogiri (1.18.
|
37
|
+
nokogiri (1.18.8-x86_64-linux-gnu)
|
88
38
|
racc (~> 1.4)
|
89
|
-
parallel (1.
|
90
|
-
parser (3.3.
|
39
|
+
parallel (1.27.0)
|
40
|
+
parser (3.3.8.0)
|
91
41
|
ast (~> 2.4.1)
|
92
42
|
racc
|
93
43
|
pg (1.5.9)
|
94
44
|
pg (1.5.9-x64-mingw-ucrt)
|
95
|
-
|
96
|
-
prettyprint
|
97
|
-
prettyprint (0.2.0)
|
98
|
-
psych (5.2.3)
|
99
|
-
date
|
100
|
-
stringio
|
45
|
+
prism (1.4.0)
|
101
46
|
qbash (0.4.0)
|
102
47
|
backtrace (> 0)
|
103
48
|
elapsed (> 0)
|
104
49
|
loog (> 0)
|
105
50
|
tago (> 0)
|
106
51
|
racc (1.8.1)
|
107
|
-
rack (3.1.
|
108
|
-
rack-session (2.1.0)
|
109
|
-
base64 (>= 0.1.0)
|
110
|
-
rack (>= 3.0.0)
|
111
|
-
rack-test (2.2.0)
|
112
|
-
rack (>= 1.3)
|
113
|
-
rackup (2.2.1)
|
114
|
-
rack (>= 3)
|
115
|
-
rails-dom-testing (2.2.0)
|
116
|
-
activesupport (>= 5.0.0)
|
117
|
-
minitest
|
118
|
-
nokogiri (>= 1.6)
|
119
|
-
rails-html-sanitizer (1.6.2)
|
120
|
-
loofah (~> 2.21)
|
121
|
-
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
122
|
-
railties (8.0.1)
|
123
|
-
actionpack (= 8.0.1)
|
124
|
-
activesupport (= 8.0.1)
|
125
|
-
irb (~> 1.13)
|
126
|
-
rackup (>= 1.0.0)
|
127
|
-
rake (>= 12.2)
|
128
|
-
thor (~> 1.0, >= 1.2.2)
|
129
|
-
zeitwerk (~> 2.6)
|
52
|
+
rack (3.1.13)
|
130
53
|
rainbow (3.1.1)
|
131
54
|
rake (13.2.1)
|
132
55
|
random-port (0.7.5)
|
133
56
|
tago (> 0)
|
134
|
-
rdoc (6.12.0)
|
135
|
-
psych (>= 4.0.0)
|
136
57
|
regexp_parser (2.10.0)
|
137
|
-
reline (0.6.0)
|
138
|
-
io-console (~> 0.5)
|
139
58
|
rexml (3.4.1)
|
140
|
-
|
141
|
-
rspec-support (~> 3.13.0)
|
142
|
-
rspec-expectations (3.13.3)
|
143
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
144
|
-
rspec-support (~> 3.13.0)
|
145
|
-
rspec-mocks (3.13.2)
|
146
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
147
|
-
rspec-support (~> 3.13.0)
|
148
|
-
rspec-rails (7.1.0)
|
149
|
-
actionpack (>= 7.0)
|
150
|
-
activesupport (>= 7.0)
|
151
|
-
railties (>= 7.0)
|
152
|
-
rspec-core (~> 3.13)
|
153
|
-
rspec-expectations (~> 3.13)
|
154
|
-
rspec-mocks (~> 3.13)
|
155
|
-
rspec-support (~> 3.13)
|
156
|
-
rspec-support (3.13.2)
|
157
|
-
rubocop (1.72.2)
|
59
|
+
rubocop (1.75.5)
|
158
60
|
json (~> 2.3)
|
159
61
|
language_server-protocol (~> 3.17.0.2)
|
160
62
|
lint_roller (~> 1.1.0)
|
@@ -162,27 +64,27 @@ GEM
|
|
162
64
|
parser (>= 3.3.0.2)
|
163
65
|
rainbow (>= 2.2.2, < 4.0)
|
164
66
|
regexp_parser (>= 2.9.3, < 3.0)
|
165
|
-
rubocop-ast (>= 1.
|
67
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
166
68
|
ruby-progressbar (~> 1.7)
|
167
69
|
unicode-display_width (>= 2.4.0, < 4.0)
|
168
|
-
rubocop-ast (1.
|
169
|
-
parser (>= 3.3.
|
170
|
-
|
70
|
+
rubocop-ast (1.44.1)
|
71
|
+
parser (>= 3.3.7.2)
|
72
|
+
prism (~> 1.4)
|
73
|
+
rubocop-minitest (0.38.0)
|
171
74
|
lint_roller (~> 1.1)
|
172
|
-
rubocop (>= 1.
|
75
|
+
rubocop (>= 1.75.0, < 2.0)
|
173
76
|
rubocop-ast (>= 1.38.0, < 2.0)
|
174
|
-
rubocop-performance (1.
|
77
|
+
rubocop-performance (1.25.0)
|
175
78
|
lint_roller (~> 1.1)
|
176
|
-
rubocop (>= 1.
|
79
|
+
rubocop (>= 1.75.0, < 2.0)
|
177
80
|
rubocop-ast (>= 1.38.0, < 2.0)
|
178
81
|
rubocop-rake (0.7.1)
|
179
82
|
lint_roller (~> 1.1)
|
180
83
|
rubocop (>= 1.72.1)
|
181
|
-
rubocop-rspec (3.
|
84
|
+
rubocop-rspec (3.6.0)
|
182
85
|
lint_roller (~> 1.1)
|
183
86
|
rubocop (~> 1.72, >= 1.72.1)
|
184
87
|
ruby-progressbar (1.13.0)
|
185
|
-
securerandom (0.4.1)
|
186
88
|
simplecov (0.22.0)
|
187
89
|
docile (~> 1.1)
|
188
90
|
simplecov-html (~> 0.11)
|
@@ -193,23 +95,17 @@ GEM
|
|
193
95
|
simplecov-html (0.13.1)
|
194
96
|
simplecov_json_formatter (0.1.4)
|
195
97
|
slop (4.10.1)
|
196
|
-
|
197
|
-
|
198
|
-
thor (1.3.2)
|
199
|
-
tzinfo (2.0.6)
|
200
|
-
concurrent-ruby (~> 1.0)
|
98
|
+
tago (0.1.0)
|
99
|
+
timeout (0.4.3)
|
201
100
|
unicode-display_width (3.1.4)
|
202
101
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
203
102
|
unicode-emoji (4.0.4)
|
204
|
-
uri (1.0.2)
|
205
|
-
useragent (0.16.11)
|
206
103
|
xcop (0.8.0)
|
207
104
|
differ (~> 0.1.2)
|
208
105
|
nokogiri (~> 1.10)
|
209
106
|
rainbow (~> 3.0)
|
210
107
|
slop (~> 4.4)
|
211
108
|
yard (0.9.37)
|
212
|
-
zeitwerk (2.7.2)
|
213
109
|
|
214
110
|
PLATFORMS
|
215
111
|
arm64-darwin-22
|
@@ -219,21 +115,21 @@ PLATFORMS
|
|
219
115
|
x86_64-linux
|
220
116
|
|
221
117
|
DEPENDENCIES
|
222
|
-
minitest (
|
118
|
+
minitest (~> 5.25)
|
223
119
|
minitest-reporters (~> 1.7)
|
224
120
|
pgtk!
|
225
|
-
rack (
|
226
|
-
rake (
|
227
|
-
|
228
|
-
rubocop (= 1.72.2)
|
121
|
+
rack (~> 3.1)
|
122
|
+
rake (~> 13.2)
|
123
|
+
rubocop (~> 1.73)
|
229
124
|
rubocop-minitest (> 0)
|
230
125
|
rubocop-performance (> 0)
|
231
126
|
rubocop-rake (> 0)
|
232
127
|
rubocop-rspec (> 0)
|
233
|
-
simplecov (
|
128
|
+
simplecov (~> 0.22)
|
234
129
|
simplecov-cobertura (~> 2.1)
|
130
|
+
timeout (> 0)
|
235
131
|
xcop (> 0)
|
236
|
-
yard (
|
132
|
+
yard (~> 0.9)
|
237
133
|
|
238
134
|
BUNDLED WITH
|
239
135
|
2.5.16
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# Ruby + PostgreSQL + Liquibase + Rake
|
2
2
|
|
3
3
|
[](https://www.elegantobjects.org)
|
4
|
-
[](https://www.rultor.com/p/yegor256/pgtk)
|
5
5
|
[](https://www.jetbrains.com/ruby/)
|
6
6
|
|
7
7
|
[](https://github.com/yegor256/pgtk/actions/workflows/rake.yml)
|
8
|
-
[](
|
8
|
+
[](https://www.0pdd.com/p?name=yegor256/pgtk)
|
9
|
+
[](https://badge.fury.io/rb/pgtk)
|
10
10
|
[](https://codeclimate.com/github/yegor256/pgtk/maintainability)
|
11
11
|
[](https://github.com/yegor256/pgtk/blob/master/LICENSE.txt)
|
12
12
|
[](https://codecov.io/github/yegor256/pgtk?branch=master)
|
@@ -50,6 +50,7 @@ Pgtk::PgsqlTask.new :pgsql do |t|
|
|
50
50
|
t.password = 'test'
|
51
51
|
t.dbname = 'test'
|
52
52
|
t.yaml = 'target/pgsql-config.yml' # YAML file to be created with connection details
|
53
|
+
t.contexts = '!test' # list of contexts or empty if all
|
53
54
|
t.config = { # list of PostgreSQL configuration options
|
54
55
|
log_min_messages: 'ERROR',
|
55
56
|
log_filename: 'target/pg.log'
|
@@ -98,7 +99,7 @@ bundle exec rake pgsql liquibase
|
|
98
99
|
|
99
100
|
A temporary PostgreSQL server will be started and the entire set of
|
100
101
|
Liquibase SQL changes will be applied. You will be able to connect
|
101
|
-
to it from your application, using the file `target/config.yml`.
|
102
|
+
to it from your application, using the file `target/pgsql-config.yml`.
|
102
103
|
|
103
104
|
From inside your app you may find this class useful:
|
104
105
|
|
@@ -122,7 +123,7 @@ Now you can fetch some data from the DB:
|
|
122
123
|
name = pgsql.exec('SELECT name FROM user WHERE id = $1', [id])[0]['name']
|
123
124
|
```
|
124
125
|
|
125
|
-
You may also use it
|
126
|
+
You may also use it when you need to run a transaction:
|
126
127
|
|
127
128
|
```ruby
|
128
129
|
pgsql.transaction do |t|
|
@@ -131,7 +132,7 @@ pgsql.transaction do |t|
|
|
131
132
|
end
|
132
133
|
```
|
133
134
|
|
134
|
-
To make your PostgreSQL database visible in your unit
|
135
|
+
To make your PostgreSQL database visible in your unit tests, I would
|
135
136
|
recommend you create a method `test_pgsql` in your `test__helper.rb` file
|
136
137
|
(which is `required` in all unit tests) and implement it like this:
|
137
138
|
|
@@ -142,7 +143,6 @@ require 'pgtk/pool'
|
|
142
143
|
module Minitest
|
143
144
|
class Test
|
144
145
|
def test_pgsql
|
145
|
-
config = YAML.load_file()
|
146
146
|
@@test_pgsql ||= Pgtk::Pool.new(
|
147
147
|
Pgtk::Wire::Yaml.new('target/pgsql-config.yml')
|
148
148
|
).start
|
@@ -151,7 +151,7 @@ module Minitest
|
|
151
151
|
end
|
152
152
|
```
|
153
153
|
|
154
|
-
You can also track all SQL queries sent through, with the help of `Pgtk::
|
154
|
+
You can also track all SQL queries sent through the pool, with the help of `Pgtk::Spy`:
|
155
155
|
|
156
156
|
```ruby
|
157
157
|
require 'pgtk/spy'
|
data/REUSE.toml
CHANGED
@@ -4,13 +4,31 @@
|
|
4
4
|
version = 1
|
5
5
|
[[annotations]]
|
6
6
|
path = [
|
7
|
+
".DS_Store",
|
7
8
|
".gitattributes",
|
8
9
|
".gitignore",
|
9
|
-
".gitleaksignore",
|
10
10
|
".pdd",
|
11
|
+
"**.json",
|
12
|
+
"**.md",
|
13
|
+
"**.png",
|
14
|
+
"**.txt",
|
15
|
+
"**/.DS_Store",
|
16
|
+
"**/.gitignore",
|
17
|
+
"**/.pdd",
|
18
|
+
"**/*.csv",
|
19
|
+
"**/*.jpg",
|
20
|
+
"**/*.json",
|
21
|
+
"**/*.md",
|
22
|
+
"**/*.pdf",
|
23
|
+
"**/*.png",
|
24
|
+
"**/*.svg",
|
25
|
+
"**/*.txt",
|
26
|
+
"**/*.vm",
|
27
|
+
"**/CNAME",
|
28
|
+
"**/Gemfile.lock",
|
11
29
|
"Gemfile.lock",
|
12
30
|
"README.md",
|
13
|
-
"renovate.json"
|
31
|
+
"renovate.json",
|
14
32
|
]
|
15
33
|
precedence = "override"
|
16
34
|
SPDX-FileCopyrightText = "Copyright (c) 2025 Yegor Bugayenko"
|
data/Rakefile
CHANGED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'timeout'
|
7
|
+
require_relative '../pgtk'
|
8
|
+
|
9
|
+
# Impatient is a decorator for Pool that enforces timeouts on all database operations.
|
10
|
+
# It ensures that SQL queries don't run indefinitely, which helps prevent application
|
11
|
+
# hangs and resource exhaustion when database operations are slow or stalled.
|
12
|
+
#
|
13
|
+
# This class implements the same interface as Pool but wraps each database operation
|
14
|
+
# in a timeout block. If a query exceeds the specified timeout, it raises a Timeout::Error
|
15
|
+
# exception, allowing the application to handle slow queries gracefully.
|
16
|
+
#
|
17
|
+
# Basic usage:
|
18
|
+
#
|
19
|
+
# # Create and configure a regular pool
|
20
|
+
# pool = Pgtk::Pool.new(wire).start(4)
|
21
|
+
#
|
22
|
+
# # Wrap the pool in an impatient decorator with a 2-second timeout
|
23
|
+
# impatient = Pgtk::Impatient.new(pool, 2)
|
24
|
+
#
|
25
|
+
# # Execute queries with automatic timeout enforcement
|
26
|
+
# begin
|
27
|
+
# impatient.exec('SELECT * FROM large_table WHERE complex_condition')
|
28
|
+
# rescue Timeout::Error
|
29
|
+
# puts "Query timed out after 2 seconds"
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Transactions also enforce timeouts on each query
|
33
|
+
# begin
|
34
|
+
# impatient.transaction do |t|
|
35
|
+
# t.exec('UPDATE large_table SET processed = true')
|
36
|
+
# t.exec('DELETE FROM queue WHERE processed = true')
|
37
|
+
# end
|
38
|
+
# rescue Timeout::Error
|
39
|
+
# puts "Transaction timed out"
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # Combining with Spy for timeout monitoring
|
43
|
+
# spy = Pgtk::Spy.new(impatient) do |sql, duration|
|
44
|
+
# puts "Query completed in #{duration} seconds: #{sql}"
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# # Now queries are both timed and monitored
|
48
|
+
# spy.exec('SELECT * FROM users')
|
49
|
+
#
|
50
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
51
|
+
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
52
|
+
# License:: MIT
|
53
|
+
class Pgtk::Impatient
|
54
|
+
# Constructor.
|
55
|
+
#
|
56
|
+
# @param [Pgtk::Pool] pool The pool to decorate
|
57
|
+
# @param [Integer] timeout Timeout in seconds for each SQL query
|
58
|
+
def initialize(pool, timeout = 1)
|
59
|
+
@pool = pool
|
60
|
+
@timeout = timeout
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get the version of PostgreSQL server.
|
64
|
+
#
|
65
|
+
# @return [String] Version of PostgreSQL server
|
66
|
+
def version
|
67
|
+
@pool.version
|
68
|
+
end
|
69
|
+
|
70
|
+
# Execute a SQL query with a timeout.
|
71
|
+
#
|
72
|
+
# @param [String] sql The SQL query with params inside (possibly)
|
73
|
+
# @param [Array] args List of arguments
|
74
|
+
# @return [Array] Result rows
|
75
|
+
# @raise [Timeout::Error] If the query takes too long
|
76
|
+
def exec(sql, *args)
|
77
|
+
Timeout.timeout(@timeout) do
|
78
|
+
@pool.exec(sql, *args)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Run a transaction with a timeout for each query.
|
83
|
+
#
|
84
|
+
# @yield [Pgtk::Impatient] Yields an impatient transaction
|
85
|
+
# @return [Object] Result of the block
|
86
|
+
def transaction
|
87
|
+
@pool.transaction do |t|
|
88
|
+
yield Pgtk::Impatient.new(t, @timeout)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/pgtk/liquibase_task.rb
CHANGED
@@ -16,12 +16,43 @@ require_relative '../pgtk'
|
|
16
16
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
17
17
|
# License:: MIT
|
18
18
|
class Pgtk::LiquibaseTask < Rake::TaskLib
|
19
|
-
|
19
|
+
# Task name
|
20
|
+
# @return [Symbol]
|
21
|
+
attr_accessor :name
|
20
22
|
|
23
|
+
# Path to Liquibase master XML file
|
24
|
+
# @return [String]
|
25
|
+
attr_accessor :master
|
26
|
+
|
27
|
+
# Path to YAML file with PostgreSQL connection details
|
28
|
+
# @return [String, Array<String>]
|
29
|
+
attr_accessor :yaml
|
30
|
+
|
31
|
+
# Whether to suppress output
|
32
|
+
# @return [Boolean]
|
33
|
+
attr_accessor :quiet
|
34
|
+
|
35
|
+
# Liquibase version to use
|
36
|
+
# @return [String]
|
37
|
+
attr_accessor :liquibase_version
|
38
|
+
|
39
|
+
# PostgreSQL JDBC driver version to use
|
40
|
+
# @return [String]
|
41
|
+
attr_accessor :postgresql_version
|
42
|
+
|
43
|
+
# Liquibase contexts to apply
|
44
|
+
# @return [String]
|
45
|
+
attr_accessor :contexts
|
46
|
+
|
47
|
+
# Initialize a new Liquibase task.
|
48
|
+
#
|
49
|
+
# @param [Array] args Task arguments
|
50
|
+
# @yield [Pgtk::LiquibaseTask, Object] Yields self and task arguments
|
21
51
|
def initialize(*args, &task_block)
|
22
52
|
super()
|
23
53
|
@name = args.shift || :liquibase
|
24
54
|
@quiet = false
|
55
|
+
@contexts = ''
|
25
56
|
@liquibase_version = '3.2.2'
|
26
57
|
@postgresql_version = '42.7.0'
|
27
58
|
desc 'Deploy Liquibase changes to the running PostgreSQL server' unless ::Rake.application.last_description
|
@@ -83,7 +114,9 @@ class Pgtk::LiquibaseTask < Rake::TaskLib
|
|
83
114
|
'--define',
|
84
115
|
Shellwords.escape("liquibase.url=#{url}"),
|
85
116
|
'--define',
|
86
|
-
Shellwords.escape("liquibase.password=#{password}")
|
117
|
+
Shellwords.escape("liquibase.password=#{password}"),
|
118
|
+
'--define',
|
119
|
+
Shellwords.escape("liquibase.contexts=#{@contexts}")
|
87
120
|
]
|
88
121
|
)
|
89
122
|
end
|
data/lib/pgtk/pgsql_task.rb
CHANGED
@@ -19,8 +19,50 @@ require_relative '../pgtk'
|
|
19
19
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
20
20
|
# License:: MIT
|
21
21
|
class Pgtk::PgsqlTask < Rake::TaskLib
|
22
|
-
|
22
|
+
# Task name
|
23
|
+
# @return [Symbol]
|
24
|
+
attr_accessor :name
|
23
25
|
|
26
|
+
# Directory where PostgreSQL server files will be stored
|
27
|
+
# @return [String]
|
28
|
+
attr_accessor :dir
|
29
|
+
|
30
|
+
# Whether to delete the PostgreSQL data directory on each run
|
31
|
+
# @return [Boolean]
|
32
|
+
attr_accessor :fresh_start
|
33
|
+
|
34
|
+
# PostgreSQL username
|
35
|
+
# @return [String]
|
36
|
+
attr_accessor :user
|
37
|
+
|
38
|
+
# PostgreSQL password
|
39
|
+
# @return [String]
|
40
|
+
attr_accessor :password
|
41
|
+
|
42
|
+
# PostgreSQL database name
|
43
|
+
# @return [String]
|
44
|
+
attr_accessor :dbname
|
45
|
+
|
46
|
+
# Path to YAML file where configuration will be written
|
47
|
+
# @return [String]
|
48
|
+
attr_accessor :yaml
|
49
|
+
|
50
|
+
# Whether to suppress output
|
51
|
+
# @return [Boolean]
|
52
|
+
attr_accessor :quiet
|
53
|
+
|
54
|
+
# TCP port for PostgreSQL server (random if nil)
|
55
|
+
# @return [Integer, nil]
|
56
|
+
attr_accessor :port
|
57
|
+
|
58
|
+
# Configuration options for PostgreSQL server
|
59
|
+
# @return [Hash]
|
60
|
+
attr_accessor :config
|
61
|
+
|
62
|
+
# Initialize a new PostgreSQL server task.
|
63
|
+
#
|
64
|
+
# @param [Array] args Task arguments
|
65
|
+
# @yield [Pgtk::PgsqlTask, Object] Yields self and task arguments
|
24
66
|
def initialize(*args, &task_block)
|
25
67
|
super()
|
26
68
|
@name = args.shift || :pgsql
|
data/lib/pgtk/pool.rb
CHANGED
@@ -8,7 +8,40 @@ require 'loog'
|
|
8
8
|
require_relative '../pgtk'
|
9
9
|
require_relative 'wire'
|
10
10
|
|
11
|
-
# Pool.
|
11
|
+
# Pool provides a connection pool for PostgreSQL database connections.
|
12
|
+
# It manages a fixed number of connections to optimize performance and
|
13
|
+
# resource usage while providing a simple interface for database operations.
|
14
|
+
#
|
15
|
+
# The Pool class handles connection lifecycle, reconnects on errors,
|
16
|
+
# and provides transaction support. It's the core class for interacting
|
17
|
+
# with a PostgreSQL database in this library.
|
18
|
+
#
|
19
|
+
# Basic usage:
|
20
|
+
#
|
21
|
+
# # Create a wire that knows how to connect to PostgreSQL
|
22
|
+
# wire = Pgtk::Wire::Direct.new(
|
23
|
+
# host: 'localhost',
|
24
|
+
# port: 5432,
|
25
|
+
# dbname: 'mydatabase',
|
26
|
+
# user: 'postgres',
|
27
|
+
# password: 'secret'
|
28
|
+
# )
|
29
|
+
#
|
30
|
+
# # Create and start a connection pool with 4 connections
|
31
|
+
# pool = Pgtk::Pool.new(wire).start(4)
|
32
|
+
#
|
33
|
+
# # Execute a simple query
|
34
|
+
# pool.exec('SELECT * FROM users')
|
35
|
+
#
|
36
|
+
# # Execute a parameterized query
|
37
|
+
# pool.exec('SELECT * FROM users WHERE email = $1', ['user@example.com'])
|
38
|
+
#
|
39
|
+
# # Use transactions for multiple operations
|
40
|
+
# pool.transaction do |t|
|
41
|
+
# t.exec('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [100, 42])
|
42
|
+
# t.exec('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [100, 43])
|
43
|
+
# end
|
44
|
+
#
|
12
45
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
13
46
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
14
47
|
# License:: MIT
|
data/lib/pgtk/spy.rb
CHANGED
@@ -8,20 +8,65 @@ require 'loog'
|
|
8
8
|
require_relative '../pgtk'
|
9
9
|
require_relative 'wire'
|
10
10
|
|
11
|
-
#
|
11
|
+
# Spy is a decorator for Pool that intercepts and tracks SQL queries.
|
12
|
+
# It provides observability into database operations by invoking a callback
|
13
|
+
# with the SQL query and its execution time for each database operation.
|
14
|
+
#
|
15
|
+
# This class implements the same interface as Pool, but adds instrumentation
|
16
|
+
# functionality while delegating actual database operations to the decorated pool.
|
17
|
+
# Use Spy for debugging, performance monitoring, or audit logging.
|
18
|
+
#
|
19
|
+
# Basic usage:
|
20
|
+
#
|
21
|
+
# # Create and configure a regular pool
|
22
|
+
# pool = Pgtk::Pool.new(wire).start(4)
|
23
|
+
#
|
24
|
+
# # Wrap the pool in a spy that tracks all executed queries
|
25
|
+
# queries = []
|
26
|
+
# spy = Pgtk::Spy.new(pool) do |sql, duration|
|
27
|
+
# puts "Query: #{sql}"
|
28
|
+
# puts "Duration: #{duration} seconds"
|
29
|
+
# queries << sql
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Use the spy just like a regular pool, with automatic tracking
|
33
|
+
# spy.exec('SELECT * FROM users')
|
34
|
+
#
|
35
|
+
# # Transactions also track each query inside the transaction
|
36
|
+
# spy.transaction do |t|
|
37
|
+
# t.exec('UPDATE users SET active = true WHERE id = $1', [42])
|
38
|
+
# t.exec('INSERT INTO audit_log (user_id, action) VALUES ($1, $2)', [42, 'activated'])
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # Examine collected queries for analysis
|
42
|
+
# puts "Total queries: #{queries.size}"
|
43
|
+
# puts "First query: #{queries.first}"
|
44
|
+
#
|
12
45
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
13
46
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
14
47
|
# License:: MIT
|
15
48
|
class Pgtk::Spy
|
49
|
+
# Constructor.
|
50
|
+
#
|
51
|
+
# @param [Pgtk::Pool] pool The pool to spy on
|
52
|
+
# @yield [String, Float] Yields the SQL query and execution time
|
16
53
|
def initialize(pool, &block)
|
17
54
|
@pool = pool
|
18
55
|
@block = block
|
19
56
|
end
|
20
57
|
|
58
|
+
# Get the version of PostgreSQL server.
|
59
|
+
#
|
60
|
+
# @return [String] Version of PostgreSQL server
|
21
61
|
def version
|
22
62
|
@pool.version
|
23
63
|
end
|
24
64
|
|
65
|
+
# Execute a SQL query and track its execution.
|
66
|
+
#
|
67
|
+
# @param [String] sql The SQL query with params inside (possibly)
|
68
|
+
# @param [Array] args List of arguments
|
69
|
+
# @return [Array] Result rows
|
25
70
|
def exec(sql, *args)
|
26
71
|
start = Time.now
|
27
72
|
ret = @pool.exec(sql, *args)
|
@@ -29,6 +74,10 @@ class Pgtk::Spy
|
|
29
74
|
ret
|
30
75
|
end
|
31
76
|
|
77
|
+
# Run a transaction with spying on each SQL query.
|
78
|
+
#
|
79
|
+
# @yield [Pgtk::Spy] Yields a spy transaction
|
80
|
+
# @return [Object] Result of the block
|
32
81
|
def transaction
|
33
82
|
@pool.transaction do |t|
|
34
83
|
yield Pgtk::Spy.new(t, &@block)
|
data/lib/pgtk/version.rb
CHANGED
data/lib/pgtk/wire.rb
CHANGED
@@ -21,10 +21,16 @@ end
|
|
21
21
|
# License:: MIT
|
22
22
|
class Pgtk::Wire::Direct
|
23
23
|
# Constructor.
|
24
|
+
#
|
25
|
+
# @param [String] host Host name of the PostgreSQL server
|
26
|
+
# @param [Integer] port Port number of the PostgreSQL server
|
27
|
+
# @param [String] dbname Database name
|
28
|
+
# @param [String] user Username
|
29
|
+
# @param [String] password Password
|
24
30
|
def initialize(host:, port:, dbname:, user:, password:)
|
25
31
|
raise "The host can't be nil" if host.nil?
|
26
32
|
@host = host
|
27
|
-
raise "The
|
33
|
+
raise "The port can't be nil" if port.nil?
|
28
34
|
@port = port
|
29
35
|
@dbname = dbname
|
30
36
|
@user = user
|
@@ -46,8 +52,10 @@ end
|
|
46
52
|
# License:: MIT
|
47
53
|
class Pgtk::Wire::Env
|
48
54
|
# Constructor.
|
55
|
+
#
|
56
|
+
# @param [String] var The name of the environment variable with the connection URL
|
49
57
|
def initialize(var = 'DATABASE_URL')
|
50
|
-
raise "The name of the
|
58
|
+
raise "The name of the environment variable can't be nil" if var.nil?
|
51
59
|
@var = var
|
52
60
|
end
|
53
61
|
|
@@ -72,6 +80,9 @@ end
|
|
72
80
|
# License:: MIT
|
73
81
|
class Pgtk::Wire::Yaml
|
74
82
|
# Constructor.
|
83
|
+
#
|
84
|
+
# @param [String] file Path to the YAML configuration file
|
85
|
+
# @param [String] node The root node name in the YAML file containing PostgreSQL configuration
|
75
86
|
def initialize(file, node = 'pgsql')
|
76
87
|
raise "The name of the file can't be nil" if file.nil?
|
77
88
|
@file = file
|
@@ -83,12 +94,13 @@ class Pgtk::Wire::Yaml
|
|
83
94
|
def connection
|
84
95
|
raise "The file #{@file.inspect} not found" unless File.exist?(@file)
|
85
96
|
cfg = YAML.load_file(@file)
|
97
|
+
raise "The node '#{@node}' not found in YAML file #{@file.inspect}" unless cfg[@node]
|
86
98
|
Pgtk::Wire::Direct.new(
|
87
|
-
host: cfg[
|
88
|
-
port: cfg[
|
89
|
-
dbname: cfg[
|
90
|
-
user: cfg[
|
91
|
-
password: cfg[
|
99
|
+
host: cfg[@node]['host'],
|
100
|
+
port: cfg[@node]['port'],
|
101
|
+
dbname: cfg[@node]['dbname'],
|
102
|
+
user: cfg[@node]['user'],
|
103
|
+
password: cfg[@node]['password']
|
92
104
|
).connection
|
93
105
|
end
|
94
106
|
end
|
data/resources/pom.xml
CHANGED
data/test/test__helper.rb
CHANGED
@@ -6,13 +6,62 @@
|
|
6
6
|
$stdout.sync = true
|
7
7
|
|
8
8
|
require 'simplecov'
|
9
|
-
SimpleCov.start
|
10
|
-
|
11
9
|
require 'simplecov-cobertura'
|
12
|
-
SimpleCov.
|
10
|
+
unless SimpleCov.running || ENV['PICKS']
|
11
|
+
SimpleCov.command_name('test')
|
12
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
13
|
+
[
|
14
|
+
SimpleCov::Formatter::HTMLFormatter,
|
15
|
+
SimpleCov::Formatter::CoberturaFormatter
|
16
|
+
]
|
17
|
+
)
|
18
|
+
SimpleCov.minimum_coverage 90
|
19
|
+
SimpleCov.minimum_coverage_by_file 70
|
20
|
+
SimpleCov.start do
|
21
|
+
add_filter 'test/'
|
22
|
+
add_filter 'vendor/'
|
23
|
+
add_filter 'target/'
|
24
|
+
track_files 'lib/**/*.rb'
|
25
|
+
track_files '*.rb'
|
26
|
+
end
|
27
|
+
end
|
13
28
|
|
29
|
+
require 'minitest/autorun'
|
14
30
|
require 'minitest/reporters'
|
15
31
|
Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
|
16
32
|
|
17
|
-
require '
|
33
|
+
require 'loog'
|
34
|
+
require 'rake'
|
35
|
+
require 'rake/tasklib'
|
18
36
|
require_relative '../lib/pgtk'
|
37
|
+
require_relative '../lib/pgtk/liquibase_task'
|
38
|
+
require_relative '../lib/pgtk/pgsql_task'
|
39
|
+
|
40
|
+
class Pgtk::Test < Minitest::Test
|
41
|
+
def bootstrap(log: Loog::NULL)
|
42
|
+
Dir.mktmpdir 'test' do |dir|
|
43
|
+
id = rand(100..999)
|
44
|
+
Pgtk::PgsqlTask.new("pgsql#{id}") do |t|
|
45
|
+
t.dir = File.join(dir, 'pgsql')
|
46
|
+
t.user = 'hello'
|
47
|
+
t.password = 'A B C привет ! & | !'
|
48
|
+
t.dbname = 'test'
|
49
|
+
t.yaml = File.join(dir, 'cfg.yml')
|
50
|
+
t.quiet = true
|
51
|
+
end
|
52
|
+
Rake::Task["pgsql#{id}"].invoke
|
53
|
+
Pgtk::LiquibaseTask.new("liquibase#{id}") do |t|
|
54
|
+
t.master = File.join(__dir__, '../test-resources/master.xml')
|
55
|
+
t.yaml = File.join(dir, 'cfg.yml')
|
56
|
+
t.quiet = true
|
57
|
+
end
|
58
|
+
Rake::Task["liquibase#{id}"].invoke
|
59
|
+
pool = Pgtk::Pool.new(
|
60
|
+
Pgtk::Wire::Yaml.new(File.join(dir, 'cfg.yml')),
|
61
|
+
log: log
|
62
|
+
)
|
63
|
+
pool.start(1)
|
64
|
+
yield pool
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'loog'
|
7
|
+
require 'pg'
|
8
|
+
require 'qbash'
|
9
|
+
require 'rake'
|
10
|
+
require 'tmpdir'
|
11
|
+
require 'yaml'
|
12
|
+
require_relative 'test__helper'
|
13
|
+
require_relative '../lib/pgtk/pool'
|
14
|
+
require_relative '../lib/pgtk/impatient'
|
15
|
+
|
16
|
+
# Pool test.
|
17
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
18
|
+
# Copyright:: Copyright (c) 2017-2025 Yegor Bugayenko
|
19
|
+
# License:: MIT
|
20
|
+
class TestImpatient < Pgtk::Test
|
21
|
+
def test_doesnt_interrupt
|
22
|
+
bootstrap do |pool|
|
23
|
+
id = Pgtk::Impatient.new(pool).exec(
|
24
|
+
'INSERT INTO book (title) VALUES ($1) RETURNING id',
|
25
|
+
['1984']
|
26
|
+
).first['id'].to_i
|
27
|
+
assert_predicate(id, :positive?)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/test/test_liquibase_task.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
|
-
require 'minitest/autorun'
|
7
6
|
require 'tmpdir'
|
8
7
|
require 'rake'
|
9
8
|
require 'yaml'
|
9
|
+
require_relative 'test__helper'
|
10
10
|
require_relative '../lib/pgtk/pgsql_task'
|
11
11
|
require_relative '../lib/pgtk/liquibase_task'
|
12
12
|
|
@@ -14,7 +14,7 @@ require_relative '../lib/pgtk/liquibase_task'
|
|
14
14
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
15
15
|
# Copyright:: Copyright (c) 2017-2025 Yegor Bugayenko
|
16
16
|
# License:: MIT
|
17
|
-
class TestLiquibaseTask <
|
17
|
+
class TestLiquibaseTask < Pgtk::Test
|
18
18
|
def test_basic
|
19
19
|
Dir.mktmpdir 'test' do |dir|
|
20
20
|
Pgtk::PgsqlTask.new(:pgsql2) do |t|
|
@@ -32,6 +32,7 @@ class TestLiquibaseTask < Minitest::Test
|
|
32
32
|
t.quiet = true
|
33
33
|
t.postgresql_version = '42.7.0'
|
34
34
|
t.liquibase_version = '3.2.2'
|
35
|
+
t.contexts = '!test'
|
35
36
|
end
|
36
37
|
Rake::Task['liquibase2'].invoke
|
37
38
|
end
|
data/test/test_pgsql_task.rb
CHANGED
@@ -3,17 +3,17 @@
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
|
-
require 'minitest/autorun'
|
7
6
|
require 'rake'
|
8
7
|
require 'tmpdir'
|
9
8
|
require 'yaml'
|
9
|
+
require_relative 'test__helper'
|
10
10
|
require_relative '../lib/pgtk/pgsql_task'
|
11
11
|
|
12
12
|
# Pgsql rake task test.
|
13
13
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
14
14
|
# Copyright:: Copyright (c) 2017-2025 Yegor Bugayenko
|
15
15
|
# License:: MIT
|
16
|
-
class TestPgsqlTask <
|
16
|
+
class TestPgsqlTask < Pgtk::Test
|
17
17
|
def test_basic
|
18
18
|
Dir.mktmpdir 'test' do |dir|
|
19
19
|
Pgtk::PgsqlTask.new(:p2) do |t|
|
data/test/test_pool.rb
CHANGED
@@ -4,12 +4,12 @@
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
6
|
require 'loog'
|
7
|
-
require 'minitest/autorun'
|
8
7
|
require 'pg'
|
9
8
|
require 'qbash'
|
10
9
|
require 'rake'
|
11
10
|
require 'tmpdir'
|
12
11
|
require 'yaml'
|
12
|
+
require_relative 'test__helper'
|
13
13
|
require_relative '../lib/pgtk/liquibase_task'
|
14
14
|
require_relative '../lib/pgtk/pgsql_task'
|
15
15
|
require_relative '../lib/pgtk/pool'
|
@@ -19,7 +19,7 @@ require_relative '../lib/pgtk/spy'
|
|
19
19
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
20
20
|
# Copyright:: Copyright (c) 2017-2025 Yegor Bugayenko
|
21
21
|
# License:: MIT
|
22
|
-
class TestPool <
|
22
|
+
class TestPool < Pgtk::Test
|
23
23
|
def test_reads_version
|
24
24
|
bootstrap do |pool|
|
25
25
|
ver = pool.version
|
@@ -181,33 +181,4 @@ class TestPool < Minitest::Test
|
|
181
181
|
end
|
182
182
|
end
|
183
183
|
end
|
184
|
-
|
185
|
-
private
|
186
|
-
|
187
|
-
def bootstrap(log: Loog::NULL)
|
188
|
-
Dir.mktmpdir 'test' do |dir|
|
189
|
-
id = rand(100..999)
|
190
|
-
Pgtk::PgsqlTask.new("pgsql#{id}") do |t|
|
191
|
-
t.dir = File.join(dir, 'pgsql')
|
192
|
-
t.user = 'hello'
|
193
|
-
t.password = 'A B C привет ! & | !'
|
194
|
-
t.dbname = 'test'
|
195
|
-
t.yaml = File.join(dir, 'cfg.yml')
|
196
|
-
t.quiet = true
|
197
|
-
end
|
198
|
-
Rake::Task["pgsql#{id}"].invoke
|
199
|
-
Pgtk::LiquibaseTask.new("liquibase#{id}") do |t|
|
200
|
-
t.master = File.join(__dir__, '../test-resources/master.xml')
|
201
|
-
t.yaml = File.join(dir, 'cfg.yml')
|
202
|
-
t.quiet = true
|
203
|
-
end
|
204
|
-
Rake::Task["liquibase#{id}"].invoke
|
205
|
-
pool = Pgtk::Pool.new(
|
206
|
-
Pgtk::Wire::Yaml.new(File.join(dir, 'cfg.yml')),
|
207
|
-
log: log
|
208
|
-
)
|
209
|
-
pool.start(1)
|
210
|
-
yield pool
|
211
|
-
end
|
212
|
-
end
|
213
184
|
end
|
data/test-resources/master.xml
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgtk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
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:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: backtrace
|
@@ -87,8 +86,8 @@ email: yegor256@gmail.com
|
|
87
86
|
executables: []
|
88
87
|
extensions: []
|
89
88
|
extra_rdoc_files:
|
90
|
-
- README.md
|
91
89
|
- LICENSE.txt
|
90
|
+
- README.md
|
92
91
|
files:
|
93
92
|
- ".0pdd.yml"
|
94
93
|
- ".gitattributes"
|
@@ -100,13 +99,13 @@ files:
|
|
100
99
|
- ".github/workflows/pdd.yml"
|
101
100
|
- ".github/workflows/rake.yml"
|
102
101
|
- ".github/workflows/reuse.yml"
|
102
|
+
- ".github/workflows/typos.yml"
|
103
103
|
- ".github/workflows/xcop.yml"
|
104
104
|
- ".github/workflows/yamllint.yml"
|
105
105
|
- ".gitignore"
|
106
106
|
- ".pdd"
|
107
107
|
- ".rubocop.yml"
|
108
108
|
- ".rultor.yml"
|
109
|
-
- ".simplecov"
|
110
109
|
- ".yamllint.yml"
|
111
110
|
- Gemfile
|
112
111
|
- Gemfile.lock
|
@@ -117,6 +116,7 @@ files:
|
|
117
116
|
- Rakefile
|
118
117
|
- cucumber.yml
|
119
118
|
- lib/pgtk.rb
|
119
|
+
- lib/pgtk/impatient.rb
|
120
120
|
- lib/pgtk/liquibase_task.rb
|
121
121
|
- lib/pgtk/pgsql_task.rb
|
122
122
|
- lib/pgtk/pool.rb
|
@@ -129,6 +129,7 @@ files:
|
|
129
129
|
- test-resources/2019/01-test.xml
|
130
130
|
- test-resources/master.xml
|
131
131
|
- test/test__helper.rb
|
132
|
+
- test/test_impatient.rb
|
132
133
|
- test/test_liquibase_task.rb
|
133
134
|
- test/test_pgsql_task.rb
|
134
135
|
- test/test_pool.rb
|
@@ -137,7 +138,6 @@ licenses:
|
|
137
138
|
- MIT
|
138
139
|
metadata:
|
139
140
|
rubygems_mfa_required: 'true'
|
140
|
-
post_install_message:
|
141
141
|
rdoc_options:
|
142
142
|
- "--charset=UTF-8"
|
143
143
|
require_paths:
|
@@ -153,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '0'
|
155
155
|
requirements: []
|
156
|
-
rubygems_version: 3.
|
157
|
-
signing_key:
|
156
|
+
rubygems_version: 3.6.7
|
158
157
|
specification_version: 4
|
159
158
|
summary: PostgreSQL ToolKit for Ruby apps
|
160
159
|
test_files: []
|
data/.simplecov
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
|
-
if Gem.win_platform?
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
8
|
-
SimpleCov::Formatter::HTMLFormatter
|
9
|
-
]
|
10
|
-
SimpleCov.start do
|
11
|
-
add_filter '/test/'
|
12
|
-
add_filter '/features/'
|
13
|
-
end
|
14
|
-
else
|
15
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
16
|
-
[SimpleCov::Formatter::HTMLFormatter]
|
17
|
-
)
|
18
|
-
SimpleCov.start do
|
19
|
-
add_filter '/test/'
|
20
|
-
add_filter '/features/'
|
21
|
-
minimum_coverage 60
|
22
|
-
end
|
23
|
-
end
|