Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix settings update regression #330

Merged
merged 2 commits into from
Feb 19, 2024

Conversation

ellnix
Copy link
Collaborator

@ellnix ellnix commented Feb 19, 2024

Pull Request

Related issue

Fixes #329
May fix #328

What does this PR do?

  • SafeIndex before I tried to fix Skip indexCreation and settingsUpdate whenever adding new record in production #280 with Correctly check if index settings have been updated #301 did not guarantee that its index exists at all, since @index was created asynchronously it was possible that SafeIndex#settings could be called on an index that does not exist.
    This line:
    return {} if e.code == 404 # not fatal

    was supposed return an empty hash when asked to fetch the settings of an index that does not exist, however ApiError#code is the meilisearch code ("index_not_found") and not the http code (404). That line was therefore skipped and the index_not_found error was being propagated and caught by the rescue nil in:
    current_settings = @ms_indexes[MeiliSearch::Rails.active?][settings].settings(getVersion: 1) rescue nil # if the index doesn't exist

    until I removed it and tried to replace it with ensuring that SafeIndex had an index by making create_index! synchronous and all kinds of hell broke loose since now every time an index was used would cause a synchronous wait.

Copy link

codecov bot commented Feb 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (29f59c8) 89.32% compared to head (03a8daa) 89.47%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #330      +/-   ##
==========================================
+ Coverage   89.32%   89.47%   +0.14%     
==========================================
  Files          11       11              
  Lines         684      684              
==========================================
+ Hits          611      612       +1     
+ Misses         73       72       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Creating the index synchronously was required to get an up to version of
its settings, in order to compare them to the user configuration and
decide whether or not to update settings. Unfortunately this made
practically every operation have a synchronous component causing a lot
of problems down the line.
This commit reverts to using create_index asynchronously to avoid said
issues, and represents the settings of a nonexistent index as an empty
hash, which will queue an update_settings if the user has specified any
settings at all.
@ellnix ellnix force-pushed the fix-settings-update-regression branch from b3d8a47 to 03a8daa Compare February 19, 2024 09:44
@ellnix ellnix marked this pull request as ready for review February 19, 2024 09:45
@ellnix ellnix added the bug Something isn't working label Feb 19, 2024
Copy link
Member

@brunoocasali brunoocasali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ellnix I made some points that we could discuss, but I don't think we should wait for the answers.

LGTM!

@@ -843,7 +843,7 @@ def meilisearch_settings_changed?(server_state, user_configuration)
if user.is_a?(Hash) && server.is_a?(Hash)
meilisearch_settings_changed?(server, user)
elsif user.is_a?(Array) && server.is_a?(Array)
user.map(&:to_s) != server.map(&:to_s)
user.map(&:to_s).sort! != server.map(&:to_s).sort!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you have to use sort! and not just sort here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mainly out of frustration. While I understand objectively that this function is very short and does not deal with a lot of data, the type conversions really bother me and it feels like it performs terribly.

So I looked up performance comparisons for different methods to compare arrays regardless of order and sort! was slightly faster than sort.

Of course these arrays are tiny and the difference does not matter one bit, especially since map already crates new arrays.

@@ -261,7 +261,7 @@ def initialize(index_uid, raise_on_failure, options)
@raise_on_failure = raise_on_failure.nil? || raise_on_failure

SafeIndex.log_or_throw(nil, @raise_on_failure) do
client.create_index!(index_uid, { primary_key: primary_key })
client.create_index(index_uid, { primary_key: primary_key })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's trust on the test suite 🙏

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it was asynchronous on 0.10.2 so it should be fine:

client.create_index(index_uid, { primary_key: primary_key })

@@ -306,7 +306,7 @@ def settings(*args)
SafeIndex.log_or_throw(:settings, @raise_on_failure) do
@index.settings(*args)
rescue ::MeiliSearch::ApiError => e
return {} if e.code == 404 # not fatal
return {} if e.code == 'index_not_found' # not fatal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we had the 404 in the first place, but index_not_found is just one issue that could happen, shouldn't we make it more generic? Like parsing the error response to grab a "match-all" case?

Copy link
Collaborator Author

@ellnix ellnix Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the logic is that everytime an index is used, we attempt to create it and we also check if its settings are good, immediately afterward.

So

  • if index.settings says that the index is not found
  • it means that the index has just been created
  • thus we can pass {} as the settings to compare against the user settings
  • this way
    • if there are any user settings at all
    • we know the index has just been created and is therefore on default settings
    • we will send an update_settings request

This logic has a flaw that we should discuss in due time but it's minor.

Anyway from what I can see the only purpose of this rescue block is to handle this one case wherein the index has not been created yet. Other errors are handled by log_or_throw since this method just propagates them.

lib/meilisearch-rails.rb Show resolved Hide resolved
@ellnix
Copy link
Collaborator Author

ellnix commented Feb 19, 2024

bors merge

@meili-bors meili-bors bot merged commit b0bfab1 into meilisearch:main Feb 19, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants