after_migrate 0.2.2 → 0.2.3
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/CHANGELOG.md +12 -0
- data/lib/after_migrate/store.rb +89 -0
- data/lib/after_migrate/version.rb +1 -1
- data/lib/after_migrate.rb +28 -4
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b9d807edc34ee3c61bcda0ef4fd2319f80bac36c3bcd1cd1e2a46eb9f5e44f28
|
|
4
|
+
data.tar.gz: 16547159bf93c5a192a38a1e92d441bcd9690412b8d58ae163f59f8bc2da71bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7e76304080055fe4b9669d9895b9fb3709266c89e29deb2e39b3d408a29ba88ef1b99ebe951e693da446d2c97fda40ba416b71fae517234b65975e250b6635d
|
|
7
|
+
data.tar.gz: 14823ec925953300f85d28586a232111f945c2b9b8fb20bdaa4bf9d3057f8467dec2eb76defda50317a5811bbd6f7071bf71bb195f188950ab2a340030e0b2a5
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.3] - 2026-06-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Redis-backed store via `config.store = :redis` for sharing collected migration tables across processes
|
|
9
|
+
- `config.redis` for passing a Redis client, connection pool, or callable client provider
|
|
10
|
+
- `config.redis_key_prefix` and `config.redis_ttl` for namespacing and expiring Redis store keys
|
|
11
|
+
- Redis store support for run isolation via `config.run_id`
|
|
12
|
+
- Redis store specs for persistence, merging, reset behavior, connection pools, `Redis.new` fallback, and missing-client errors
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Store cache keys now include Redis-specific configuration, so changing Redis store settings rebuilds the active store instance
|
|
16
|
+
|
|
5
17
|
## [0.2.2] - 2026-05-31
|
|
6
18
|
|
|
7
19
|
### Added
|
data/lib/after_migrate/store.rb
CHANGED
|
@@ -100,5 +100,94 @@ module AfterMigrate
|
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
|
+
|
|
104
|
+
class RedisStore < Memory
|
|
105
|
+
attr_reader :key_prefix, :run_id, :ttl
|
|
106
|
+
|
|
107
|
+
def initialize(redis:, key_prefix: 'after_migrate', run_id: nil, ttl: 24 * 60 * 60)
|
|
108
|
+
super()
|
|
109
|
+
@redis = redis
|
|
110
|
+
@key_prefix = key_prefix.to_s
|
|
111
|
+
@run_id = run_id.to_s.presence || 'default'
|
|
112
|
+
@ttl = ttl.to_i
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def affected_tables
|
|
116
|
+
load_into_memory
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def merge_tables(schema, table_names)
|
|
121
|
+
return if table_names.blank?
|
|
122
|
+
|
|
123
|
+
with_redis do |redis|
|
|
124
|
+
redis.sadd(index_key, schema)
|
|
125
|
+
redis.sadd(schema_key(schema), table_names.to_a)
|
|
126
|
+
expire_keys(redis, schema)
|
|
127
|
+
end
|
|
128
|
+
merge_into_memory(schema => table_names)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def reset!
|
|
132
|
+
super
|
|
133
|
+
with_redis do |redis|
|
|
134
|
+
schemas = redis.smembers(index_key)
|
|
135
|
+
keys = schemas.map { |schema| schema_key(schema) }
|
|
136
|
+
redis.del(*(keys + [index_key])) if keys.any?
|
|
137
|
+
redis.del(index_key) if keys.empty?
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def load_into_memory
|
|
144
|
+
with_redis do |redis|
|
|
145
|
+
redis.smembers(index_key).each do |schema|
|
|
146
|
+
merge_into_memory(schema => redis.smembers(schema_key(schema)))
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def merge_into_memory(schemas)
|
|
152
|
+
schemas.each do |schema, table_names|
|
|
153
|
+
set = @affected_tables.compute_if_absent(schema) { Concurrent::Set.new }
|
|
154
|
+
set.merge(table_names)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def index_key
|
|
159
|
+
"#{base_key}:schemas"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def schema_key(schema)
|
|
163
|
+
"#{base_key}:schema:#{schema}"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def base_key
|
|
167
|
+
"#{key_prefix}:#{run_id}"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def expire_keys(redis, schema)
|
|
171
|
+
return unless ttl.positive?
|
|
172
|
+
|
|
173
|
+
redis.expire(index_key, ttl)
|
|
174
|
+
redis.expire(schema_key(schema), ttl)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def with_redis(&block)
|
|
178
|
+
redis = resolved_redis
|
|
179
|
+
return redis.with { |connection| block.call(connection) } if redis.respond_to?(:with)
|
|
180
|
+
|
|
181
|
+
block.call(redis)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def resolved_redis
|
|
185
|
+
client = @redis.respond_to?(:call) ? @redis.call : @redis
|
|
186
|
+
return client if client
|
|
187
|
+
return Redis.new if defined?(Redis)
|
|
188
|
+
|
|
189
|
+
raise 'AfterMigrate Redis store requires config.redis or the redis gem'
|
|
190
|
+
end
|
|
191
|
+
end
|
|
103
192
|
end
|
|
104
193
|
end
|
data/lib/after_migrate.rb
CHANGED
|
@@ -8,7 +8,8 @@ require 'after_migrate/railtie'
|
|
|
8
8
|
|
|
9
9
|
module AfterMigrate
|
|
10
10
|
class Configuration
|
|
11
|
-
attr_accessor :enabled, :verbose, :vacuum, :analyze, :rake_tasks_enhanced, :defer,
|
|
11
|
+
attr_accessor :enabled, :verbose, :vacuum, :analyze, :rake_tasks_enhanced, :defer,
|
|
12
|
+
:store, :store_path, :run_id, :redis, :redis_key_prefix, :redis_ttl
|
|
12
13
|
|
|
13
14
|
def initialize
|
|
14
15
|
@enabled = true
|
|
@@ -20,6 +21,9 @@ module AfterMigrate
|
|
|
20
21
|
@store = :memory
|
|
21
22
|
@store_path = 'tmp/after_migrate/affected_tables.json'
|
|
22
23
|
@run_id = nil
|
|
24
|
+
@redis = nil
|
|
25
|
+
@redis_key_prefix = 'after_migrate'
|
|
26
|
+
@redis_ttl = 24 * 60 * 60
|
|
23
27
|
end
|
|
24
28
|
end
|
|
25
29
|
|
|
@@ -58,21 +62,41 @@ module AfterMigrate
|
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
def store
|
|
61
|
-
|
|
62
|
-
@
|
|
63
|
-
@store_key = key
|
|
65
|
+
@store = nil if @store_key != store_key
|
|
66
|
+
@store_key = store_key
|
|
64
67
|
@store ||= build_store
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
private
|
|
68
71
|
|
|
72
|
+
def store_key
|
|
73
|
+
[
|
|
74
|
+
configuration.store.to_s,
|
|
75
|
+
configuration.store_path.to_s,
|
|
76
|
+
configuration.run_id.to_s,
|
|
77
|
+
configuration.redis_key_prefix.to_s,
|
|
78
|
+
configuration.redis_ttl.to_s
|
|
79
|
+
]
|
|
80
|
+
end
|
|
81
|
+
|
|
69
82
|
def build_store
|
|
70
83
|
case configuration.store.to_s
|
|
71
84
|
when 'file'
|
|
72
85
|
Stores::FileStore.new(path: configuration.store_path, run_id: configuration.run_id)
|
|
86
|
+
when 'redis'
|
|
87
|
+
redis_store
|
|
73
88
|
else
|
|
74
89
|
Stores::Memory.new
|
|
75
90
|
end
|
|
76
91
|
end
|
|
92
|
+
|
|
93
|
+
def redis_store
|
|
94
|
+
Stores::RedisStore.new(
|
|
95
|
+
redis: configuration.redis,
|
|
96
|
+
key_prefix: configuration.redis_key_prefix,
|
|
97
|
+
run_id: configuration.run_id,
|
|
98
|
+
ttl: configuration.redis_ttl
|
|
99
|
+
)
|
|
100
|
+
end
|
|
77
101
|
end
|
|
78
102
|
end
|