Продолжение: ThinkingSphinx и обратный вызов не обновляют индекс после создания записи
Тестирую поиск с rspec и chrome headless.
С индексами SQL я использовал эту спецификацию функции + помощник: https://pastebin.com/9m7WbvN7
Заменены SQL-индексы на реальное время:
ThinkingSphinx::Index.define :review, with: :real_time do
indexes title, sortable: true
indexes body
indexes author.username, as: :author, sortable: true
has author_id, :type => :integer
has created_at, :type => :timestamp
has updated_at, :type => :timestamp
end
В режиме разработки все работает, но тесты стали падать.
Пробовал редактировать sphinx_helper по мануалу: https://freelancing-gods.com/thinking-sphinx/v5/testing.html
Но я потерпел неудачу и получаю сообщение об ошибке:
An error occurred in a `before(:suite)` hook.
Failure/Error: ThinkingSphinx::Test.start_with_autostop
Riddle::CommandFailedError:
Sphinx command failed to execute
# /gems/riddle-2.4.3/lib/riddle/execute_command.rb:25:in `call'
# /gems/riddle-2.4.3/lib/riddle/execute_command.rb:7:in `call'
# /gems/riddle-2.4.3/lib/riddle/controller.rb:33:in `index'
# /gems/thinking-sphinx-5.5.1/lib/thinking_sphinx/test.rb:13:in `start'
# /gems/thinking-sphinx-5.5.1/lib/thinking_sphinx/test.rb:19:in `start_with_autostop'
# ./spec/sphinx_helper.rb:14:in `block (2 levels) in <top (required)>'
Обновление: добавление порта ничего не изменило.
config/thinking_sphinx.yml:
test:
mysql41: 9307
Если вы запустите его вручную через rake, файл конфигурации будет создан, и sphinx успешно запустится:
bundle exec rake ts:configure RAILS_ENV=test
Generating configuration to /home/vagrant/data/app/config/test.sphinx.conf
bundle exec rake ts:start RAILS_ENV=test
using config file '/home/vagrant/data/app/config/test.sphinx.conf'...
listening on 127.0.0.1:9307
precaching index 'review_core'
precaching index 'user_core'
precached 2 indexes in 0.002 sec
Started searchd successfully (pid: 6532).
Содержимое test.sphinx.conf такое же, как и development.sphinx.conf, только пути меняются.
test.sphinx.conf, кстати, создается при попытке запустить тест https://pastebin.com/GavMg5BB
Если добавить в /gems/thinking-sphinx-5.5.1/lib/thinking_sphinx/test.rb
:
def self.start(options = {})
pp config.controller
вывод: https://pastebin.com/ta34Ys6k
При запуске теста в log/test.searchd.log ничего не пишется, т.к. sphinx не запускается.
UP2 Это то, что пытается запустить загадка::
# /gems/riddle-2.4.3/lib/riddle/execute_command.rb:7
"indexer --config \"/home/vagrant/data/app/config/test.sphinx.conf\" --all"
Если я попытаюсь сделать это вручную, я получаю:
ERROR: nothing to do.
@pat Я обновил пост, добавил немного информации.
Команда indexer ничего не сделает, потому что вы используете индексы в реальном времени, а это используется только для индексов, поддерживаемых SQL.
… и похоже, что start_with_autostop
предполагает использование индексов, поддерживаемых SQL. Вот почему он пытается запустить эту команду! Вместо того, чтобы использовать этот подход, используйте start(index: false)
перед каждым соответствующим тестом — вы можете увидеть пример этого подхода здесь: github.com/pat/drumknott-server/blob/main/spec/rails_helper.rb
@pat Да, спасибо. Я уже пробовал это. Я нашел решение, я напишу о нем позже.
Ура, я наконец-то разобрался.
Да start_with_autostop
(и не только) вызывает индексацию, а она возвращает ошибку Риддла.
Нам тоже не нужно звонить ThinkingSphinx::Test.index
.ThinkingSphinx::Test.run
, который раньше оборачивал тест, у нас тоже больше не работает, потому что вызывает ThinkingSphinx::Test.start
без аргумента index: false
.
Теперь нам просто нужно запустить Sphinx и иметь обратные вызовы ThinkingSphinx в моделях, иначе созданные вами объекты не будут проиндексированы, что имеет смысл. Поскольку теперь у нас есть обратные вызовы для моделей, мы должны поддерживать работу Sphinx во всех тестах, использующих эти модели, иначе мы получим ошибку:
Error connecting to Sphinx via the MySQL protocol. Can't connect to MySQL server on '127.0.0.1:9307' (111).
Поэтому нам нужно, чтобы Sphinx работал в фоновом режиме в течение всего времени тестов, например, например. Редис.
Если мы будем запускать и останавливать Sphinx с каждым спецификационным файлом, то время тестирования заметно увеличится.
Есть несколько решений, которые работают для меня на данный момент:
1. добавить в rails_helper внутри RSpec.configure
# Starting Sphinx before all tests
config.before(:suite) do
ThinkingSphinx::Test.init
ThinkingSphinx::Test.start(index: false)
end
# Stoping ThinkingSphinx after all the tests
config.after(:suite) do
ThinkingSphinx::Test.stop
end
Далее на ваш выбор:
ThinkingSphinx
, sphinx_helper вызывается в Feature тестах для Sphinx вместо rails_helper.2. Запускаем Sphinx через Rake-таски в rails_helper:
# before RSpec.configure
Rails.application.load_tasks
# inside RSpec.configure
config.before(:suite) do
Rake::Task['ts:configure'].invoke
Rake::Task['ts:start'].invoke
end
config.after(:suite) do
Rake::Task['ts:stop'].invoke
Rake::Task['ts:clear'].invoke
end
Далее на ваш выбор: то же, что и в пункте 1.
3. Если вам нужен DatabaseCleaner, вы можете поместить его глобально в rails_helper внутри RSpec.configure:
config.use_transactional_fixtures = false
# Starting Sphinx before all tests
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
ThinkingSphinx::Test.init
ThinkingSphinx::Test.start(index: false)
end
config.before(:each) do |test|
# fix ActiveRecord::RecordNotFound in JS tests
DatabaseCleaner.strategy = test.metadata[:js] ? :truncation : :transaction
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
# Stoping ThinkingSphinx after all the tests.
config.after(:suite) do
ThinkingSphinx::Test.stop
end
sphinx_helper, то просто удалите его.
Во всех Feature-тестах Sphinx необходимо удалить обертку ThinkingSphinx::Test.run
, а также sphinx: true
и js: true
(если вам явно не нужен JS)
Также не забудьте добавить обратный вызов для индексированных моделей:
ThinkingSphinx::Callbacks.append(
self, :behaviours => [:real_time]
)
Также можно добавить удаление папки index после всех тестов и остановку Sphinx:
config.after(:suite) do
ThinkingSphinx::Test.stop
FileUtils.rm_rf("#{Rails.root}/db/sphinx/test")
end
PS: Если будут новые подробности, я обновлю пост.
Не заметил сразу ничего неправильного в вашем коде… но можете ли вы подтвердить, что используете другой порт для Sphinx в своей тестовой среде?