with_advisory_lock 5.1.0 → 7.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +36 -40
  3. data/.github/workflows/release.yml +1 -4
  4. data/.gitignore +2 -2
  5. data/.release-please-manifest.json +1 -1
  6. data/.ruby-version +2 -0
  7. data/.tool-versions +1 -1
  8. data/CHANGELOG.md +51 -0
  9. data/Gemfile +31 -0
  10. data/LICENSE.txt +4 -4
  11. data/Makefile +10 -0
  12. data/README.md +7 -35
  13. data/Rakefile +5 -2
  14. data/bin/console +11 -0
  15. data/bin/rails +15 -0
  16. data/bin/sanity +20 -0
  17. data/bin/sanity_check +86 -0
  18. data/bin/setup +8 -0
  19. data/bin/setup_test_db +59 -0
  20. data/bin/test_connections +22 -0
  21. data/docker-compose.yml +19 -0
  22. data/lib/with_advisory_lock/concern.rb +27 -16
  23. data/lib/with_advisory_lock/core_advisory.rb +110 -0
  24. data/lib/with_advisory_lock/jruby_adapter.rb +29 -0
  25. data/lib/with_advisory_lock/lock_stack_item.rb +6 -0
  26. data/lib/with_advisory_lock/mysql_advisory.rb +62 -0
  27. data/lib/with_advisory_lock/postgresql_advisory.rb +112 -0
  28. data/lib/with_advisory_lock/result.rb +14 -0
  29. data/lib/with_advisory_lock/version.rb +1 -1
  30. data/lib/with_advisory_lock.rb +38 -9
  31. data/test/dummy/Rakefile +8 -0
  32. data/test/dummy/app/controllers/application_controller.rb +7 -0
  33. data/test/dummy/app/models/application_record.rb +6 -0
  34. data/test/dummy/app/models/label.rb +4 -0
  35. data/test/dummy/app/models/mysql_label.rb +5 -0
  36. data/test/dummy/app/models/mysql_record.rb +6 -0
  37. data/test/dummy/app/models/mysql_tag.rb +10 -0
  38. data/test/dummy/app/models/mysql_tag_audit.rb +5 -0
  39. data/test/dummy/app/models/tag.rb +8 -0
  40. data/test/dummy/app/models/tag_audit.rb +4 -0
  41. data/test/dummy/config/application.rb +31 -0
  42. data/test/dummy/config/boot.rb +3 -0
  43. data/test/dummy/config/database.yml +13 -0
  44. data/test/dummy/config/environment.rb +7 -0
  45. data/test/dummy/config/routes.rb +4 -0
  46. data/test/dummy/config.ru +6 -0
  47. data/test/{test_models.rb → dummy/db/schema.rb} +3 -14
  48. data/test/dummy/db/secondary_schema.rb +15 -0
  49. data/test/dummy/lib/tasks/db.rake +40 -0
  50. data/test/sanity_check_test.rb +63 -0
  51. data/test/test_helper.rb +18 -37
  52. data/test/with_advisory_lock/concern_test.rb +79 -0
  53. data/test/with_advisory_lock/lock_test.rb +197 -0
  54. data/test/with_advisory_lock/multi_adapter_test.rb +17 -0
  55. data/test/with_advisory_lock/parallelism_test.rb +101 -0
  56. data/test/with_advisory_lock/postgresql_race_condition_test.rb +118 -0
  57. data/test/with_advisory_lock/shared_test.rb +129 -0
  58. data/test/with_advisory_lock/thread_test.rb +83 -0
  59. data/test/with_advisory_lock/transaction_test.rb +83 -0
  60. data/with_advisory_lock.gemspec +26 -6
  61. metadata +64 -55
  62. data/Appraisals +0 -45
  63. data/gemfiles/activerecord_6.1.gemfile +0 -21
  64. data/gemfiles/activerecord_7.0.gemfile +0 -21
  65. data/gemfiles/activerecord_7.1.gemfile +0 -14
  66. data/lib/with_advisory_lock/base.rb +0 -118
  67. data/lib/with_advisory_lock/database_adapter_support.rb +0 -26
  68. data/lib/with_advisory_lock/flock.rb +0 -33
  69. data/lib/with_advisory_lock/mysql.rb +0 -27
  70. data/lib/with_advisory_lock/postgresql.rb +0 -43
  71. data/test/concern_test.rb +0 -33
  72. data/test/lock_test.rb +0 -80
  73. data/test/nesting_test.rb +0 -28
  74. data/test/options_test.rb +0 -66
  75. data/test/parallelism_test.rb +0 -75
  76. data/test/shared_test.rb +0 -134
  77. data/test/thread_test.rb +0 -61
  78. data/test/transaction_test.rb +0 -68
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6918df100f32e829701a38ad6b7dd30db20d7a83635b82cbd8ccc7f3022a88d5
4
- data.tar.gz: f231c4fa8b5c403de000054839603e2297215929a64cccc63c21c577bc19ecd7
3
+ metadata.gz: 2af1c67f9aa840ba30d4c1a280a74a02bd46e83cef6ee426a59e16d77afaf99f
4
+ data.tar.gz: 055c8a8f251605c01d91fb4ead5f5cd3ab31b4327ee1bdb2b5fbd7b24cd0e455
5
5
  SHA512:
6
- metadata.gz: 21a2201433600aa26b0f7b0176b3b4e87606a00459b70d9dfb10a385c00a53fa5f0365cd426c2b5793d1b0022fa37e663567b0daf185e4be93d5a59e10695e2e
7
- data.tar.gz: b1e707a2115e83cd1667bb6b1842c7150b28da3603bd3ec668fc9918de01553fc10d44e65d89d94a3f7a183489da49b0348d1cc59650487d48482648041445df
6
+ metadata.gz: 9ea47f0a89759ee4573b7c0bf7a481e48bf7e5e6feac6b132ee42a5441478bb0d02840f1e40d5963ebc5c5bc93af47a21e4f58337e33c42091d07160994a0821
7
+ data.tar.gz: b584c732c8fd97dd74cc6c92286d19ef9f79fbb9911a626c092c0197028cc99540f3af5dce34fbc9579fd1c01d207c7426e57b91c0928cbb4ff3620f62bd0995
@@ -1,4 +1,3 @@
1
- ---
2
1
  name: CI
3
2
 
4
3
  on:
@@ -6,59 +5,50 @@ on:
6
5
  branches:
7
6
  - master
8
7
 
8
+ concurrency:
9
+ group: ci-${{ github.head_ref }}
10
+ cancel-in-progress: true
11
+
9
12
  jobs:
10
13
  minitest:
11
14
  runs-on: ubuntu-latest
15
+ name: CI Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}
12
16
  services:
13
- mysql:
14
- image: mysql/mysql-server:5.7
15
- ports:
16
- - "3306:3306"
17
- env:
18
- MYSQL_ROOT_PASSWORD: root
19
- MYSQL_DATABASE: with_advisory_lock_test
20
- MYSQL_ROOT_HOST: '%'
21
17
  postgres:
22
- image: 'postgres:14-alpine'
23
- ports: ['5432:5432']
18
+ image: 'postgres:17-alpine'
19
+ ports:
20
+ - '5432'
24
21
  env:
25
- POSTGRES_USER: closure_tree
26
- POSTGRES_PASSWORD: closure_tree
22
+ POSTGRES_USER: with_advisory
23
+ POSTGRES_PASSWORD: with_advisory_pass
27
24
  POSTGRES_DB: with_advisory_lock_test
28
25
  options: >-
29
26
  --health-cmd pg_isready
30
27
  --health-interval 10s
31
28
  --health-timeout 5s
32
29
  --health-retries 5
33
-
30
+ mysql:
31
+ image: mysql/mysql-server
32
+ ports:
33
+ - 3306
34
+ env:
35
+ MYSQL_USER: with_advisory
36
+ MYSQL_PASSWORD: with_advisory_pass
37
+ MYSQL_DATABASE: with_advisory_lock_test
38
+ MYSQL_ROOT_HOST: '%'
34
39
  strategy:
35
40
  fail-fast: false
36
41
  matrix:
37
42
  ruby:
38
- - '3.2'
39
- - '3.1'
40
- - '3.0'
41
- - '2.7'
43
+ - '3.3'
44
+ - '3.4'
42
45
  - 'truffleruby'
43
46
  rails:
44
- - activerecord_7.1
45
- - activerecord_7.0
46
- - activerecord_6.1
47
- adapter:
48
- - sqlite3:///tmp/test.sqlite3
49
- - mysql2://root:root@0/with_advisory_lock_test
50
- - trilogy://root:root@0/with_advisory_lock_test
51
- - postgres://closure_tree:closure_tree@0/with_advisory_lock_test
52
- include:
53
- - ruby: jruby
54
- rails: activerecord_6.1
55
- adapter: jdbcmysql://root:root@0/with_advisory_lock_test
56
- - ruby: jruby
57
- rails: activerecord_6.1
58
- adapter: jdbcsqlite3:///tmp/test.sqlite3
59
- - ruby: jruby
60
- rails: activerecord_6.1
61
- adapter: jdbcpostgresql://closure_tree:closure_tree@0/with_advisory_lock_test
47
+ - 7.2
48
+ - "8.0"
49
+ env:
50
+ ACTIVERECORD_VERSION: ${{ matrix.rails }}
51
+ RAILS_ENV: test
62
52
  steps:
63
53
  - name: Checkout
64
54
  uses: actions/checkout@v4
@@ -69,12 +59,18 @@ jobs:
69
59
  ruby-version: ${{ matrix.ruby }}
70
60
  bundler-cache: true
71
61
  rubygems: latest
62
+
63
+ - name: Setup test databases
72
64
  env:
73
- BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile
65
+ DATABASE_URL_PG: postgres://with_advisory:with_advisory_pass@localhost:${{ job.services.postgres.ports[5432] }}/with_advisory_lock_test
66
+ DATABASE_URL_MYSQL: mysql2://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
67
+ run: |
68
+ cd test/dummy
69
+ bundle exec rake db:test:prepare
74
70
 
75
71
  - name: Test
76
72
  env:
77
- BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile
78
- DATABASE_URL: ${{ matrix.adapter }}
73
+ DATABASE_URL_PG: postgres://with_advisory:with_advisory_pass@localhost:${{ job.services.postgres.ports[5432] }}/with_advisory_lock_test
74
+ DATABASE_URL_MYSQL: mysql2://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
79
75
  WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
80
- run: bundle exec rake
76
+ run: bin/rails test
@@ -14,7 +14,4 @@ jobs:
14
14
  release-please:
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: google-github-actions/release-please-action@v4
18
- id: release
19
- with:
20
- command: manifest
17
+ - uses: googleapis/release-please-action@v4
data/.gitignore CHANGED
@@ -18,5 +18,5 @@ test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
20
  *.iml
21
- test/sqlite.db
22
- .env
21
+ .env
22
+ test/dummy/log/
@@ -1 +1 @@
1
- {".":"5.1.0"}
1
+ {".":"7.0.0"}
data/.ruby-version ADDED
@@ -0,0 +1,2 @@
1
+ 3.4.4
2
+
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 3.0.5
1
+ ruby 3.4.4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  ## Changelog
2
2
 
3
+ ## [7.0.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v6.0.0...with_advisory_lock/v7.0.0) (2025-07-05)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * require Rails 7.2+ as minimum version
9
+
10
+ ### Features
11
+
12
+ * fire Ruby from its second job checking locks and let PostgreSQL do what it's paid for ([#124](https://github.com/ClosureTree/with_advisory_lock/issues/124)) ([f7f8dbc](https://github.com/ClosureTree/with_advisory_lock/commit/f7f8dbcd69842a358d0d70227bcc52ba3183c098))
13
+ * handle connection disconnection gracefully ([1944e98](https://github.com/ClosureTree/with_advisory_lock/commit/1944e98877917e234bfe597f9358c0b74643a045))
14
+ * handle connection disconnection gracefully ([77046a9](https://github.com/ClosureTree/with_advisory_lock/commit/77046a94c7504f77a59fae6fbcd75e73ed41bf23))
15
+ * implement MySQL native timeout support ([#123](https://github.com/ClosureTree/with_advisory_lock/issues/123)) ([387dedd](https://github.com/ClosureTree/with_advisory_lock/commit/387dedd133c897f7a3da13ed2ebbd9223b81317d))
16
+ * require Rails 7.2+ as minimum version ([d4e7826](https://github.com/ClosureTree/with_advisory_lock/commit/d4e7826ddc216c103cd666674068cb7f512fc32d))
17
+ * validate transaction-level locks require active transaction ([#122](https://github.com/ClosureTree/with_advisory_lock/issues/122)) ([e4bc6c1](https://github.com/ClosureTree/with_advisory_lock/commit/e4bc6c10666e02c560f18629df0106c39bb85e19))
18
+
19
+ ## [6.0.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.3.0...with_advisory_lock/v6.0.0) (2025-05-28)
20
+
21
+
22
+ ### ⚠ BREAKING CHANGES
23
+
24
+ * Remove private APIs (Base, DatabaseAdapterSupport). Add full mixed adapter support for PostgreSQL/MySQL in same app. Add JRuby compatibility.
25
+ * drop support for sqlite3
26
+ * drop legacy version of ruby/rails ([#113](https://github.com/ClosureTree/with_advisory_lock/issues/113))
27
+
28
+ ### Features
29
+
30
+ * drop legacy version of ruby/rails ([#113](https://github.com/ClosureTree/with_advisory_lock/issues/113)) ([26fd427](https://github.com/ClosureTree/with_advisory_lock/commit/26fd4278f9fa155974e6f86df7cd92dd2b7d9154))
31
+ * drop support for sqlite3 ([26fd427](https://github.com/ClosureTree/with_advisory_lock/commit/26fd4278f9fa155974e6f86df7cd92dd2b7d9154))
32
+ * move to rails dummy app to test multidb setup ([#115](https://github.com/ClosureTree/with_advisory_lock/issues/115)) ([71a3431](https://github.com/ClosureTree/with_advisory_lock/commit/71a34316b365a0f3be0e8a046db14289e69efc9c))
33
+ * support of multidb ([#116](https://github.com/ClosureTree/with_advisory_lock/issues/116)) ([935e7e5](https://github.com/ClosureTree/with_advisory_lock/commit/935e7e5fb05dad2eba034745d2ef49e11c163f7d))
34
+
35
+ ## [5.3.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.2.0...with_advisory_lock/v5.3.0) (2025-04-25)
36
+
37
+
38
+ ### Features
39
+
40
+ * add #current_advisory_locks method ([#111](https://github.com/ClosureTree/with_advisory_lock/issues/111)) ([ccbd3b2](https://github.com/ClosureTree/with_advisory_lock/commit/ccbd3b23465f7fa1fc3800334159986c31d5c351))
41
+
42
+ ## [5.2.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.1.0...with_advisory_lock/v5.2.0) (2025-04-24)
43
+
44
+
45
+ ### Features
46
+
47
+ * use current connnection instead of the one in ActiveRecord::Base ([#90](https://github.com/ClosureTree/with_advisory_lock/issues/90)) ([c28a172](https://github.com/ClosureTree/with_advisory_lock/commit/c28a172a5a64594448b6090501fc0b8cbace06f6))
48
+
49
+
50
+ ### Bug Fixes
51
+
52
+ * Removed MySQL unused lock variable and broaden SQLite detection. ([#94](https://github.com/ClosureTree/with_advisory_lock/issues/94)) ([f818a18](https://github.com/ClosureTree/with_advisory_lock/commit/f818a181dde6711c8439c4cbf67c4525a09d346e))
53
+
3
54
  ## [5.1.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v5.0.1...with_advisory_lock/v5.1.0) (2024-01-21)
4
55
 
5
56
 
data/Gemfile CHANGED
@@ -1,3 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
6
+
7
+ gem 'rake'
8
+
9
+ # Gems that will be removed from default gems in Ruby 3.5.0
10
+ gem 'benchmark'
11
+ gem 'logger'
12
+ gem 'ostruct'
13
+
14
+ activerecord_version = ENV.fetch('ACTIVERECORD_VERSION', '7.2')
15
+
16
+ gem 'activerecord', "~> #{activerecord_version}.0"
17
+
18
+ gem 'dotenv'
19
+ gem 'railties'
20
+
21
+ platforms :ruby do
22
+ gem 'mysql2'
23
+ gem 'pg'
24
+ gem 'sqlite3'
25
+ gem 'trilogy'
26
+ end
27
+
28
+ platforms :jruby do
29
+ # JRuby JDBC adapters support Rails 7.2+
30
+ if activerecord_version >= '7.2'
31
+ gem 'activerecord-jdbcmysql-adapter', '~> 72.0'
32
+ gem 'activerecord-jdbcpostgresql-adapter', '~> 72.0'
33
+ end
34
+ end
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
- Copyright (c) 2013 Matthew McEachen
2
-
3
- MIT License
1
+ SPDX-License-Identifier: MIT
2
+ SPDX-FileCopyrightText: 2013 Matthew McEachen
3
+ SPDX-FileCopyrightText: 2013-2025 Abdelkader Boudih
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,10 @@
1
+ .PHONY: test
2
+
3
+ test: setup-db
4
+ bin/rails test
5
+
6
+ setup-db:
7
+ docker compose up -d
8
+ sleep 2
9
+ bundle
10
+ bin/setup_test_db
data/README.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # with_advisory_lock
2
2
 
3
- Adds advisory locking (mutexes) to ActiveRecord 6.0+, with ruby 2.7+, jruby or truffleruby, when used with
3
+ Adds advisory locking (mutexes) to ActiveRecord 7.2+, with ruby 3.3+, jruby or truffleruby, when used with
4
4
  [MySQL](https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_get-lock)
5
5
  or
6
6
  [PostgreSQL](https://www.postgresql.org/docs/current/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS).
7
- SQLite resorts to file locking.
7
+
8
+ **Note:** SQLite support has been removed. For single-node SQLite deployments,
9
+ consider using a Ruby mutex instead. Support for MySQL 5.7 has also been
10
+ dropped; please use MySQL 8 or PostgreSQL.
8
11
 
9
12
  [![Gem Version](https://badge.fury.io/rb/with_advisory_lock.svg)](https://badge.fury.io/rb/with_advisory_lock)
10
13
  [![CI](https://github.com/ClosureTree/with_advisory_lock/actions/workflows/ci.yml/badge.svg)](https://github.com/ClosureTree/with_advisory_lock/actions/workflows/ci.yml)
@@ -13,7 +16,7 @@ SQLite resorts to file locking.
13
16
 
14
17
  An advisory lock is a [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion)
15
18
  used to ensure no two processes run some process at the same time. When the
16
- advisory lock is powered by your database server, as long as it isn't SQLite,
19
+ advisory lock is powered by your database server,
17
20
  your mutex spans hosts.
18
21
 
19
22
  ## Usage
@@ -134,7 +137,7 @@ row-level locks prevent concurrent modification to a given model.
134
137
 
135
138
  **If you're building a
136
139
  [CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)
137
- application, this will be 2.4, 2.5 and your most commonly used lock.**
140
+ application, this will be 2.4, 2.5 and your most commonly used lock.**
138
141
 
139
142
  ### Table-level locks
140
143
 
@@ -152,38 +155,7 @@ Advisory locks with MySQL and PostgreSQL ignore database transaction boundaries.
152
155
 
153
156
  You will want to wrap your block within a transaction to ensure consistency.
154
157
 
155
- ### MySQL < 5.7.5 doesn't support nesting
156
-
157
- With MySQL < 5.7.5, if you ask for a _different_ advisory lock within
158
- a `with_advisory_lock` block, you will be releasing the parent lock (!!!). A
159
- `NestedAdvisoryLockError`will be raised in this case. If you ask for the same
160
- lock name, `with_advisory_lock` won't ask for the lock again, and the block
161
- given will be yielded to.
162
-
163
- This is not an issue in MySQL >= 5.7.5, and no error will be raised for nested
164
- lock usage. You can override this by passing `force_nested_lock_support: true`
165
- or `force_nested_lock_support: false` to the `with_advisory_lock` options.
166
-
167
158
  ### Is clustered MySQL supported?
168
159
 
169
160
  [No.](https://github.com/ClosureTree/with_advisory_lock/issues/16)
170
161
 
171
- ### There are many `lock-*` files in my project directory after test runs
172
-
173
- This is expected if you aren't using MySQL or Postgresql for your tests.
174
- See [issue 3](https://github.com/ClosureTree/with_advisory_lock/issues/3).
175
-
176
- SQLite doesn't have advisory locks, so we resort to file locking, which will
177
- only work if the `FLOCK_DIR` is set consistently for all ruby processes.
178
-
179
- In your `spec_helper.rb` or `minitest_helper.rb`, add a `before` and `after` block:
180
-
181
- ```ruby
182
- before do
183
- ENV['FLOCK_DIR'] = Dir.mktmpdir
184
- end
185
-
186
- after do
187
- FileUtils.remove_entry_secure ENV['FLOCK_DIR']
188
- end
189
- ```
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
2
4
 
3
5
  require 'yard'
4
6
  YARD::Rake::YardocTask.new do |t|
@@ -14,4 +16,5 @@ Rake::TestTask.new do |t|
14
16
  t.verbose = true
15
17
  end
16
18
 
17
- task :default => :test
19
+
20
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'no_fly_list'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require 'irb'
11
+ IRB.start(__FILE__)
data/bin/rails ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This command will automatically be run when you run "rails" with Rails gems
5
+ # installed from the root of your application.
6
+
7
+ ENGINE_ROOT = File.expand_path('..', __dir__)
8
+ APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
9
+
10
+ # Set up gems listed in the Gemfile.
11
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
12
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
13
+
14
+ require 'rails/all'
15
+ require 'rails/engine/commands'
data/bin/sanity ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ check_port() {
5
+ local port="$1"
6
+ local name="$2"
7
+ if nc -z localhost "$port" >/dev/null 2>&1; then
8
+ echo "$name running on port $port"
9
+ else
10
+ echo "ERROR: $name is not running on port $port" >&2
11
+ return 1
12
+ fi
13
+ }
14
+
15
+ main() {
16
+ check_port 5433 "Postgresql"
17
+ check_port 3366 "Mysql"
18
+ }
19
+
20
+ main "$@"
data/bin/sanity_check ADDED
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ ENV['RAILS_ENV'] = 'test'
5
+ ENV['DATABASE_URL_PG'] ||= 'postgres://with_advisory:with_advisory_pass@localhost:5433/with_advisory_lock_test'
6
+ ENV['DATABASE_URL_MYSQL'] ||= 'mysql2://with_advisory:with_advisory_pass@0.0.0.0:3366/with_advisory_lock_test'
7
+
8
+ require_relative '../test/dummy/config/environment'
9
+
10
+ puts '=' * 80
11
+ puts 'WITH_ADVISORY_LOCK SANITY CHECK'
12
+ puts '=' * 80
13
+ puts
14
+
15
+ # Check Rails environment
16
+ puts "Rails Environment: #{Rails.env}"
17
+ puts "Rails Root: #{Rails.root}"
18
+ puts
19
+
20
+ # Check PostgreSQL connection
21
+ puts 'PostgreSQL Connection (ApplicationRecord):'
22
+ begin
23
+ ApplicationRecord.connection.execute('SELECT 1')
24
+ puts ' ✓ Connected to PostgreSQL'
25
+ puts " Database: #{ApplicationRecord.connection.current_database}"
26
+ puts " Adapter: #{ApplicationRecord.connection.adapter_name}"
27
+ puts " Tables: #{ApplicationRecord.connection.tables.sort.join(', ')}"
28
+
29
+ # Test creating a record
30
+ tag = Tag.create!(name: "test-pg-#{Time.now.to_i}")
31
+ puts " ✓ Created Tag record with id: #{tag.id}"
32
+ tag.destroy
33
+ puts ' ✓ Deleted Tag record'
34
+ rescue StandardError => e
35
+ puts " ✗ ERROR: #{e.message}"
36
+ puts " #{e.backtrace.first}"
37
+ end
38
+ puts
39
+
40
+ # Check MySQL connection
41
+ puts 'MySQL Connection (MysqlRecord):'
42
+ begin
43
+ MysqlRecord.connection.execute('SELECT 1')
44
+ puts ' ✓ Connected to MySQL'
45
+ puts " Database: #{MysqlRecord.connection.current_database}"
46
+ puts " Adapter: #{MysqlRecord.connection.adapter_name}"
47
+ puts " Tables: #{MysqlRecord.connection.tables.sort.join(', ')}"
48
+
49
+ # Test creating a record
50
+ mysql_tag = MysqlTag.create!(name: "test-mysql-#{Time.now.to_i}")
51
+ puts " ✓ Created MysqlTag record with id: #{mysql_tag.id}"
52
+ mysql_tag.destroy
53
+ puts ' ✓ Deleted MysqlTag record'
54
+ rescue StandardError => e
55
+ puts " ✗ ERROR: #{e.message}"
56
+ puts " #{e.backtrace.first}"
57
+ end
58
+ puts
59
+
60
+ # Check model associations
61
+ puts 'Model Configuration:'
62
+ puts ' PostgreSQL Models:'
63
+ puts " - Tag -> #{Tag.connection.adapter_name}"
64
+ puts " - TagAudit -> #{TagAudit.connection.adapter_name}"
65
+ puts " - Label -> #{Label.connection.adapter_name}"
66
+ puts ' MySQL Models:'
67
+ puts " - MysqlTag -> #{MysqlTag.connection.adapter_name}"
68
+ puts " - MysqlTagAudit -> #{MysqlTagAudit.connection.adapter_name}"
69
+ puts " - MysqlLabel -> #{MysqlLabel.connection.adapter_name}"
70
+ puts
71
+
72
+ # Check if WithAdvisoryLock is loaded
73
+ puts 'WithAdvisoryLock Status:'
74
+ puts " Module loaded: #{defined?(WithAdvisoryLock) ? 'Yes' : 'No'}"
75
+ puts " Concern loaded: #{defined?(WithAdvisoryLock::Concern) ? 'Yes' : 'No'}"
76
+ puts " PostgreSQL adapter loaded: #{defined?(WithAdvisoryLock::PostgreSQL) ? 'Yes' : 'No'}"
77
+ puts " MySQL adapter loaded: #{defined?(WithAdvisoryLock::MySQL) ? 'Yes' : 'No'}"
78
+
79
+ # Check if models have advisory lock methods
80
+ puts "\nModel Methods:"
81
+ puts " Tag.with_advisory_lock available: #{Tag.respond_to?(:with_advisory_lock)}"
82
+ puts " MysqlTag.with_advisory_lock available: #{MysqlTag.respond_to?(:with_advisory_lock)}"
83
+
84
+ puts "\n#{'=' * 80}"
85
+ puts 'SANITY CHECK COMPLETE'
86
+ puts '=' * 80
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+ bin/rails db:setup
8
+ bin/rails db:migrate
data/bin/setup_test_db ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'active_record'
6
+
7
+ # Setup PostgreSQL database
8
+ puts 'Setting up PostgreSQL test database...'
9
+ ActiveRecord::Base.establish_connection(
10
+ adapter: 'postgresql',
11
+ host: 'localhost',
12
+ port: 5433,
13
+ database: 'with_advisory_lock_test',
14
+ username: 'with_advisory',
15
+ password: 'with_advisory_pass'
16
+ )
17
+
18
+ ActiveRecord::Schema.define(version: 1) do
19
+ create_table 'tags', force: true do |t|
20
+ t.string 'name'
21
+ end
22
+
23
+ create_table 'tag_audits', id: false, force: true do |t|
24
+ t.string 'tag_name'
25
+ end
26
+
27
+ create_table 'labels', id: false, force: true do |t|
28
+ t.string 'name'
29
+ end
30
+ end
31
+ puts 'PostgreSQL tables created!'
32
+
33
+ # Setup MySQL database
34
+ puts "\nSetting up MySQL test database..."
35
+ ActiveRecord::Base.establish_connection(
36
+ adapter: 'mysql2',
37
+ host: '127.0.0.1',
38
+ port: 3366,
39
+ database: 'with_advisory_lock_test',
40
+ username: 'with_advisory',
41
+ password: 'with_advisory_pass'
42
+ )
43
+
44
+ ActiveRecord::Schema.define(version: 1) do
45
+ create_table 'mysql_tags', force: true do |t|
46
+ t.string 'name'
47
+ end
48
+
49
+ create_table 'mysql_tag_audits', id: false, force: true do |t|
50
+ t.string 'tag_name'
51
+ end
52
+
53
+ create_table 'mysql_labels', id: false, force: true do |t|
54
+ t.string 'name'
55
+ end
56
+ end
57
+ puts 'MySQL tables created!'
58
+
59
+ puts "\nTest databases setup complete!"
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ ENV['RAILS_ENV'] = 'test'
5
+ ENV['DATABASE_URL_PG'] ||= 'postgres://with_advisory:with_advisory_pass@localhost:5433/with_advisory_lock_test'
6
+ ENV['DATABASE_URL_MYSQL'] ||= 'mysql2://with_advisory:with_advisory_pass@0.0.0.0:3366/with_advisory_lock_test'
7
+
8
+ require_relative '../test/dummy/config/environment'
9
+
10
+ puts 'Testing database connections...'
11
+
12
+ puts "\nPostgreSQL (ApplicationRecord):"
13
+ puts " Connected: #{ApplicationRecord.connected?}"
14
+ puts " Tables: #{ApplicationRecord.connection.tables.sort.join(', ')}"
15
+
16
+ puts "\nMySQL (MysqlRecord):"
17
+ puts " Connected: #{MysqlRecord.connected?}"
18
+ puts " Tables: #{MysqlRecord.connection.tables.sort.join(', ')}"
19
+
20
+ puts "\nModel connections:"
21
+ puts " Tag uses: #{Tag.connection.adapter_name}"
22
+ puts " MysqlTag uses: #{MysqlTag.connection.adapter_name}"
@@ -0,0 +1,19 @@
1
+ services:
2
+ pg:
3
+ image: postgres:17-alpine
4
+ environment:
5
+ POSTGRES_USER: with_advisory
6
+ POSTGRES_PASSWORD: with_advisory_pass
7
+ POSTGRES_DB: with_advisory_lock_test
8
+ ports:
9
+ - "5433:5432"
10
+ mysql:
11
+ image: mysql:8
12
+ environment:
13
+ MYSQL_USER: with_advisory
14
+ MYSQL_PASSWORD: with_advisory_pass
15
+ MYSQL_DATABASE: with_advisory_lock_test
16
+ MYSQL_RANDOM_ROOT_PASSWORD: "yes"
17
+ MYSQL_ROOT_HOST: '%'
18
+ ports:
19
+ - "3366:3306"