Browse Source

Add max_allowed_packet check to MySQL initializer (fixes #2034)

Ryan Lue 6 years ago
parent
commit
67e8b0a2d2

+ 74 - 37
config/initializers/db_preferences_mysql.rb

@@ -1,40 +1,77 @@
-# mysql
-if ActiveRecord::Base.connection_config[:adapter] == 'mysql2'
-  Rails.application.config.db_4bytes_utf8 = false
-  Rails.application.config.db_null_byte = true
-
-  # mysql version check
-  #  mysql example: "5.7.3"
-  #  mariadb example: "10.1.17-MariaDB"
-  server_version = ActiveRecord::Base.connection.select_rows('SHOW VARIABLES LIKE \'version\'')[0][1]
-  raise 'Unable to retrive database version' if !server_version
-  (server_version, server_vendor) = server_version.split('-')
-  if !server_vendor
-    server_vendor = 'MySQL'
+return if ActiveRecord::Base.connection_config[:adapter] != 'mysql2'
+
+Rails.application.config.db_4bytes_utf8 = false
+Rails.application.config.db_null_byte = true
+connection = ActiveRecord::Base.connection
+
+# rubocop:disable Rails/Output
+# rubocop:disable Rails/Exit
+# rubocop:disable Layout/IndentHeredoc
+
+# Version check --------------------------------------------------------------
+#  mysql example: "5.7.3"
+#  mariadb example: "10.1.17-MariaDB"
+server_version = connection.execute('SELECT @@version;').first.first
+raise 'Unable to retrive database version' if server_version.blank?
+version_number = Gem::Version.new(server_version.split('-').first)
+vendor         = server_version.split('-').second || 'MySQL'
+
+case vendor
+when 'MySQL'
+  if version_number < Gem::Version.new('5.6')
+    printf "\e[31m" # ANSI red
+    puts <<~MSG
+    Error: Incompatible database backend version
+    (MySQL 5.6+ required; #{version_number} found)
+    MSG
+    printf "\e[0m" # ANSI normal
+    exit 1
   end
-  (major, minor) = server_version.split('.')
-  if server_vendor == 'MySQL'
-    if major.to_i < 5 || (major.to_i == 5 && minor.to_i < 6)
-      # rubocop:disable Rails/Output
-      # rubocop:disable Rails/Exit
-      p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-      p '+ I\'m sorry, MySQL 5.6+ is required                 +'
-      p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-      exit 1
-      # rubocop:enable Rails/Exit
-      # rubocop:enable Rails/Output
-    end
-
-  elsif server_vendor == 'MariaDB'
-    if major.to_i < 10
-      # rubocop:disable Rails/Output
-      # rubocop:disable Rails/Exit
-      p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-      p '+ I\'m sorry, MariaDB 10.0+ is required              +'
-      p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-      exit 1
-      # rubocop:enable Rails/Exit
-      # rubocop:enable Rails/Output
-    end
+when 'MariaDB'
+  if version_number < Gem::Version.new('10.0')
+    printf "\e[31m" # ANSI red
+    puts <<~MSG
+    Error: Incompatible database backend version
+    (MariaDB 10.0+ required; #{version_number} found)
+    MSG
+    printf "\e[0m" # ANSI normal
+    exit 1
   end
 end
+
+# Configuration check --------------------------------------------------------
+# Before MySQL 8.0, the default value of max_allowed_packet was 1MB - 4MB,
+# which is impractically small and can lead to failures processing emails.
+#
+# See https://github.com/zammad/zammad/issues/1759
+#     https://github.com/zammad/zammad/issues/1970
+#     https://github.com/zammad/zammad/issues/2034
+max_allowed_packet = connection.execute('SELECT @@max_allowed_packet;').first.first
+max_allowed_packet_mb = max_allowed_packet / 1024 / 1024
+
+if max_allowed_packet_mb <= 4
+  printf "\e[31m" # ANSI red
+  puts <<~MSG
+  Error: Database config value 'max_allowed_packet' too small (#{max_allowed_packet_mb}MB)
+  Please increase this value in your #{vendor} configuration (64MB+ recommended).
+  MSG
+  printf "\e[0m" # ANSI normal
+  exit 1
+end
+
+if connection.execute("SHOW tables LIKE 'settings';").any? &&
+   Setting.get('postmaster_max_size').present? &&
+   Setting.get('postmaster_max_size') > max_allowed_packet_mb
+  printf "\e[33m" # ANSI yellow
+  puts <<~MSG
+  Warning: Database config value 'max_allowed_packet' less than Zammad setting 'Maximum Email Size'
+  Zammad will fail to process emails (both incoming and outgoing)
+  larger than the value of 'max_allowed_packet' (#{max_allowed_packet_mb}MB).
+  Please increase this value in your #{vendor} configuration accordingly.
+  MSG
+  printf "\e[0m" # ANSI normal
+end
+
+# rubocop:enable Rails/Exit
+# rubocop:enable Rails/Output
+# rubocop:enable Layout/IndentHeredoc

+ 25 - 19
config/initializers/db_preferences_postgresql.rb

@@ -1,23 +1,29 @@
-# postgresql
-if ActiveRecord::Base.connection_config[:adapter] == 'postgresql'
-  Rails.application.config.db_case_sensitive = true
-  Rails.application.config.db_like = 'ILIKE'
-  Rails.application.config.db_null_byte = false
+return if ActiveRecord::Base.connection_config[:adapter] != 'postgresql'
 
-  # postgresql version check
-  #  example output: "9.5.0"
-  server_version = ActiveRecord::Base.connection.select_rows('SHOW server_version;')[0][0]
-  (major, minor) = server_version.split('.')
-  if major.to_i < 9 || (major.to_i == 9 && minor.to_i < 1)
+Rails.application.config.db_case_sensitive = true
+Rails.application.config.db_like = 'ILIKE'
+Rails.application.config.db_null_byte = false
 
-    # rubocop:disable Rails/Output
-    # rubocop:disable Rails/Exit
-    p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-    p '+ I\'m sorry, PostgreSQL 9.1+ is required            +'
-    p '+++++++++++++++++++++++++++++++++++++++++++++++++++++'
-    exit 1
-    # rubocop:enable Rails/Exit
-    # rubocop:enable Rails/Output
+# rubocop:disable Rails/Output
+# rubocop:disable Rails/Exit
+# rubocop:disable Layout/IndentHeredoc
 
-  end
+# Version check --------------------------------------------------------------
+#  example output: "9.5.0"
+#                  "10.3 (Debian 10.3-2)"
+server_version = ActiveRecord::Base.connection.execute('SHOW server_version;').first['server_version']
+version_number = Gem::Version.new(server_version.split.first)
+
+if version_number < Gem::Version.new('9.1')
+  printf "\e[31m" # ANSI red
+  puts <<~MSG
+  Error: Incompatible database backend version
+  (PostgreSQL 9.1+ required; #{version_number} found)
+  MSG
+  printf "\e[0m" # ANSI normal
+  exit 1
 end
+
+# rubocop:enable Rails/Exit
+# rubocop:enable Rails/Output
+# rubocop:enable Layout/IndentHeredoc