tenant_realm 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec5080c5a6b4e997fd094811df564e8cb6c7520030a1fb0617917a155dd05223
4
- data.tar.gz: 159100e048f540997d9e9ffa33ba215c035357573bb297a65afa52bd6547d593
3
+ metadata.gz: cb38988c0c6f15c4ab3ad38292bf08b4f1f3f30579d4c50b6fe992748f9c4c53
4
+ data.tar.gz: '0740480bc624fbd480c00dee419d442b3358093b12b5a080787cba77898708b7'
5
5
  SHA512:
6
- metadata.gz: 789611a5e9bc41b794a65e39d4d4cb48a69ad6d37a6d1bde72cb10e6f2bf499278f6715c5f50a7ba26023360408919bf921e33e72b9b994263747582eb0e8dc8
7
- data.tar.gz: a7dc2cddb27f123a9772bd53d4e4b1f3d39f9f5cad245f83de9329aa9c3bd6acebde917cb42ce84927b12b896396f8837fe715f5f22ede2cbcec365cb2d72bfc
6
+ metadata.gz: 2babc4881ad94fbd81ae8356de99ea1ba9b3cd970ac78ef5a3ccbde642c5cedffa5560b36a0e27cb88eed3d3b30f4300d21811edce64cb4149abf7070cbf64ac
7
+ data.tar.gz: a0fd3f716507576ba08520997faeb93f6748c383c523e96266ec5fd7c9969e36e66e948cf39630d8caa09642ac36ccaf6e8fbab52b4bb5c474f012885925e75c
@@ -5,6 +5,16 @@ namespace :tenant_realm do
5
5
  task migrate: :environment do
6
6
  tenants = TenantRealm::Tenant.tenants
7
7
 
8
+ puts 'Migrating primary'
9
+ root_db_config = TenantRealm::DbContext.root_db_config
10
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(root_db_config) do
11
+ ActiveRecord::Tasks::DatabaseTasks.migrate
12
+ TenantRealm::DbContext.dump_schema(
13
+ shard: :primary,
14
+ db_config: root_db_config
15
+ )
16
+ end
17
+
8
18
  tenants.each do |tenant|
9
19
  shard = TenantRealm::Utils.shard_name_from_tenant(tenant:)
10
20
 
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :tenant_realm do
4
+ desc 'Rollback db for all tenants'
5
+ task rollback: :environment do
6
+ tenants = TenantRealm::Tenant.tenants
7
+
8
+ puts 'Rollback primary'
9
+ Rake::Task['db:rollback:primary'].invoke
10
+ Rake::Task['db:rollback:primary'].reenable
11
+
12
+ tenants.each do |tenant|
13
+ shard = TenantRealm::Utils.shard_name_from_tenant(tenant:)
14
+
15
+ puts "Rollback #{shard}"
16
+
17
+ db_config = TenantRealm::Utils.dig_db_config(tenant:)
18
+
19
+ if db_config.blank?
20
+ puts "Skip Rollback #{shard}"
21
+
22
+ next
23
+ end
24
+
25
+ Rake::Task["db:rollback:#{shard}"].invoke
26
+ Rake::Task["db:rollback:#{shard}"].reenable
27
+ end
28
+ end
29
+ end
@@ -4,7 +4,7 @@ module TenantRealm
4
4
  module Cache
5
5
  class BaseCache
6
6
  class << self
7
- def cache_tenants(_tenants)
7
+ def cache_tenants(tenants:)
8
8
  raise NotImplementedError
9
9
  end
10
10
 
@@ -12,11 +12,11 @@ module TenantRealm
12
12
  raise NotImplementedError
13
13
  end
14
14
 
15
- def cache_tenant(_tenant)
15
+ def cache_tenant(tenant:)
16
16
  raise NotImplementedError
17
17
  end
18
18
 
19
- def tenant(_identifier)
19
+ def tenant(identifier:)
20
20
  raise NotImplementedError
21
21
  end
22
22
 
@@ -9,7 +9,7 @@ module TenantRealm
9
9
  module Cache
10
10
  class KredisCache < BaseCache
11
11
  class << self
12
- def cache_tenants(tenants)
12
+ def cache_tenants(tenants:)
13
13
  return if tenants.blank?
14
14
 
15
15
  cached_tenants = tenants_kredis
@@ -22,7 +22,9 @@ module TenantRealm
22
22
  cached_tenants.value&.map(&:deep_symbolize_keys) || []
23
23
  end
24
24
 
25
- def cache_tenant(tenant)
25
+ def cache_tenant(tenant:)
26
+ return tenant if tenant.blank?
27
+
26
28
  tenant_unique_keys(tenant).each do |key|
27
29
  cached_tenant = tenant_kredis(key)
28
30
  cached_tenant.value = tenant
@@ -31,7 +33,7 @@ module TenantRealm
31
33
  tenant
32
34
  end
33
35
 
34
- def tenant(identifier)
36
+ def tenant(identifier:)
35
37
  cached_tenant = tenant_kredis(identifier)
36
38
  cached_tenant.value&.deep_symbolize_keys
37
39
  end
@@ -55,10 +55,10 @@ module TenantRealm
55
55
  YAML.dump(config, f)
56
56
  end
57
57
 
58
- ActiveRecord::Base.configurations.configurations << ActiveRecord::DatabaseConfigurations::HashConfig.new(
59
- Rails.env,
58
+ ActiveRecord::Base.configurations.configurations << build_db_hash_config(
60
59
  shard_name,
61
- tenant_shard_config
60
+ tenant_shard_config,
61
+ Rails.env
62
62
  )
63
63
 
64
64
  sym_shard = shard_name.to_sym
@@ -110,8 +110,30 @@ module TenantRealm
110
110
  db_config
111
111
  end
112
112
 
113
+ def dump_schema(db_config:, shard:)
114
+ return unless ActiveRecord.dump_schema_after_migration
115
+
116
+ schema_format = ENV.fetch('SCHEMA_FORMAT', ActiveRecord.schema_format).to_sym
117
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(
118
+ build_db_hash_config(
119
+ shard.to_s,
120
+ db_config,
121
+ Rails.env
122
+ ),
123
+ schema_format
124
+ )
125
+ end
126
+
113
127
  private
114
128
 
129
+ def build_db_hash_config(shard, db_config, env_name = Rails.env)
130
+ ActiveRecord::DatabaseConfigurations::HashConfig.new(
131
+ env_name,
132
+ shard,
133
+ db_config
134
+ )
135
+ end
136
+
115
137
  def build_connected_shards
116
138
  @@shards.keys.each_with_object({}) do |shard, shards|
117
139
  sym_shard = shard.to_sym
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # internal usage
4
+ # no need hash parameters
3
5
  module TenantRealm
4
6
  class Helpers
5
7
  class << self
@@ -10,42 +10,46 @@ module TenantRealm
10
10
  }
11
11
 
12
12
  class << self
13
- def tenants
13
+ def tenants(force_load: false)
14
14
  if cache.present?
15
- tenants = cache.tenants
16
- return tenants if tenants.present?
15
+ unless force_load
16
+ tenants = cache.tenants
17
+ return tenants if tenants.present?
18
+ end
17
19
 
18
20
  tenants = Utils.fetch_tenants
19
- cache.cache_tenants(tenants)
21
+ cache.cache_tenants(tenants:)
20
22
  tenants
21
23
  else
22
24
  Utils.fetch_tenants
23
25
  end
24
26
  end
25
27
 
26
- def tenant(identifier)
28
+ def tenant(identifier:, force_load: false)
27
29
  if cache.present?
28
- tenant = cache.tenant(identifier)
29
- return tenant if tenant.present?
30
+ unless force_load
31
+ tenant = cache.tenant(identifier:)
32
+ return tenant if tenant.present?
33
+ end
30
34
 
31
- tenant = Utils.fetch_tenant(identifier)
32
- cache.cache_tenant(tenant)
35
+ tenant = Utils.fetch_tenant(identifier:)
36
+ cache.cache_tenant(tenant:)
33
37
  tenant
34
38
  else
35
39
  Utils.fetch_tenant
36
40
  end
37
41
  end
38
42
 
39
- def cache_tenants(tenants)
43
+ def cache_tenants(tenants:)
40
44
  return Helpers.dev_log('Tenant Realm: Skip cache tenants because cache not configured') if cache.blank?
41
45
 
42
- cache.cache_tenants(tenants)
46
+ cache.cache_tenants(tenants:)
43
47
  end
44
48
 
45
- def cache_tenant(tenant)
49
+ def cache_tenant(tenant:)
46
50
  return Helpers.dev_log('Tenant Realm: Skip cache tenant because cache not configured') if cache.blank?
47
51
 
48
- cache.cache_tenant(tenant)
52
+ cache.cache_tenant(tenant:)
49
53
  end
50
54
 
51
55
  private
@@ -13,7 +13,7 @@ module TenantRealm
13
13
  (Config.fetch_tenants.call.presence || []).map(&:deep_symbolize_keys)
14
14
  end
15
15
 
16
- def fetch_tenant(identifier)
16
+ def fetch_tenant(identifier:)
17
17
  Helpers.raise_if_not_proc(Config.fetch_tenant, 'config.fetch_tenant')
18
18
 
19
19
  Config.fetch_tenant.call(identifier)&.deep_symbolize_keys
@@ -41,7 +41,7 @@ module TenantRealm
41
41
  shard.underscore
42
42
  end
43
43
 
44
- def identifier_resolver(request)
44
+ def identifier_resolver(request:)
45
45
  raise Error, 'config.identifier_resolver must be provided' if Config.identifier_resolver.blank?
46
46
 
47
47
  Helpers.raise_if_not_proc(Config.identifier_resolver, 'config.identifier_resolver')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TenantRealm
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
data/lib/tenant_realm.rb CHANGED
@@ -30,13 +30,13 @@ module TenantRealm
30
30
 
31
31
  return :primary if skip_switch_db
32
32
 
33
- identifier = Utils.identifier_resolver(request)
34
- tenant = Tenant.tenant(identifier)
33
+ identifier = Utils.identifier_resolver(request:)
34
+ tenant = Tenant.tenant(identifier:)
35
35
  db_config = Utils.dig_db_config(tenant:)
36
- shard = Utils.shard_name_from_tenant(tenant:)
37
36
 
38
37
  return :primary if db_config.blank?
39
38
 
39
+ shard = Utils.shard_name_from_tenant(tenant:)
40
40
  Config.current.tenant = tenant
41
41
  DbContext.add_shard(shard:, db_config:)
42
42
  ActiveRecord::Base.connects_to(shards: DbContext.connected_shards)
data/tenant_realm.gemspec CHANGED
@@ -34,6 +34,10 @@ Gem::Specification.new do |spec|
34
34
  .vscode/settings.json
35
35
  LICENSE.txt
36
36
  lefthook.yml
37
+ docs/
38
+ biome.json
39
+ package.json
40
+ pnpm-lock.yaml
37
41
  ]
38
42
  )
39
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tenant_realm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alpha
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-27 00:00:00.000000000 Z
11
+ date: 2024-01-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby on Rails gem to support multi-tenant
14
14
  email:
@@ -23,6 +23,7 @@ files:
23
23
  - lib/generators/templates/tenant_realm.tt
24
24
  - lib/generators/tenant_realm_generator.rb
25
25
  - lib/tasks/migrate.rake
26
+ - lib/tasks/rollback.rake
26
27
  - lib/tenant_realm.rb
27
28
  - lib/tenant_realm/cache/base_cache.rb
28
29
  - lib/tenant_realm/cache/kredis_cache.rb