pg_multitenant_schemas 0.1.3 → 0.2.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/.ruby-version +1 -0
- data/CHANGELOG.md +46 -0
- data/README.md +269 -16
- data/docs/README.md +77 -0
- data/docs/configuration.md +340 -0
- data/docs/context.md +292 -0
- data/docs/errors.md +498 -0
- data/docs/integration_testing.md +454 -0
- data/docs/migrator.md +291 -0
- data/docs/rails_integration.md +468 -0
- data/docs/schema_switcher.md +182 -0
- data/docs/tenant_resolver.md +394 -0
- data/docs/testing.md +358 -0
- data/examples/context_management.rb +198 -0
- data/examples/migration_workflow.rb +50 -0
- data/examples/rails_integration/controller_examples.rb +368 -0
- data/examples/schema_operations.rb +124 -0
- data/lib/pg_multitenant_schemas/configuration.rb +4 -4
- data/lib/pg_multitenant_schemas/migration_display_reporter.rb +30 -0
- data/lib/pg_multitenant_schemas/migration_executor.rb +81 -0
- data/lib/pg_multitenant_schemas/migration_schema_operations.rb +54 -0
- data/lib/pg_multitenant_schemas/migration_status_reporter.rb +65 -0
- data/lib/pg_multitenant_schemas/migrator.rb +89 -0
- data/lib/pg_multitenant_schemas/schema_switcher.rb +40 -66
- data/lib/pg_multitenant_schemas/tasks/advanced_tasks.rake +21 -0
- data/lib/pg_multitenant_schemas/tasks/basic_tasks.rake +20 -0
- data/lib/pg_multitenant_schemas/tasks/pg_multitenant_schemas.rake +53 -143
- data/lib/pg_multitenant_schemas/tasks/tenant_tasks.rake +65 -0
- data/lib/pg_multitenant_schemas/tenant_task_helpers.rb +102 -0
- data/lib/pg_multitenant_schemas/version.rb +1 -1
- data/lib/pg_multitenant_schemas.rb +10 -5
- data/pg_multitenant_schemas.gemspec +10 -9
- data/rails_integration/app/controllers/application_controller.rb +6 -0
- data/rails_integration/app/models/tenant.rb +6 -0
- metadata +39 -17
data/docs/migrator.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Migrator - Automated Migration Management
|
|
2
|
+
|
|
3
|
+
**File**: `lib/pg_multitenant_schemas/migrator.rb`
|
|
4
|
+
|
|
5
|
+
## 📋 Overview
|
|
6
|
+
|
|
7
|
+
The `Migrator` class provides comprehensive automated migration management for multi-tenant applications. It handles running migrations across all tenant schemas, setting up new tenants, and tracking migration status.
|
|
8
|
+
|
|
9
|
+
## 🎯 Purpose
|
|
10
|
+
|
|
11
|
+
- **Bulk Migration**: Run migrations across all tenant schemas with single command
|
|
12
|
+
- **Tenant Setup**: Automated tenant creation with schema and migrations
|
|
13
|
+
- **Status Tracking**: Monitor migration status across all tenants
|
|
14
|
+
- **Error Resilience**: Handle migration failures gracefully per tenant
|
|
15
|
+
- **Progress Reporting**: Detailed feedback during migration operations
|
|
16
|
+
|
|
17
|
+
## 🔧 Key Methods
|
|
18
|
+
|
|
19
|
+
### Core Migration Operations
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
# Migrate all tenant schemas
|
|
23
|
+
Migrator.migrate_all
|
|
24
|
+
|
|
25
|
+
# Migrate specific tenant
|
|
26
|
+
Migrator.migrate_tenant('acme_corp')
|
|
27
|
+
|
|
28
|
+
# Check migration status across all tenants
|
|
29
|
+
Migrator.migration_status
|
|
30
|
+
|
|
31
|
+
# Setup new tenant (create schema + run migrations)
|
|
32
|
+
Migrator.setup_tenant('new_tenant')
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Tenant Management
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# Setup all existing tenants
|
|
39
|
+
Migrator.setup_all_tenants
|
|
40
|
+
|
|
41
|
+
# Create tenant with attributes and schema
|
|
42
|
+
Migrator.create_tenant_with_schema({
|
|
43
|
+
subdomain: 'acme',
|
|
44
|
+
name: 'ACME Corporation'
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
# Rollback specific tenant
|
|
48
|
+
Migrator.rollback_tenant('tenant_name', steps: 2)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🏗️ Implementation Details
|
|
52
|
+
|
|
53
|
+
### Migration Execution Flow
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
def migrate_all
|
|
57
|
+
puts "🚀 Starting migration for all tenant schemas..."
|
|
58
|
+
|
|
59
|
+
tenant_schemas.each do |schema|
|
|
60
|
+
puts "📦 Migrating schema: #{schema}"
|
|
61
|
+
|
|
62
|
+
migrate_tenant(schema)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
puts "✅ Migration completed for all schemas"
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Error Handling Strategy
|
|
70
|
+
|
|
71
|
+
The Migrator implements robust error handling:
|
|
72
|
+
|
|
73
|
+
- **Per-Tenant Isolation**: Failures in one tenant don't affect others
|
|
74
|
+
- **Detailed Error Reporting**: Specific error messages per tenant
|
|
75
|
+
- **Continue on Error**: Migration continues for remaining tenants
|
|
76
|
+
- **Transaction Safety**: Each tenant migration is self-contained
|
|
77
|
+
|
|
78
|
+
### Progress Tracking
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
def migration_status
|
|
82
|
+
puts "📊 Migration Status Report"
|
|
83
|
+
|
|
84
|
+
tenant_schemas.each do |schema|
|
|
85
|
+
pending = pending_migrations_for_schema(schema)
|
|
86
|
+
|
|
87
|
+
if pending.empty?
|
|
88
|
+
puts "▸ #{schema}: ✅ Up to date"
|
|
89
|
+
else
|
|
90
|
+
puts "▸ #{schema}: ⚠️ #{pending.count} pending migrations"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 🔄 Usage Patterns
|
|
97
|
+
|
|
98
|
+
### Daily Operations
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Check what needs migration
|
|
102
|
+
PgMultitenantSchemas::Migrator.migration_status
|
|
103
|
+
|
|
104
|
+
# Run migrations across all tenants
|
|
105
|
+
PgMultitenantSchemas::Migrator.migrate_all
|
|
106
|
+
|
|
107
|
+
# Setup new tenant
|
|
108
|
+
PgMultitenantSchemas::Migrator.setup_tenant('new_client')
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Deployment Workflow
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
# In deployment script
|
|
115
|
+
namespace :deploy do
|
|
116
|
+
task :migrate_tenants do
|
|
117
|
+
PgMultitenantSchemas::Migrator.migrate_all
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### New Tenant Onboarding
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
# Complete tenant setup
|
|
126
|
+
tenant_attributes = {
|
|
127
|
+
subdomain: 'newco',
|
|
128
|
+
name: 'New Company Ltd',
|
|
129
|
+
domain: 'newco.com'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
tenant = PgMultitenantSchemas::Migrator.create_tenant_with_schema(tenant_attributes)
|
|
133
|
+
puts "✅ Tenant #{tenant.subdomain} ready for use"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Rollback Operations
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
# Rollback specific tenant
|
|
140
|
+
PgMultitenantSchemas::Migrator.rollback_tenant('acme_corp', steps: 1)
|
|
141
|
+
|
|
142
|
+
# Check status after rollback
|
|
143
|
+
PgMultitenantSchemas::Migrator.migration_status
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 🎛️ Configuration Integration
|
|
147
|
+
|
|
148
|
+
The Migrator respects global configuration:
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
PgMultitenantSchemas.configure do |config|
|
|
152
|
+
config.default_schema = 'public'
|
|
153
|
+
config.tenant_model = 'Tenant'
|
|
154
|
+
config.connection_class = 'ApplicationRecord'
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 📊 Status Reporting
|
|
159
|
+
|
|
160
|
+
### Migration Status Output
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
📊 Migration Status Report
|
|
164
|
+
▸ acme_corp: ✅ Up to date (5 migrations)
|
|
165
|
+
▸ beta_corp: ⚠️ 2 pending migrations
|
|
166
|
+
- 20241201120000_add_feature_flags
|
|
167
|
+
- 20241202100000_update_user_fields
|
|
168
|
+
▸ demo_corp: ✅ Up to date (5 migrations)
|
|
169
|
+
|
|
170
|
+
📈 Overall: 2/3 tenants current, 2 migrations pending
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Migration Progress Output
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
🚀 Starting migration for all tenant schemas...
|
|
177
|
+
|
|
178
|
+
📦 Migrating schema: acme_corp
|
|
179
|
+
✓ Running migration 20241201120000_add_feature_flags
|
|
180
|
+
✓ Running migration 20241202100000_update_user_fields
|
|
181
|
+
✅ Completed migration for acme_corp
|
|
182
|
+
|
|
183
|
+
📦 Migrating schema: beta_corp
|
|
184
|
+
✓ Running migration 20241201120000_add_feature_flags
|
|
185
|
+
✗ Error in migration 20241202100000_update_user_fields: column already exists
|
|
186
|
+
⚠️ Continuing with next tenant...
|
|
187
|
+
|
|
188
|
+
✅ Migration completed for all schemas
|
|
189
|
+
📊 Summary: 1/2 tenants migrated successfully
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 🔍 Advanced Features
|
|
193
|
+
|
|
194
|
+
### Custom Migration Paths
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
# Override migration paths if needed
|
|
198
|
+
class CustomMigrator < PgMultitenantSchemas::Migrator
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
def migration_paths
|
|
202
|
+
[
|
|
203
|
+
Rails.root.join('db', 'migrate'),
|
|
204
|
+
Rails.root.join('db', 'tenant_migrations')
|
|
205
|
+
]
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Migration Callbacks
|
|
211
|
+
|
|
212
|
+
```ruby
|
|
213
|
+
# Add hooks for migration events
|
|
214
|
+
module MigrationHooks
|
|
215
|
+
def self.before_tenant_migration(schema_name)
|
|
216
|
+
Rails.logger.info "Starting migration for #{schema_name}"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def self.after_tenant_migration(schema_name, success)
|
|
220
|
+
status = success ? "SUCCESS" : "FAILED"
|
|
221
|
+
Rails.logger.info "Migration for #{schema_name}: #{status}"
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Batch Processing
|
|
227
|
+
|
|
228
|
+
```ruby
|
|
229
|
+
# Process tenants in batches for large installations
|
|
230
|
+
def migrate_all_batched(batch_size: 10)
|
|
231
|
+
tenant_schemas.each_slice(batch_size) do |batch|
|
|
232
|
+
batch.each { |schema| migrate_tenant(schema) }
|
|
233
|
+
sleep(1) # Brief pause between batches
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## 🚨 Important Considerations
|
|
239
|
+
|
|
240
|
+
### Performance
|
|
241
|
+
|
|
242
|
+
- **Parallel Processing**: Consider parallelization for large tenant counts
|
|
243
|
+
- **Resource Usage**: Monitor database connections during bulk operations
|
|
244
|
+
- **Timing**: Run during low-traffic periods for production
|
|
245
|
+
|
|
246
|
+
### Data Integrity
|
|
247
|
+
|
|
248
|
+
- **Backup Strategy**: Ensure proper backups before major migrations
|
|
249
|
+
- **Testing**: Test migrations on staging environment with production data
|
|
250
|
+
- **Rollback Plan**: Have rollback procedures for failed migrations
|
|
251
|
+
|
|
252
|
+
### Monitoring
|
|
253
|
+
|
|
254
|
+
- **Log Analysis**: Monitor migration logs for patterns and issues
|
|
255
|
+
- **Alert Setup**: Set up alerts for migration failures
|
|
256
|
+
- **Performance Metrics**: Track migration duration and resource usage
|
|
257
|
+
|
|
258
|
+
## 🔧 Troubleshooting
|
|
259
|
+
|
|
260
|
+
### Common Issues
|
|
261
|
+
|
|
262
|
+
**Migration Stuck**
|
|
263
|
+
```ruby
|
|
264
|
+
# Check for long-running queries
|
|
265
|
+
ActiveRecord::Base.connection.execute("SELECT * FROM pg_stat_activity WHERE state = 'active'")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Schema Not Found**
|
|
269
|
+
```ruby
|
|
270
|
+
# Verify schema exists
|
|
271
|
+
if !PgMultitenantSchemas::SchemaSwitcher.schema_exists?('tenant_name')
|
|
272
|
+
PgMultitenantSchemas::Migrator.setup_tenant('tenant_name')
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Permission Errors**
|
|
277
|
+
```ruby
|
|
278
|
+
# Check database permissions
|
|
279
|
+
ActiveRecord::Base.connection.execute("SELECT has_schema_privilege('tenant_schema', 'USAGE')")
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## 🔗 Related Components
|
|
283
|
+
|
|
284
|
+
- **[SchemaSwitcher](schema_switcher.md)**: Core schema operations used by Migrator
|
|
285
|
+
- **[Context](context.md)**: Tenant context management during migrations
|
|
286
|
+
- **[Configuration](configuration.md)**: Migrator configuration options
|
|
287
|
+
- **[Rails Integration](rails_integration.md)**: Framework integration features
|
|
288
|
+
|
|
289
|
+
## 📝 Examples
|
|
290
|
+
|
|
291
|
+
See [examples/migration_workflow.rb](../examples/) for complete usage examples and [rake tasks documentation](../lib/pg_multitenant_schemas/tasks/) for command-line usage.
|