Продолжение: конфликт плагинов при назначении

Ранее у нас возникли проблемы с обновлением до последней версии Discourse. Как выяснилось, это было связано с проблемой плагина Assign и производственными данными, которую @angus помог нам выявить и устранить, удалив плагин.

В дальнейшем мы хотели бы снова включить плагин, но необходимо исключить возможность повторения критической ошибки, с которой мы столкнулись ранее. Ниже приведены детали, связанные с фрагментами логов, зафиксированными во время инцидента.

/var/www/discourse/plugins/discourse-assign/plugin.rb:284:in `block (2 levels) in activate!’

Трассировка стека:

> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:69:in `async_exec_params'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:69:in `exec_params'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:611:in `block (2 levels) in exec_no_cache'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:610:in `block in exec_no_cache'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract_adapter.rb:581:in `block (2 levels) in log'
> /usr/local/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract_adapter.rb:580:in `block in log'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract_adapter.rb:571:in `log'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:609:in `exec_no_cache'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:596:in `execute_and_clear'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/postgresql/database_statements.rb:81:in `exec_query'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:478:in `select'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:70:in `select_all'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/query_cache.rb:104:in `block in select_all'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/query_cache.rb:127:in `block in cache_sql'
> /usr/local/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/query_cache.rb:113:in `cache_sql'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/query_cache.rb:104:in `select_all'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:77:in `select_one'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/relation/finder_methods.rb:322:in `block in exists?'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/relation.rb:584:in `skip_query_cache_if_necessary'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/relation/finder_methods.rb:322:in `exists?'
> /var/www/discourse/plugins/discourse-assign/plugin.rb:69:in `block (2 levels) in activate!'
> /var/www/discourse/lib/plugin/instance.rb:188:in `public_send'
> /var/www/discourse/lib/plugin/instance.rb:188:in `block (2 levels) in add_to_class'
> /var/www/discourse/plugins/discourse-assign/plugin.rb:284:in `block (2 levels) in activate!'
> (eval):49:in `_fast_attributes'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:456:in `attributes'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:480:in `_serializable_hash'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:359:in `serializable_hash'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:347:in `as_json'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/json/encoding.rb:22:in `encode'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/json/encoding.rb:22:in `encode'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/core_ext/object/json.rb:41:in `to_json'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:331:in `to_json'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/multi_json-1.13.1/lib/multi_json/adapters/oj.rb:40:in `dump'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/multi_json-1.13.1/lib/multi_json/adapters/oj.rb:40:in `dump'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/multi_json-1.13.1/lib/multi_json/adapter.rb:25:in `dump'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/multi_json-1.13.1/lib/multi_json.rb:139:in `dump'
> /var/www/discourse/app/controllers/application_controller.rb:535:in `preload_current_user_data'
> /var/www/discourse/app/controllers/application_controller.rb:354:in `preload_json'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:426:in `block in make_lambda'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:198:in `block (2 levels) in halting'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:199:in `block in halting'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in `block in invoke_before'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in `each'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:513:in `invoke_before'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:131:in `run_callbacks'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/callbacks.rb:41:in `process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/rescue.rb:22:in `process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `block in instrument'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/notifications.rb:168:in `instrument'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/abstract_controller/base.rb:134:in `process'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionview-5.2.3/lib/action_view/rendering.rb:32:in `process'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiling_methods.rb:78:in `block in profile_method'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:191:in `dispatch'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_controller/metal.rb:252:in `dispatch'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:34:in `serve'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:52:in `block in serve'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `each'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/journey/router.rb:35:in `serve'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/routing/route_set.rb:840:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-protection-2.0.5/lib/rack/protection/frame_options.rb:31:in `call'
> /var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:68:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:25:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/head.rb:12:in `call'
> /var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
> /var/www/discourse/lib/middleware/anonymous_cache.rb:220:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:232:in `context'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:226:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/cookies.rb:670:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in `run_callbacks'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.0/lib/logster/middleware/reporter.rb:30:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in `call_app'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:28:in `call'
> /var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
> /var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in `call'
> /var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/method_override.rb:22:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiler.rb:171:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.2/lib/message_bus/rack/middleware.rb:57:in `call'
> /var/www/discourse/lib/middleware/request_tracker.rb:169:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `public_send'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `method_missing'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:68:in `block in call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `each'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `call'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:605:in `process_client'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:700:in `worker_loop'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:144:in `start'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/bin/unicorn:128:in `<top (required)>'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
> /var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'

Информация:

> ActiveRecord::StatementInvalid (PG::InvalidTextRepresentation: Ошибка: недопустимый синтаксис ввода для целого числа: «admins»
> LINE 1: …p_users". "user_id" = 15040 AND (groups.id in ('3', 'admins', '…
> ^
> : SELECT 1 AS one FROM "groups" INNER JOIN "group_users" ON "groups". "id" = "group_users". "group_id" WHERE "group_users". "user_id" = 15040 AND (groups.id in ('3', 'admins', 'RDSE')) LIMIT 1)
> /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.0.2/lib/patches/db/pg.rb:69:in `async_exec_params'

Пожалуйста, дайте знать, если потребуется дополнительная информация для продолжения работы. Спасибо.

Извините, я вас не понимаю. Конфликт с чем?

Вы уверены, что “group id 3 admins” верно?

@Mittineague Я подтвердил сегодня утром, что идентификатор группы для администраторов действительно является идентификатором группы по умолчанию.

Информация из логов, которую я привёл, относится к периоду простоя. Мы временно отключили плагин Assign, что сразу решило проблему и позволило нам снова успешно использовать Discourse.

Значение параметра сайта assign_allowed_on_groups находится в некорректном состоянии. Мы перешли от использования названий групп к использованию их идентификаторов.

(groups.id in (‘3’,‘admins’,'…

Чтобы исправить проблему, замените admins на идентификатор группы.

Как мне это изменить?

В папке Discourse вам следует:

  • Войти в контейнер, выполнив ./launcher enter app
  • Открыть консоль Rails, выполнив rails c

После входа в консоль вы можете запустить этот скрипт для исправления проблемы:

allowed_groups = SiteSetting.assign_allowed_on_groups.split('|')
allowed_groups.map! do |ag| 
  ag.to_i.to_s == ag ? ag : Group.select(:id).find_by(name: ag).id
end

SiteSetting.assign_allowed_on_groups = allowed_groups.join('|')

После выполнения вышеуказанных рекомендаций мне не удалось успешно запустить скрипт. Ниже приведён вывод попытки. Любые указания будут крайне полезны :pray:

app:/var/www/discourse# rails c

[1] pry(main)> allowed_groups = SiteSetting.assign_allowed_on_groups.split('|')

NoMethodError: undefined method `assign_allowed_on_groups' for #<Class:0x0000563ec4670260>

from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activerecord-5.2.3/lib/active_record/dynamic_matchers.rb:22:in `method_missing'

[2] pry(main)> allowed_groups.map! do |ag|

[2] pry(main)* ag.to_i.to_s == ag ? ag : Group.select(:id).find_by(name: ag).id

[2] pry(main)* end

NoMethodError: undefined method `map!' for nil:NilClass

from (pry):2:in `__pry__'

[3] pry(main)> SiteSetting.assign_allowed_on_groups = allowed_groups.join('|')

NoMethodError: undefined method `join' for nil:NilClass

from (pry):5:in `__pry__'

Похоже, у вас установлена старая версия плагина Discourse Assign … вы используете ветку tests-passed с последней версией Discourse Assign?

Давайте разберёмся в этом, @sam, и я сообщу вам, что обнаружу :+1:

Поскольку плагин Assign в настоящее время удалён, @sam, вы считаете, что переустановка плагина с последней версией может быть лучшим решением?

@sam @angus Сегодня вечером я снова попытался переустановить плагин Assign, но после входа в систему снова столкнулся с полным сбоем. Я записал логи сбоя, но не хотел бы публиковать их открыто, хотя готов отправить их через личные сообщения.

Есть ли какие-либо предложения, как двигаться дальше?

Вы находитесь на стабильной ветке? Установлены ли другие плагины, которые могут вызывать конфликт?

Думаю, да, так как я обновился из Master.

Только следующие, ничего, что бросилось бы мне в глаза.

Вам нужно было проделать некоторую работу, чтобы оказаться на (менее предпочтительной) стабильной ветке. Видите ли вы что-то вроде

version: stable

в вашем app.yml? Если вы находитесь на stable, то ситуация может быть более сложной.

Вы можете попробовать запустить ./discourse-doctor. Также убедитесь, что выполнили git pull перед повторной сборкой.

57%20PM

Это то, что я вижу в своём App.yml

Есть ли здесь какие-либо дополнительные идеи, которые помогут нам продвинуться с плагином Assign? @angus?

Привет, @Jim.Morrison,

Можешь запустить это в консоли и показать мне вывод:

DB.query_single(<<~SQL SELECT site_settings.value FROM site_settings WHERE site_settings.name = 'assign_allowed_on_groups' SQL ).first.to_s.split('|')

Думаю, мой скрипт не сработал, потому что плагин был отключен.

Направил тебе детали из консоли в личные сообщения. Спасибо, @Roman!

После долгих обсуждений с @Roman нам наконец удалось решить эту проблему!

После выполнения запроса, который написал Roman, чтобы устранить конфликт данных, добавления плагина Assign и последующей пересборки приложения, я добился успеха!

Roman стал огромной поддержкой на протяжении всего этого процесса, и я не могу достаточно высоко оценить его вклад! Большое спасибо за сотрудничество со мной, @Roman!