diff --git a/.gitlab/ci/base.yml b/.gitlab/ci/base.yml index 3d7b2e6fc..12b0a00d6 100644 --- a/.gitlab/ci/base.yml +++ b/.gitlab/ci/base.yml @@ -68,41 +68,52 @@ name: redis:latest alias: redis +.docker_memcached: &docker_memcached + name: memcached:latest + alias: memcached + command: ["memcached", "-m", "256M"] + # service templates .services_mysql: &services_mysql services: - <<: *docker_mysql -.services_mysql_redis: &services_mysql_redis +.services_mysql_redis_memcached: &services_mysql_redis_memcached variables: REDIS_URL: "redis://redis:6379" + MEMCACHE_SERVERS: "memcached" services: - <<: *docker_mysql - <<: *docker_redis + - <<: *docker_memcached .services_postgresql: &services_postgresql services: - <<: *docker_postgresql -.services_postgresql_redis: &services_postgresql_redis +.services_postgresql_redis_memcached: &services_postgresql_redis_memcached variables: REDIS_URL: "redis://redis:6379" + MEMCACHE_SERVERS: "memcached" services: - <<: *docker_postgresql - <<: *docker_redis + - <<: *docker_memcached .services_mysql_postgresql: &services_mysql_postgresql services: - <<: *docker_mysql - <<: *docker_postgresql -.services_mysql_postgresql_redis: &services_mysql_postgresql_redis +.services_mysql_postgresql_redis_memcached: &services_mysql_postgresql_redis_memcached variables: REDIS_URL: "redis://redis:6379" + MEMCACHE_SERVERS: "memcached" services: - <<: *docker_mysql - <<: *docker_postgresql - <<: *docker_redis + - <<: *docker_memcached .services_postgresql_selenium: &services_postgresql_selenium services: @@ -133,10 +144,11 @@ - <<: *docker_selenium - <<: *docker_imap -.services_mysql_postgresql_elasticsearch_selenium_imap_redis: &services_mysql_postgresql_elasticsearch_selenium_imap_redis +.services_mysql_postgresql_elasticsearch_selenium_imap_redis_memcached: &services_mysql_postgresql_elasticsearch_selenium_imap_redis_memcached variables: ELASTICSEARCH_TAG: 'stable' REDIS_URL: "redis://redis:6379" + MEMCACHE_SERVERS: "memcached" services: - <<: *docker_mysql - <<: *docker_postgresql @@ -144,6 +156,7 @@ - <<: *docker_selenium - <<: *docker_imap - <<: *docker_redis + - <<: *docker_memcached # we need at least one job to store and include this template # but we skip this via 'only' -> 'variables' -> '$IGNORE' diff --git a/.gitlab/ci/browser-core.yml b/.gitlab/ci/browser-core.yml index a55bac857..0bb7b9172 100644 --- a/.gitlab/ci/browser-core.yml +++ b/.gitlab/ci/browser-core.yml @@ -19,7 +19,7 @@ include: - .env_base - .variables_es - .variables_app_restart_cmd - - .services_mysql_postgresql_elasticsearch_selenium_imap_redis + - .services_mysql_postgresql_elasticsearch_selenium_imap_redis_memcached variables: RAILS_ENV: "production" script: @@ -53,7 +53,7 @@ include: extends: - .env_base - .variables_app_restart_cmd - - .services_mysql_postgresql_redis + - .services_mysql_postgresql_redis_memcached variables: RAILS_ENV: "production" @@ -63,7 +63,7 @@ include: extends: - .env_base - .variables_es - - .services_mysql_postgresql_elasticsearch_selenium_imap_redis + - .services_mysql_postgresql_elasticsearch_selenium_imap_redis_memcached variables: RAILS_ENV: "test" REDIS_URL: "redis://redis:6379" diff --git a/.gitlab/ci/browser-integration.yml b/.gitlab/ci/browser-integration.yml index c4d5f1504..629189765 100644 --- a/.gitlab/ci/browser-integration.yml +++ b/.gitlab/ci/browser-integration.yml @@ -15,7 +15,7 @@ include: - .env_base - .variables_app_restart_cmd - .variables_es - - .services_mysql_postgresql_elasticsearch_selenium_imap_redis + - .services_mysql_postgresql_elasticsearch_selenium_imap_redis_memcached variables: RAILS_ENV: "test" script: diff --git a/.gitlab/ci/rspec.yml b/.gitlab/ci/rspec.yml index e3355b17c..3b161d298 100644 --- a/.gitlab/ci/rspec.yml +++ b/.gitlab/ci/rspec.yml @@ -36,7 +36,7 @@ rspec:integration: stage: test extends: - .env_base - - .services_mysql_postgresql_redis + - .services_mysql_postgresql_redis_memcached - .rspec_integration_rules variables: RAILS_ENV: "test" diff --git a/.gitlab/ci/rspec/mysql.yml b/.gitlab/ci/rspec/mysql.yml index 7c40a8d97..2a6312169 100644 --- a/.gitlab/ci/rspec/mysql.yml +++ b/.gitlab/ci/rspec/mysql.yml @@ -1,11 +1,11 @@ rspec:mysql: stage: test extends: - - .services_mysql_redis + - .services_mysql_redis_memcached - .template_rspec rspec:mysql:db_reset: stage: test extends: - - .services_mysql_redis + - .services_mysql_redis_memcached - .template_rspec_db_reset diff --git a/.gitlab/ci/rspec/postgresql.yml b/.gitlab/ci/rspec/postgresql.yml index e2b7e5c65..ed20db802 100644 --- a/.gitlab/ci/rspec/postgresql.yml +++ b/.gitlab/ci/rspec/postgresql.yml @@ -1,11 +1,11 @@ rspec:postgresql: stage: test extends: - - .services_postgresql_redis + - .services_postgresql_redis_memcached - .template_rspec rspec:postgresql:db_reset: stage: test extends: - - .services_postgresql_redis + - .services_postgresql_redis_memcached - .template_rspec_db_reset diff --git a/.gitlab/ci/unit/mysql.yml b/.gitlab/ci/unit/mysql.yml index bd7e5e9e4..59d03c286 100644 --- a/.gitlab/ci/unit/mysql.yml +++ b/.gitlab/ci/unit/mysql.yml @@ -1,5 +1,5 @@ unit:mysql: stage: test extends: - - .services_mysql_redis + - .services_mysql_redis_memcached - .template_unit \ No newline at end of file diff --git a/.gitlab/ci/unit/postgresql.yml b/.gitlab/ci/unit/postgresql.yml index 4bfd7ed43..29a0285f2 100644 --- a/.gitlab/ci/unit/postgresql.yml +++ b/.gitlab/ci/unit/postgresql.yml @@ -1,5 +1,5 @@ unit:postgresql: stage: test extends: - - .services_postgresql_redis + - .services_postgresql_redis_memcached - .template_unit \ No newline at end of file diff --git a/.gitlab/configure_environment.rb b/.gitlab/configure_environment.rb index 479200fe0..e61e17c19 100755 --- a/.gitlab/configure_environment.rb +++ b/.gitlab/configure_environment.rb @@ -23,17 +23,30 @@ class ConfigureEnvironment def self.configure_redis if ENV['REDIS_URL'].nil? || ENV['REDIS_URL'].empty? # rubocop:disable Rails/Blank - puts 'Redis is not available, using File as web socket session back end.' + puts 'Redis is not available, using File as web socket session store.' return end if [true, false].sample - puts 'Using Redis as web socket session back end.' + puts 'Using Redis as web socket session store.' return end - puts 'Using File as web socket session back end.' + puts 'Using File as web socket session store.' @env_file_content += "unset REDIS_URL\n" end + def self.configure_memcached + if ENV['MEMCACHE_SERVERS'].nil? || ENV['MEMCACHE_SERVERS'].empty? # rubocop:disable Rails/Blank + puts 'Memcached is not available, using File as Rails cache store.' + return + end + if [true, false].sample + puts 'Using memcached as Rails cache store.' + return + end + puts "Using Zammad's file store as Rails cache store." + @env_file_content += "unset MEMCACHE_SERVERS\n" + end + def self.configure_database # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity if File.exist? File.join(__dir__, '../config/database.yml') @@ -103,6 +116,7 @@ class ConfigureEnvironment def self.run configure_redis + configure_memcached configure_database write_env_file end diff --git a/config/application.rb b/config/application.rb index baeaa07ef..1cda3131d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -47,10 +47,18 @@ module Zammad config.api_path = '/api/v1' # define cache store - config.cache_store = :zammad_file_store, Rails.root.join('tmp', "cache_file_store_#{Rails.env}"), { expires_in: 7.days } + config.cache_store = if ENV['MEMCACHE_SERVERS'].present? + [:mem_cache_store, ENV['MEMCACHE_SERVERS'], { expires_in: 7.days }] + else + [:zammad_file_store, Rails.root.join('tmp', "cache_file_store_#{Rails.env}"), { expires_in: 7.days }] + end # define websocket session store - config.websocket_session_store = ENV['REDIS_URL'] ? :redis : :file + config.websocket_session_store = if ENV['REDIS_URL'].present? + :redis + else + :file + end # Rails 6.1 returns false when the enqueuing is aborted. config.active_job.return_false_on_aborted_enqueue = true diff --git a/config/initializers/log_cache_store.rb b/config/initializers/log_cache_store.rb new file mode 100644 index 000000000..ce31b3dcc --- /dev/null +++ b/config/initializers/log_cache_store.rb @@ -0,0 +1,7 @@ +# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/ + +if Rails.application.config.cache_store.first.eql? :mem_cache_store + Rails.logger.info 'Using memcached as Rails cache store.' +else + Rails.logger.info "Using Zammad's file store as Rails cache store." +end diff --git a/config/initializers/log_websocket_session_store.rb b/config/initializers/log_websocket_session_store.rb new file mode 100644 index 000000000..cb4e659e8 --- /dev/null +++ b/config/initializers/log_websocket_session_store.rb @@ -0,0 +1,7 @@ +# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/ + +if Rails.application.config.websocket_session_store.eql? :redis + Rails.logger.info 'Using Redis as web socket session store.' +else + Rails.logger.info 'Using File as web socket session store.' +end diff --git a/test/unit/notification_factory_mailer_test.rb b/test/unit/notification_factory_mailer_test.rb index faad9abf1..a3a689d8b 100644 --- a/test/unit/notification_factory_mailer_test.rb +++ b/test/unit/notification_factory_mailer_test.rb @@ -281,6 +281,11 @@ class NotificationFactoryMailerTest < ActiveSupport::TestCase agent1.save travel 30.seconds + if Rails.application.config.cache_store.first.eql? :mem_cache_store + # External memcached does not support time travel, so clear the cache to avoid an outdated match. + Cache.clear + end + result = NotificationFactory::Mailer.notification_settings(agent1, ticket1, 'create') assert_equal(true, result[:channels][:online]) assert_equal(true, result[:channels][:email]) diff --git a/test/unit/ticket_notification_test.rb b/test/unit/ticket_notification_test.rb index e2031c23f..609ed1a6e 100644 --- a/test/unit/ticket_notification_test.rb +++ b/test/unit/ticket_notification_test.rb @@ -666,6 +666,10 @@ class TicketNotificationTest < ActiveSupport::TestCase @agent2.save! travel 1.minute # to skip loopup cache in Transaction::Notification + if Rails.application.config.cache_store.first.eql? :mem_cache_store + # External memcached does not support time travel, so clear the cache to avoid an outdated match. + Cache.clear + end # create ticket in group ApplicationHandleInfo.current = 'scheduler.postmaster' @@ -732,6 +736,10 @@ class TicketNotificationTest < ActiveSupport::TestCase @agent2.save! travel 1.minute # to skip loopup cache in Transaction::Notification + if Rails.application.config.cache_store.first.eql? :mem_cache_store + # External memcached does not support time travel, so clear the cache to avoid an outdated match. + Cache.clear + end # create ticket in group ApplicationHandleInfo.current = 'scheduler.postmaster' @@ -798,6 +806,10 @@ class TicketNotificationTest < ActiveSupport::TestCase @agent2.save! travel 1.minute # to skip loopup cache in Transaction::Notification + if Rails.application.config.cache_store.first.eql? :mem_cache_store + # External memcached does not support time travel, so clear the cache to avoid an outdated match. + Cache.clear + end # create ticket in group ApplicationHandleInfo.current = 'scheduler.postmaster' @@ -877,6 +889,10 @@ class TicketNotificationTest < ActiveSupport::TestCase @agent2.save! travel 1.minute # to skip loopup cache in Transaction::Notification + if Rails.application.config.cache_store.first.eql? :mem_cache_store + # External memcached does not support time travel, so clear the cache to avoid an outdated match. + Cache.clear + end # create ticket in group ApplicationHandleInfo.current = 'scheduler.postmaster'