Class: Nando::MigrationWithoutTransaction

Inherits:
Migration
  • Object
show all
Defined in:
lib/nando/migration.rb

Instance Method Summary collapse

Methods inherited from Migration

#execute, #invalidate_postgresql_redis_cache!, #update_function

Constructor Details

#initialize(conn, version) ⇒ MigrationWithoutTransaction

Returns a new instance of MigrationWithoutTransaction.



38
39
40
41
# File 'lib/nando/migration.rb', line 38

def initialize (conn, version)
  super(conn, version)
  @conn.exec('DROP FUNCTION IF EXISTS sharding.create_company_shard(integer,text)')
end

Instance Method Details

#database_clusterObject

utils



305
306
307
# File 'lib/nando/migration.rb', line 305

def database_cluster
  @conn.exec("SHOW cloudware.cluster").to_a[0]["cloudware.cluster"].to_i
end

#down_on_schema(schema, running_migration_version, options, progress_feedback, &block) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/nando/migration.rb', line 196

def down_on_schema (schema, running_migration_version, options, progress_feedback, &block)
  with_new_connection(options) do
    @conn.transaction do |conn|
      # TODO: ensure this has the same behavior as "ActiveRecord::Base.transaction(requires_new: true)"
      if migration_ran_on_schema?(schema, running_migration_version, conn)
        # TODO: splited a "say_with_time", might need to review this
        puts "#{progress_feedback}Rolling back migration on schema #{schema['schema_name']}"
        block.call(schema['schema_name'], schema['id'], schema['use_sharded_company'].to_b, schema['tablespace_name'], schema['company_schema']) unless block.nil?
        migration_rolled_back_on_schema!(schema, running_migration_version, conn) if options[:record_on_schema_migrations]
      else
        puts "#{progress_feedback}Migration didn't run on schema #{schema['schema_name']}, skipping"
      end
    end
  end
end

#each_fiscal_year(schema, &block) ⇒ Object



112
113
114
115
# File 'lib/nando/migration.rb', line 112

def each_fiscal_year (schema, &block)
  return if block.nil?
  @conn.exec(%Q[SELECT * FROM "#{schema}"."fiscal_years"]).to_a.each(&block)
end

#each_user_template(schema_name, &block) ⇒ Object



149
150
151
152
# File 'lib/nando/migration.rb', line 149

def each_user_template (schema_name, &block)
  return if block.nil?
  @conn.exec(%Q[SELECT * FROM "accounting"."user_templates" WHERE schema_name='#{schema_name}' ORDER BY "id"]).to_a.each(&block)
end

#execute_migration(method) ⇒ Object



43
44
45
# File 'lib/nando/migration.rb', line 43

def execute_migration (method)
  self.send(method)
end

#get_accounting_companies_schemasObject



276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/nando/migration.rb', line 276

def get_accounting_companies_schemas
  get_schemas %Q[
    SELECT "accounting_companies"."company_id" AS "id",
           "accounting_companies"."schema_name",
           common.get_tablespace_name("accounting_companies"."schema_name") AS "tablespace_name",
           "companies"."schema_name" AS company_schema,
           "companies"."use_sharded_company"
      FROM "accounting"."accounting_companies"
      JOIN "public"."companies" ON "companies"."id" = "accounting_companies"."company_id"
     WHERE "companies"."is_deleted" IS DISTINCT FROM true
       AND "companies"."cluster" = #{database_cluster}
     ORDER BY "accounting_companies"."id"
  ]
end

#get_companies_schemasObject



262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/nando/migration.rb', line 262

def get_companies_schemas
  get_schemas %Q[
    SELECT "id",
           "schema_name",
           "use_sharded_company",
           common.get_tablespace_name("schema_name") AS "tablespace_name"
      FROM "public"."companies"
     WHERE "schema_name" IS NOT NULL
       AND "is_deleted" IS DISTINCT FROM true
       AND "companies"."cluster" = #{database_cluster}
     ORDER BY "id"
  ]
end

#get_companies_schemas_from_module(module_name) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/nando/migration.rb', line 245

def get_companies_schemas_from_module (module_name)
  get_schemas %Q[
    SELECT "companies"."id",
           "companies"."schema_name",
           "companies"."use_sharded_company",
           common.get_tablespace_name("companies"."schema_name") AS "tablespace_name"
      FROM "public"."company_modules"
      JOIN "public"."companies" ON "companies"."id" = "company_modules"."company_id"
     WHERE "companies"."schema_name" IS NOT NULL
       AND "company_modules"."name" = '#{module_name}'
       AND "company_modules"."has_schema_structure"
       AND "companies"."is_deleted" IS DISTINCT FROM true
       AND "companies"."cluster" = #{database_cluster}
     ORDER BY "id"
  ]
end

#get_migration_versionObject



314
315
316
# File 'lib/nando/migration.rb', line 314

def get_migration_version
  return @version
end

#get_schemas(query) ⇒ Object



309
310
311
312
# File 'lib/nando/migration.rb', line 309

def get_schemas (query)
  schemas_rows = @conn.exec(query).to_a
  return schemas_rows
end

#get_sharded_company_schemasObject

schema queries



230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/nando/migration.rb', line 230

def get_sharded_company_schemas
  get_schemas %Q[
    SELECT "id",
           "schema_name",
           "use_sharded_company",
           common.get_tablespace_name("schema_name") AS "tablespace_name"
      FROM "public"."companies"
     WHERE "schema_name" IS NOT NULL
       AND "use_sharded_company"
       AND "is_deleted" IS DISTINCT FROM true
       AND "companies"."cluster" = #{database_cluster}
     ORDER BY "id"
   ]
end

#get_user_schemasObject



291
292
293
294
295
296
297
298
299
300
# File 'lib/nando/migration.rb', line 291

def get_user_schemas
  get_schemas %Q[
    SELECT DISTINCT "user_id" AS "id",
           "schema_name",
           false AS "use_sharded_company",
           common.get_tablespace_name("schema_name") AS "tablespace_name"
      FROM "accounting"."user_templates"
     ORDER BY "id"
  ]
end

#migrate_accounting_companies(options = {}, &block) ⇒ Object

WORK OVER ACCOUNTING COMPANIES



85
86
87
88
89
# File 'lib/nando/migration.rb', line 85

def migrate_accounting_companies (options = {}, &block)
  return if block.nil?

  work_on_schemas(get_accounting_companies_schemas, 'accounting company', :up, options, &block)
end

#migrate_companies(module_name = nil, options = {}, &block) ⇒ Object

WORK OVER SHARDED COMPANIES, AND ALREADY SHARDED MODULES



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/nando/migration.rb', line 53

def migrate_companies (module_name = nil, options = {}, &block)
  return if block.nil?

  if module_name.nil?
    work_on_schemas(get_sharded_company_schemas, 'global company', :up, options, &block)
    # TODO: splited a "say_with_time", might need to review this
    puts "[PUBLIC] Running migration on unsharded companies"
    block.call('public', nil, nil, 'tablespace_000')
  elsif module_name.to_sym == :all
    work_on_schemas(get_companies_schemas, 'global company', :up, options, &block)
  else
    work_on_schemas(get_companies_schemas_from_module(module_name), 'global company', :up, options, &block)
  end
end

#migrate_fiscal_years(options = {}, &block) ⇒ Object



95
96
97
98
99
100
101
102
# File 'lib/nando/migration.rb', line 95

def migrate_fiscal_years (options = {}, &block)
  return if block.nil?
  work_on_schemas get_accounting_companies_schemas, 'accounting company', :up, options do |schema, company_id, use_sharded_company, tablespace_name, company_schema|
    each_fiscal_year(schema) do |fiscal_year|
      block.call schema, fiscal_year['table_prefix'], fiscal_year, company_id, tablespace_name, company_schema, use_sharded_company
    end
  end
end

#migrate_user_schemas(options = {}, &block) ⇒ Object

WORK OVER USER TEMPLATES



121
122
123
124
125
# File 'lib/nando/migration.rb', line 121

def migrate_user_schemas (options = {}, &block)
  return if block.nil?

  work_on_schemas(get_user_schemas, 'user template', :up, options, &block)
end

#migrate_user_templates(options = {}, &block) ⇒ Object



131
132
133
134
135
136
137
138
139
# File 'lib/nando/migration.rb', line 131

def migrate_user_templates (options = {}, &block)
  return if block.nil?

  work_on_schemas get_user_schemas, 'user template', :up, options do |schema, id, use_sharded_company, tablespace_name|
    each_user_template(schema) do |user_template|
      block.call(schema, user_template['table_prefix'], user_template, tablespace_name)
    end
  end
end

#migration_ran_on_schema!(schema, migration_version, conn = nil) ⇒ Object



327
328
329
330
331
332
333
334
# File 'lib/nando/migration.rb', line 327

def migration_ran_on_schema! (schema, migration_version, conn = nil)
  query = %Q[INSERT INTO "#{schema['schema_name']}"."#{@migration_table}" ("#{@migration_field}") VALUES ('#{migration_version}')]
  if conn.nil?
    @conn.exec(query)
  else
    conn.exec(query)
  end
end

#migration_ran_on_schema?(schema, migration_version, conn = nil) ⇒ Boolean

Returns:

  • (Boolean)


318
319
320
321
322
323
324
325
# File 'lib/nando/migration.rb', line 318

def migration_ran_on_schema? (schema, migration_version, conn = nil)
  query = %Q[SELECT 1 FROM "#{schema['schema_name']}"."#{@migration_table}" WHERE "#{@migration_field}" = '#{migration_version}']
  if conn.nil?
    @conn.exec(query).any?
  else
    conn.exec(query).any?
  end
end

#migration_rolled_back_on_schema!(schema, migration_version, conn = nil) ⇒ Object



336
337
338
339
340
341
342
343
# File 'lib/nando/migration.rb', line 336

def migration_rolled_back_on_schema! (schema, migration_version, conn = nil)
  query = %Q[DELETE FROM "#{schema['schema_name']}"."#{@migration_table}" WHERE "#{@migration_field}" = '#{migration_version}']
  if conn.nil?
    @conn.exec(query)
  else
    conn.exec(query)
  end
end

#rollback_accounting_companies(options = {}, &block) ⇒ Object



91
92
93
# File 'lib/nando/migration.rb', line 91

def rollback_accounting_companies(options = {}, &block)
  work_on_schemas(get_accounting_companies_schemas, 'accounting company', :down, options, &block)
end

#rollback_companies(module_name = nil, options = {}, &block) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/nando/migration.rb', line 68

def rollback_companies (module_name = nil, options = {}, &block)
  if module_name.nil?
    work_on_schemas(get_sharded_company_schemas, 'global company', :down, options, &block)
    # TODO: splited a "say_with_time", might need to review this
    puts "[PUBLIC] Rolling back migration on unsharded companies"
    block.call('public', nil, nil, 'tablespace_000')
  elsif module_name.to_sym == :all
    work_on_schemas(get_companies_schemas, 'global company', :down, options, &block)
  else
    work_on_schemas(get_companies_schemas_from_module(module_name), 'global company', :down, options, &block)
  end
end

#rollback_fiscal_years(options = {}, &block) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/nando/migration.rb', line 104

def rollback_fiscal_years (options = {}, &block)
  work_on_schemas get_accounting_companies_schemas, 'accounting company', :down, options do |schema, company_id, use_sharded_company, tablespace_name, company_schema|
    each_fiscal_year(schema) do |fiscal_year|
      block.call schema, fiscal_year['table_prefix'], fiscal_year, company_id, tablespace_name, company_schema, use_sharded_company
    end
  end
end

#rollback_user_schemas(options = {}, &block) ⇒ Object



127
128
129
# File 'lib/nando/migration.rb', line 127

def rollback_user_schemas (options = {}, &block)
  work_on_schemas(get_user_schemas, 'user template', :down, options, &block)
end

#rollback_user_templates(options = {}, &block) ⇒ Object



141
142
143
144
145
146
147
# File 'lib/nando/migration.rb', line 141

def rollback_user_templates (options = {}, &block)
  work_on_schemas get_user_schemas, 'user template', :down, options do |schema, id, use_sharded_company, tablespace_name|
    each_user_template(schema) do |user_template|
      block.call(schema, user_template['table_prefix'], user_template, tablespace_name)
    end
  end
end

#table_exists?(schema_name, table_name) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/nando/migration.rb', line 154

def table_exists? (schema_name, table_name)
  @conn.exec(%Q[SELECT 1 FROM "information_schema"."tables" WHERE "table_schema" = '#{schema_name}' AND "table_name" = '#{table_name}']).any?
end

#up_on_schema(schema, running_migration_version, options, progress_feedback, &block) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/nando/migration.rb', line 180

def up_on_schema (schema, running_migration_version, options, progress_feedback, &block)
  with_new_connection(options) do
    @conn.transaction do |conn|
      # TODO: ensure this has the same behavior as "ActiveRecord::Base.transaction(requires_new: true)"
      if migration_ran_on_schema?(schema, running_migration_version, conn)
        puts "#{progress_feedback}Migration already ran on schema #{schema['schema_name']}, skipping"
      else
        # TODO: splited a "say_with_time", might need to review this
        puts "#{progress_feedback}Running migration on schema #{schema['schema_name']}"
        block.call(schema['schema_name'], schema['id'], schema['use_sharded_company'].to_b, schema['tablespace_name'], schema['company_schema']) unless block.nil?
        migration_ran_on_schema!(schema, running_migration_version, conn) if options[:record_on_schema_migrations]
      end
    end
  end
end

#with_new_connection(options = {}, &block) ⇒ Object



212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/nando/migration.rb', line 212

def with_new_connection (options = {}, &block)
  options[:_internal_reset_counter] ||= 0
  if options[:_internal_reset_counter] == options[:max_schemas_per_conn] || ( 0 == options[:_internal_reset_counter] && !options[:statement_timeout].nil? )
    # TODO: what was the objective of this? Is a reset enough?
    # ActiveRecord::Base.connection.reset!()
    # ActiveRecord::Base.connection.raw_connection.reset
    # ActiveRecord::Base.connection.raw_connection.exec("SET statement_timeout TO #{0 == options[:statement_timeout]? "'48h'" : options[:statement_timeout]}") if options[:statement_timeout]
    @conn.reset()
    @conn.exec("SET statement_timeout TO #{0 == options[:statement_timeout]? "'48h'" : options[:statement_timeout]}") if options[:statement_timeout]
    options[:_internal_reset_counter] = 0
  end
  options[:_internal_reset_counter] +=1
  block.call unless block.nil?
end

#work_on_schemas(schemas, schema_type_description, direction, options, &block) ⇒ Object

helper methods



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/nando/migration.rb', line 161

def work_on_schemas (schemas, schema_type_description, direction, options, &block)
  options ||= {}
  options[:record_on_schema_migrations] = true unless options.has_key?(:record_on_schema_migrations)
  options[:use_public_schema] = true unless options.has_key?(:use_public_schema)

  schema_count = schemas.count.to_s
  options[:max_schemas_per_conn] ||= 200 # min_queries_per_conn / max_queries_per_conn
  options[:_internal_reset_counter] = 0

  running_migration_version = get_migration_version

  puts "#{direction == :up ? 'Migrating' : 'Rolling back'} on #{schema_count} #{schema_type_description} schema(s)"

  schemas.each_with_index do |schema, index|
    # create_schema_migrations_table_on_schema(schema) unless schema_migration_table_exists?(schema)
    send :"#{direction}_on_schema", schema, running_migration_version, options, "[#{(index + 1).to_s.rjust(schema_count.length)}/#{schema_count}] ", &block
  end
end