pg-locks-monitor 0.2.2 → 0.3.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 +4 -4
- data/.github/workflows/ci.yml +26 -16
- data/Rakefile +1 -1
- data/docker-compose.yml.sample +0 -2
- data/lib/pg-locks-monitor.rb +28 -4
- data/lib/pg_locks_monitor/version.rb +1 -1
- data/pg-locks-monitor.gemspec +1 -1
- data/spec/default_notifier_spec.rb +19 -15
- data/spec/smoke_spec.rb +26 -0
- data/spec/spec_helper.rb +28 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 609f63093dd3729e2b05577d39d55d13a09cfeb78dadc185e3cd1bbeff15a5eb
|
4
|
+
data.tar.gz: 29bb4e5292296c81338ac5250efbc8e85927cdb8ede8354f0e4300b96bca7528
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50377aa6446f17e900a28d427a0c6fc734ab78e29934f73af50d7957d3f81228515abb236964c1b6d5e866c5fad001eda0853f13d5aeb0a3cb540d70c7cd0011
|
7
|
+
data.tar.gz: 782c10cf04da3cbf8ec325cb15680f90bbea646344df1e5e1a1e72125781279f98321f1cce41c6c5d7da60dd59cfaa04a04eadff3233ebe0a282202808fd308e
|
data/.github/workflows/ci.yml
CHANGED
@@ -48,7 +48,15 @@ jobs:
|
|
48
48
|
docker run --env POSTGRES_USER=postgres \
|
49
49
|
--env POSTGRES_DB=pg-locks-monitor-test \
|
50
50
|
--env POSTGRES_PASSWORD=secret \
|
51
|
-
-d -p 5436:5432 postgres:15.
|
51
|
+
-d -p 5436:5432 postgres:15.8-alpine \
|
52
|
+
postgres -c shared_preload_libraries=pg_stat_statements
|
53
|
+
sleep 15
|
54
|
+
- name: Run PostgreSQL 16
|
55
|
+
run: |
|
56
|
+
docker run --env POSTGRES_USER=postgres \
|
57
|
+
--env POSTGRES_DB=pg-locks-monitor-test \
|
58
|
+
--env POSTGRES_PASSWORD=secret \
|
59
|
+
-d -p 5437:5432 postgres:16.4-alpine \
|
52
60
|
postgres -c shared_preload_libraries=pg_stat_statements
|
53
61
|
sleep 15
|
54
62
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
@@ -73,17 +81,7 @@ jobs:
|
|
73
81
|
POSTGRES_PASSWORD: secret
|
74
82
|
DATABASE_URL: postgresql://postgres:secret@localhost:5432/pg-locks-monitor-test
|
75
83
|
run: |
|
76
|
-
bundle exec rspec spec
|
77
|
-
- name: Run tests for PG 11
|
78
|
-
env:
|
79
|
-
PG_VERSION: 11
|
80
|
-
POSTGRES_HOST: localhost
|
81
|
-
POSTGRES_USER: postgres
|
82
|
-
POSTGRES_DB: pg-locks-monitor-test
|
83
|
-
POSTGRES_PASSWORD: secret
|
84
|
-
DATABASE_URL: postgresql://postgres:secret@localhost:5432/pg-locks-monitor-test
|
85
|
-
run: |
|
86
|
-
bundle exec rake test_all
|
84
|
+
bundle exec rspec spec
|
87
85
|
- name: Run tests for PG 12
|
88
86
|
env:
|
89
87
|
PG_VERSION: 12
|
@@ -93,7 +91,7 @@ jobs:
|
|
93
91
|
POSTGRES_PASSWORD: secret
|
94
92
|
DATABASE_URL: postgresql://postgres:secret@localhost:5433/pg-locks-monitor-test
|
95
93
|
run: |
|
96
|
-
bundle exec
|
94
|
+
bundle exec rspec spec
|
97
95
|
- name: Run tests for PG 13
|
98
96
|
env:
|
99
97
|
PG_VERSION: 13
|
@@ -103,7 +101,7 @@ jobs:
|
|
103
101
|
POSTGRES_PASSWORD: secret
|
104
102
|
DATABASE_URL: postgresql://postgres:secret@localhost:5434/pg-locks-monitor-test
|
105
103
|
run: |
|
106
|
-
bundle exec
|
104
|
+
bundle exec rspec spec
|
107
105
|
- name: Run tests for PG 14
|
108
106
|
env:
|
109
107
|
PG_VERSION: 14
|
@@ -113,7 +111,7 @@ jobs:
|
|
113
111
|
POSTGRES_PASSWORD: secret
|
114
112
|
DATABASE_URL: postgresql://postgres:secret@localhost:5435/pg-locks-monitor-test
|
115
113
|
run: |
|
116
|
-
bundle exec
|
114
|
+
bundle exec rspec spec
|
117
115
|
- name: Run tests for PG 15
|
118
116
|
env:
|
119
117
|
PG_VERSION: 15
|
@@ -123,5 +121,17 @@ jobs:
|
|
123
121
|
POSTGRES_PASSWORD: secret
|
124
122
|
DATABASE_URL: postgresql://postgres:secret@localhost:5436/pg-locks-monitor-test
|
125
123
|
run: |
|
126
|
-
bundle exec
|
124
|
+
bundle exec rspec spec
|
125
|
+
- name: Run tests for PG 16
|
126
|
+
env:
|
127
|
+
PG_VERSION: 15
|
128
|
+
POSTGRES_HOST: localhost
|
129
|
+
POSTGRES_USER: postgres
|
130
|
+
POSTGRES_DB: pg-locks-monitor-test
|
131
|
+
POSTGRES_PASSWORD: secret
|
132
|
+
DATABASE_URL: postgresql://postgres:secret@localhost:5437/pg-locks-monitor-test
|
133
|
+
run: |
|
134
|
+
bundle exec rspec spec
|
135
|
+
|
136
|
+
|
127
137
|
|
data/Rakefile
CHANGED
@@ -5,5 +5,5 @@ RSpec::Core::RakeTask.new(:spec)
|
|
5
5
|
|
6
6
|
desc "Test all PG versions"
|
7
7
|
task :test_all do
|
8
|
-
system("PG_VERSION=11 bundle exec rspec spec
|
8
|
+
system("PG_VERSION=11 bundle exec rspec spec && PG_VERSION=12 bundle exec rspec spec && PG_VERSION=13 bundle exec rspec spec && PG_VERSION=14 bundle exec rspec spec && PG_VERSION=16 bundle exec rspec spec && PG_VERSION=16 bundle exec rspec spec")
|
9
9
|
end
|
data/docker-compose.yml.sample
CHANGED
data/lib/pg-locks-monitor.rb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
require "uri"
|
4
4
|
require "pg"
|
5
|
-
require "
|
5
|
+
require "rails-pg-extras"
|
6
|
+
require "active_record"
|
6
7
|
|
7
8
|
module PgLocksMonitor
|
8
9
|
def self.snapshot!
|
9
|
-
locks =
|
10
|
+
locks = RailsPgExtras.locks(
|
10
11
|
in_format: :hash,
|
11
12
|
).select do |lock|
|
12
13
|
if (age = lock.fetch("age"))
|
@@ -19,14 +20,21 @@ module PgLocksMonitor
|
|
19
20
|
configuration.notifier_class.call(locks)
|
20
21
|
end
|
21
22
|
|
22
|
-
blocking =
|
23
|
-
(
|
23
|
+
blocking = RailsPgExtras.blocking(in_format: :hash).select do |block|
|
24
|
+
if (age = block.fetch("blocking_duration"))
|
25
|
+
(ActiveSupport::Duration.parse(age).to_f * 1000) > configuration.locks_min_duration_ms
|
26
|
+
end
|
24
27
|
end.select(&configuration.blocking_filter_proc)
|
25
28
|
.first(configuration.locks_limit)
|
26
29
|
|
27
30
|
if blocking.count > 0 && configuration.monitor_blocking
|
28
31
|
configuration.notifier_class.call(blocking)
|
29
32
|
end
|
33
|
+
|
34
|
+
{
|
35
|
+
locks: locks,
|
36
|
+
blocking: blocking,
|
37
|
+
}
|
30
38
|
end
|
31
39
|
|
32
40
|
def self.configuration
|
@@ -36,6 +44,22 @@ module PgLocksMonitor
|
|
36
44
|
def self.configure
|
37
45
|
yield(configuration)
|
38
46
|
end
|
47
|
+
|
48
|
+
class DurationHelper
|
49
|
+
require "date"
|
50
|
+
|
51
|
+
def self.parse_to_ms(duration_str)
|
52
|
+
time = DateTime.strptime(duration_str, "%H:%M:%S.%N")
|
53
|
+
hours = time.hour
|
54
|
+
minutes = time.minute
|
55
|
+
seconds = time.second
|
56
|
+
nanoseconds = time.second_fraction * (10 ** 9)
|
57
|
+
|
58
|
+
total_ms = (hours * 3600 * 1000) + (minutes * 60 * 1000) + (seconds * 1000) + (nanoseconds / 1_000_000).to_i
|
59
|
+
|
60
|
+
total_ms
|
61
|
+
end
|
62
|
+
end
|
39
63
|
end
|
40
64
|
|
41
65
|
require "pg_locks_monitor/default_notifier"
|
data/pg-locks-monitor.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.test_files = s.files.grep(%r{^(spec)/})
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.license = "MIT"
|
18
|
-
s.add_dependency "
|
18
|
+
s.add_dependency "rails-pg-extras"
|
19
19
|
s.add_dependency "slack-notifier"
|
20
20
|
s.add_development_dependency "rake"
|
21
21
|
s.add_development_dependency "rspec"
|
@@ -3,14 +3,6 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe PgLocksMonitor::DefaultNotifier do
|
6
|
-
before do
|
7
|
-
# Mock Rails and its logger
|
8
|
-
Rails = nil
|
9
|
-
logger_double = double("Logger")
|
10
|
-
allow(logger_double).to receive(:info)
|
11
|
-
allow(Rails).to receive(:logger).and_return(logger_double)
|
12
|
-
end
|
13
|
-
|
14
6
|
it "requires correct config if Slack notifications enabled" do
|
15
7
|
expect {
|
16
8
|
PgLocksMonitor::DefaultNotifier.call({})
|
@@ -24,14 +16,26 @@ describe PgLocksMonitor::DefaultNotifier do
|
|
24
16
|
}.to raise_error(RuntimeError)
|
25
17
|
end
|
26
18
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
describe "Slack notification enabled" do
|
20
|
+
before do
|
21
|
+
PgLocksMonitor.configure do |config|
|
22
|
+
config.notify_slack = true
|
23
|
+
config.slack_webhook_url = "https://hooks.slack.com/services/123456789/123456789/123456789"
|
24
|
+
config.slack_channel = "pg-locks-monitor"
|
25
|
+
end
|
32
26
|
end
|
33
27
|
|
34
|
-
|
35
|
-
|
28
|
+
after do
|
29
|
+
PgLocksMonitor.configure do |config|
|
30
|
+
config.notify_slack = false
|
31
|
+
config.slack_webhook_url = nil
|
32
|
+
config.slack_channel = nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "sends the Slack notification" do
|
37
|
+
expect_any_instance_of(Slack::Notifier).to receive(:ping)
|
38
|
+
PgLocksMonitor::DefaultNotifier.call({ locks: "data" })
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
data/spec/smoke_spec.rb
CHANGED
@@ -3,11 +3,37 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe PgLocksMonitor do
|
6
|
+
def spawn_update
|
7
|
+
Thread.new do
|
8
|
+
conn = RailsPgExtras.connection
|
9
|
+
conn.execute("
|
10
|
+
BEGIN;
|
11
|
+
UPDATE pg_locks_monitor_users SET name = 'Updated';
|
12
|
+
select pg_sleep(2);
|
13
|
+
COMMIT;
|
14
|
+
")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
6
18
|
describe "snapshot!" do
|
7
19
|
it "works" do
|
8
20
|
expect {
|
9
21
|
PgLocksMonitor.snapshot!
|
10
22
|
}.not_to raise_error
|
11
23
|
end
|
24
|
+
|
25
|
+
it "returns correct locks data" do
|
26
|
+
spawn_update
|
27
|
+
spawn_update
|
28
|
+
result = PgLocksMonitor.snapshot!
|
29
|
+
expect(result.fetch(:locks).count).to eq(0)
|
30
|
+
expect(result.fetch(:blocking).count).to eq(0)
|
31
|
+
|
32
|
+
sleep 1
|
33
|
+
|
34
|
+
result = PgLocksMonitor.snapshot!
|
35
|
+
expect(result.fetch(:locks).count).to eq(5)
|
36
|
+
expect(result.fetch(:blocking).count).to eq(1)
|
37
|
+
end
|
12
38
|
end
|
13
39
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,8 +14,36 @@ port = if pg_version == "11"
|
|
14
14
|
"5434"
|
15
15
|
elsif pg_version == "14"
|
16
16
|
"5435"
|
17
|
+
elsif pg_version == "15"
|
18
|
+
"5436"
|
19
|
+
elsif pg_version == "16"
|
20
|
+
"5437"
|
17
21
|
else
|
18
22
|
"5432"
|
19
23
|
end
|
20
24
|
|
21
25
|
ENV["DATABASE_URL"] ||= "postgresql://postgres:secret@localhost:#{port}/pg-locks-monitor-test"
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
Rails = {}
|
29
|
+
|
30
|
+
config.before(:each) do
|
31
|
+
# Mock Rails and its logger
|
32
|
+
logger_double = double("Logger")
|
33
|
+
allow(logger_double).to receive(:info)
|
34
|
+
allow(Rails).to receive(:logger).and_return(logger_double)
|
35
|
+
end
|
36
|
+
|
37
|
+
config.before(:suite) do
|
38
|
+
ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"])
|
39
|
+
conn = RailsPgExtras.connection
|
40
|
+
conn.execute("CREATE TABLE IF NOT EXISTS pg_locks_monitor_users (id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL);")
|
41
|
+
conn.execute("INSERT INTO pg_locks_monitor_users (name) VALUES ('Alice');")
|
42
|
+
conn.execute("INSERT INTO pg_locks_monitor_users (name) VALUES ('Bob');")
|
43
|
+
end
|
44
|
+
|
45
|
+
config.after(:suite) do
|
46
|
+
conn = RailsPgExtras.connection
|
47
|
+
conn.execute("DROP TABLE IF EXISTS pg_locks_monitor_users;")
|
48
|
+
end
|
49
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg-locks-monitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pawurb
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rails-pg-extras
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|