module MixedGauge # Offers database related Rake tasks module DatabaseTasks class << self # @return [Boolean] def ar5? ActiveRecord::VERSION::MAJOR == 5 end # @return [Boolean] def ar4? ActiveRecord::VERSION::MAJOR == 4 end # @return [Boolean] def ar42? ar4? && ActiveRecord::VERSION::MINOR == 2 end # @return [Boolean] def ar41? ar4? && ActiveRecord::VERSION::MINOR == 1 end # @return [Boolean] def ar417_above? ar41? && ActiveRecord::VERSION::TINY > 7 end # Show information of database sharding config. def info puts 'All clusters registered to mixed_gauge' puts clusters.each do |cluster| puts "= Cluster: #{cluster.name} =" cluster.connections.each do |name| puts "- #{name}" end puts end end # @private # @param [String] task_name # @return [Rake::Task] def to_rake_task(task_name) Rake::Task[task_name] end # @private # @return [Array] def cluster_names MixedGauge.config.cluster_configs.keys end # @private # @return [Array] def clusters MixedGauge.config.cluster_configs.values end # @private # @return [MixedGauge::ClusterConfig] # @raise [KeyError] def fetch_cluster_config(cluster_name) MixedGauge.config.fetch_cluster_config(cluster_name) end # For mock-ablity # @private def exit_with_error exit 1 end end # TasksForMultipleClusters module TasksForMultipleClusters # @param [String] task_name def invoke_task_for_all_clusters(task_name) cluster_names.each do |cluster_name| invoke_task(task_name, cluster_name) end end # @private # @param [String] name # @param [Symbol] cluster_name def invoke_task(name, cluster_name) task_name = "mixed_gauge:#{name}" to_rake_task(task_name).invoke(cluster_name.to_s) to_rake_task(task_name).reenable end end extend TasksForMultipleClusters # Organize cluster config and handle error for invalid args, call single # cluster task with each single connection config. module TaskOrganizerForSingleClusterTask # @param [Hash{Symbol => String}] args def create_all_databases(args) exec_task_for_all_databases('create', args) end # @param [Hash{Symbol => String}] args def drop_all_databases(args) exec_task_for_all_databases('drop', args) end # @param [Hash{Symbol => String}] args def load_schema_all_databases(args) exec_task_for_all_databases('load_schema', args) end private # @param [String] task_name # @param [Hash{Symbol => String}] args def exec_task_for_all_databases(task_name, args) cluster_name = cluster_name_or_error(task_name, args) cluster = cluster_or_error(cluster_name) cluster.connections.each do |connection_name| __send__(task_name, connection_name.to_s) end end # @param [String] name A task name # @param [Hash{Symbol => String}] args # @return [String] def cluster_name_or_error(name, args) unless (cluster_name = args[:cluster_name]) $stderr.puts <<-MSG Missing cluster_name. Find cluster_name via `rake mixed_gauge:info` then call `rake "mixed_gauge:#{name}[$cluster_name]"`. MSG exit_with_error end cluster_name end # @param [String] cluster_name # @return [MixedGauge::ClusterConfig] def cluster_or_error(cluster_name) fetch_cluster_config(cluster_name.to_sym) rescue KeyError $stderr.puts %(cluster name "#{cluster_name}" not found.) exit_with_error end end extend TaskOrganizerForSingleClusterTask # Create, drop, load_schema for single connection config. module TasksForSingleConnection # @param [String] connection_name def create(connection_name) configuration = ActiveRecord::Base.configurations[connection_name] ActiveRecord::Tasks::DatabaseTasks.create(configuration) # Re-configure using configuration with database ActiveRecord::Base.establish_connection(configuration) end # @param [String] connection_name def drop(connection_name) configuration = ActiveRecord::Base.configurations[connection_name] ActiveRecord::Tasks::DatabaseTasks.drop(configuration) end # @param [String] connection_name def load_schema(connection_name) configuration = ActiveRecord::Base.configurations[connection_name] if ar5? ActiveRecord::Tasks::DatabaseTasks.load_schema(configuration, :ruby) elsif ar42? || ar417_above? ActiveRecord::Tasks::DatabaseTasks.load_schema_for(configuration, :ruby) elsif ar41? ActiveRecord::Base.establish_connection(configuration) ActiveRecord::Tasks::DatabaseTasks.load_schema(:ruby) else raise "This version of ActiveRecord is not supported: v#{ActiveRecord::VERSION::STRING}" end end end extend TasksForSingleConnection end end