pg-locks-monitor 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 170cb606bd1459b6b1a7525ed08ce17f2aab0757703ec9a33f64dadeafdebf7c
4
- data.tar.gz: 503f92da91e4ca9d03999c45abb50507f8888b209df33c4a0e8b87e4cfdcb6b5
3
+ metadata.gz: 609f63093dd3729e2b05577d39d55d13a09cfeb78dadc185e3cd1bbeff15a5eb
4
+ data.tar.gz: 29bb4e5292296c81338ac5250efbc8e85927cdb8ede8354f0e4300b96bca7528
5
5
  SHA512:
6
- metadata.gz: 27d0ac7d4340b0de7739b6383ec203830ab92eb5b952cbc41b9447c6d41aa540d52522f067bd1cdd857802c6c8a49a16ddaff9b95f2c51beed0f3e3b8dae6022
7
- data.tar.gz: b4594194b88910f3fcc2e9c7e79205147076ff0fcd6ccf79ca2bc0e7e4290a3d5167e041f7660e72ecdfff1e7fe598684f103256a976582c83c884b8639dc77d
6
+ metadata.gz: 50377aa6446f17e900a28d427a0c6fc734ab78e29934f73af50d7957d3f81228515abb236964c1b6d5e866c5fad001eda0853f13d5aeb0a3cb540d70c7cd0011
7
+ data.tar.gz: 782c10cf04da3cbf8ec325cb15680f90bbea646344df1e5e1a1e72125781279f98321f1cce41c6c5d7da60dd59cfaa04a04eadff3233ebe0a282202808fd308e
@@ -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.1-alpine \
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 rake test_all
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 rake test_all
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 rake test_all
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 rake test_all
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/ && PG_VERSION=12 bundle exec rspec spec/ && PG_VERSION=13 bundle exec rspec spec/ && PG_VERSION=14 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
@@ -1,5 +1,3 @@
1
- version: '3'
2
-
3
1
  services:
4
2
  postgres11:
5
3
  image: postgres:11.16-alpine
@@ -2,11 +2,12 @@
2
2
 
3
3
  require "uri"
4
4
  require "pg"
5
- require "ruby-pg-extras"
5
+ require "rails-pg-extras"
6
+ require "active_record"
6
7
 
7
8
  module PgLocksMonitor
8
9
  def self.snapshot!
9
- locks = RubyPgExtras.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 = RubyPgExtras.blocking(in_format: :hash).select do |block|
23
- (ActiveSupport::Duration.parse(block.fetch("blocking_duration")).to_f * 1000) > configuration.blocking_min_duration_ms
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"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgLocksMonitor
4
- VERSION = "0.2.2"
4
+ VERSION = "0.3.1"
5
5
  end
@@ -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 "ruby-pg-extras"
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
- it "sends the Slack notification if enabled" do
28
- PgLocksMonitor.configure do |config|
29
- config.notify_slack = true
30
- config.slack_webhook_url = "https://hooks.slack.com/services/123456789/123456789/123456789"
31
- config.slack_channel = "pg-locks-monitor"
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
- expect_any_instance_of(Slack::Notifier).to receive(:ping)
35
- PgLocksMonitor::DefaultNotifier.call({ locks: "data" })
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.2.2
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-02 00:00:00.000000000 Z
11
+ date: 2024-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ruby-pg-extras
14
+ name: rails-pg-extras
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="