diff --git a/.circleci/config.yml b/.circleci/config.yml index 43743f532..d612fdf63 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,7 +28,7 @@ workflows: debian: buster matrix: parameters: - ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2' ] + ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2', '3.0.0' ] # - test: # database: postgresql # sphinx_version: 3.3.1 @@ -62,7 +62,7 @@ workflows: debian: buster matrix: parameters: - ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2' ] + ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2', '3.0.0' ] - test: name: "Manticore 3.5.4 with PostgreSQL" database: postgresql @@ -71,7 +71,7 @@ workflows: debian: buster matrix: parameters: - ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2' ] + ruby: [ '2.4.9', '2.5.8', '2.6.6', '2.7.2', '3.0.0' ] jobs: test: @@ -115,6 +115,8 @@ jobs: command: | if [ "<< parameters.ruby >>" == "2.7.2" ]; then export BUNDLER_VERSION=2.1.4 + elif [ "<< parameters.ruby >>" == "3.0.0" ]; then + export BUNDLER_VERSION=2.1.4 else export BUNDLER_VERSION=1.17.3 fi diff --git a/Appraisals b/Appraisals index 548fe8c4a..d61a10503 100644 --- a/Appraisals +++ b/Appraisals @@ -15,18 +15,18 @@ appraise 'rails_5_0' do gem 'jdbc-mysql', '~> 5.1.36', :platform => :jruby gem 'activerecord-jdbcmysql-adapter', '~> 50.0', :platform => :jruby gem 'activerecord-jdbcpostgresql-adapter', '~> 50.0', :platform => :jruby -end if RUBY_PLATFORM != "java" || ENV["SPHINX_VERSION"].to_f > 2.1 +end if (RUBY_PLATFORM != "java" || ENV["SPHINX_VERSION"].to_f > 2.1) && RUBY_VERSION.to_f < 3.0 appraise 'rails_5_1' do gem 'rails', '~> 5.1.0' gem 'mysql2', '~> 0.4.0', :platform => :ruby -end if RUBY_PLATFORM != 'java' +end if RUBY_PLATFORM != 'java' && RUBY_VERSION.to_f < 3.0 appraise 'rails_5_2' do gem 'rails', '~> 5.2.0' gem 'mysql2', '~> 0.5.0', :platform => :ruby gem 'pg', '~> 1.0', :platform => :ruby -end if RUBY_PLATFORM != 'java' +end if RUBY_PLATFORM != 'java' && RUBY_VERSION.to_f < 3.0 appraise 'rails_6_0' do gem 'rails', '~> 6.0.0' diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 8629a7b5b..9f85326bf 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -2,6 +2,20 @@ All notable changes to this project (at least, from v3.0.0 onwards) are documented in this file. +## 5.2.0 - 2021-06-12 + +[Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v5.2.0) + +### Added + +* Confirmed support for Ruby 3.0. +* Orphaned records in real-time indices can now be cleaned up without running `rails ts:rebuild`. Disabled by default, can be enabled by setting `real_time_tidy` to true per environment in `config/thinking_sphinx.yml` (and will need `ts:rebuild` to restructure indices upon initial deploy). More details in [#1192](https://github.com/pat/thinking-sphinx/pull/1192). + +### Fixed + +* Avoid loading ActiveRecord during Rails initialisation so app configuration can still have an impact ([@jdelStrother](https://github.com/jdelStrother) in [#1194](https://github.com/pat/thinking-sphinx/pull/1194)). +* Remove `app/indices` (in both the Rails app and engines) from Rails' eager load paths, which was otherwise leading to indices being loaded more than once. (See [#1191](https://github.com/pat/thinking-sphinx/issues/1191) and [#1195](https://github.com/pat/thinking-sphinx/issues/1195)). + ## 5.1.0 - 2020-12-28 [Release Notes](https://github.com/pat/thinking-sphinx/releases/tag/v5.1.0) diff --git a/README.textile b/README.textile index a72095ef3..f5c1ca0ac 100644 --- a/README.textile +++ b/README.textile @@ -1,6 +1,6 @@ h1. Thinking Sphinx -Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v5.1.0. +Thinking Sphinx is a library for connecting ActiveRecord to the Sphinx full-text search tool, and integrates closely with Rails (but also works with other Ruby web frameworks). The current release is v5.2.0. h2. Upgrading @@ -14,7 +14,7 @@ It's a gem, so install it like you would any other gem. You will also need to sp
gem 'mysql2', '~> 0.4', :platform => :ruby
gem 'jdbc-mysql', '~> 5.1.35', :platform => :jruby
-gem 'thinking-sphinx', '~> 5.1'
+gem 'thinking-sphinx', '~> 5.2'
The MySQL gems mentioned are required for connecting to Sphinx, so please include it even when you're using PostgreSQL for your database.
@@ -29,18 +29,18 @@ h2. Requirements
The current release of Thinking Sphinx works with the following versions of its dependencies:
|_. Library |_. Minimum |_. Tested Against |
-| Ruby | v2.4 | v2.4, v2.5, v2.6, v2.7 |
-| Sphinx | v2.2.11 | v2.2.11, v3.2.1 |
-| Manticore | v2.8 | v2.8, v3.4 |
-| ActiveRecord | v4.2 | v4.2..v6.0 |
+| Ruby | v2.4 | v2.4, v2.5, v2.6, v2.7, v3.0 |
+| Sphinx | v2.2.11 | v2.2.11, v3.3.1 |
+| Manticore | v2.8 | v2.8, v3.5 |
+| ActiveRecord | v4.2 | v4.2..v6.1 |
It _might_ work with older versions of Ruby, but it's highly recommended to update to a supported release.
-It should also work with JRuby, but the test environment on Travis CI has been timing out, hence that's not actively tested against at the moment.
+It should also work with JRuby, but the test environment for that in CI has been unreliable, hence that's not actively tested against at the moment.
h3. Sphinx or Manticore
-Thinking Sphinx is currently built for Sphinx 2.2.11 or newer (though it'll likely work with 2.1.x releases), or Manticore v2.8+.
+Thinking Sphinx is currently built for Sphinx 2.2.11 or newer, or Manticore v2.8+.
h3. Rails and ActiveRecord
diff --git a/lib/thinking_sphinx.rb b/lib/thinking_sphinx.rb
index 15bc37d4e..2e59e8c66 100644
--- a/lib/thinking_sphinx.rb
+++ b/lib/thinking_sphinx.rb
@@ -96,12 +96,15 @@ module Subscribers; end
require 'thinking_sphinx/utf8'
require 'thinking_sphinx/wildcard'
# Extended
-require 'thinking_sphinx/active_record'
require 'thinking_sphinx/deltas'
require 'thinking_sphinx/distributed'
require 'thinking_sphinx/logger'
require 'thinking_sphinx/real_time'
-require 'thinking_sphinx/railtie' if defined?(Rails::Railtie)
+if defined?(Rails::Railtie)
+ require 'thinking_sphinx/railtie'
+else
+ require 'thinking_sphinx/active_record'
+end
ThinkingSphinx.before_index_hooks << ThinkingSphinx::Hooks::GuardPresence
diff --git a/lib/thinking_sphinx/railtie.rb b/lib/thinking_sphinx/railtie.rb
index 8ba1f8583..668a0e897 100644
--- a/lib/thinking_sphinx/railtie.rb
+++ b/lib/thinking_sphinx/railtie.rb
@@ -7,6 +7,7 @@ class ThinkingSphinx::Railtie < Rails::Railtie
initializer 'thinking_sphinx.initialisation' do
ActiveSupport.on_load(:active_record) do
+ require 'thinking_sphinx/active_record'
ActiveRecord::Base.include ThinkingSphinx::ActiveRecord::Base
end
@@ -16,6 +17,10 @@ class ThinkingSphinx::Railtie < Rails::Railtie
Rails.root.join("app", "indices").to_s
)
end
+
+ Rails.application.config.eager_load_paths -=
+ ThinkingSphinx::Configuration.instance.index_paths
+ Rails.application.config.eager_load_paths.freeze
end
end
diff --git a/lib/thinking_sphinx/real_time/index/template.rb b/lib/thinking_sphinx/real_time/index/template.rb
index 9b7dc635f..c8db1067d 100644
--- a/lib/thinking_sphinx/real_time/index/template.rb
+++ b/lib/thinking_sphinx/real_time/index/template.rb
@@ -13,6 +13,10 @@ def apply
add_attribute primary_key, :sphinx_internal_id, :bigint
add_attribute class_column, :sphinx_internal_class, :string, :facet => true
add_attribute 0, :sphinx_deleted, :integer
+
+ if tidying?
+ add_attribute -> (_) { Time.current.to_i }, :sphinx_updated_at, :timestamp
+ end
end
private
@@ -34,7 +38,15 @@ def class_column
[:class, :name]
end
+ def config
+ ThinkingSphinx::Configuration.instance
+ end
+
def primary_key
index.primary_key.to_sym
end
+
+ def tidying?
+ config.settings["real_time_tidy"]
+ end
end
diff --git a/lib/thinking_sphinx/real_time/populator.rb b/lib/thinking_sphinx/real_time/populator.rb
index 2bfaa088b..b739445ea 100644
--- a/lib/thinking_sphinx/real_time/populator.rb
+++ b/lib/thinking_sphinx/real_time/populator.rb
@@ -7,6 +7,7 @@ def self.populate(index)
def initialize(index)
@index = index
+ @started_at = Time.current
end
def populate
@@ -17,12 +18,14 @@ def populate
instrument 'populated', :instances => instances
end
+ transcriber.clear_before(started_at) if configuration.settings["real_time_tidy"]
+
instrument 'finish_populating'
end
private
- attr_reader :index
+ attr_reader :index, :started_at
delegate :controller, :batch_size, :to => :configuration
delegate :scope, :to => :index
diff --git a/lib/thinking_sphinx/real_time/transcriber.rb b/lib/thinking_sphinx/real_time/transcriber.rb
index dc8bbc02a..4562bb3c5 100644
--- a/lib/thinking_sphinx/real_time/transcriber.rb
+++ b/lib/thinking_sphinx/real_time/transcriber.rb
@@ -5,6 +5,12 @@ def initialize(index)
@index = index
end
+ def clear_before(time)
+ execute <<~SQL.strip
+ DELETE FROM #{@index.name} WHERE sphinx_updated_at < #{time.to_i}
+ SQL
+ end
+
def copy(*instances)
items = instances.select { |instance|
instance.persisted? && copy?(instance)
diff --git a/lib/thinking_sphinx/real_time/translator.rb b/lib/thinking_sphinx/real_time/translator.rb
index 20e6da3de..f723c762d 100644
--- a/lib/thinking_sphinx/real_time/translator.rb
+++ b/lib/thinking_sphinx/real_time/translator.rb
@@ -10,6 +10,7 @@ def initialize(object, column)
end
def call
+ return name.call(object) if name.is_a?(Proc)
return name unless name.is_a?(Symbol)
return result unless result.is_a?(String)
diff --git a/lib/thinking_sphinx/settings.rb b/lib/thinking_sphinx/settings.rb
index 402042d51..850150a29 100644
--- a/lib/thinking_sphinx/settings.rb
+++ b/lib/thinking_sphinx/settings.rb
@@ -19,7 +19,8 @@ class ThinkingSphinx::Settings
"binlog_path" => "tmp/binlog/ENVIRONMENT",
"workers" => "threads",
"mysql_encoding" => "utf8",
- "maximum_statement_length" => (2 ** 23) - 5
+ "maximum_statement_length" => (2 ** 23) - 5,
+ "real_time_tidy" => false
}.freeze
def self.call(configuration)
diff --git a/spec/thinking_sphinx/real_time/index_spec.rb b/spec/thinking_sphinx/real_time/index_spec.rb
index ffac6960a..06e1e152d 100644
--- a/spec/thinking_sphinx/real_time/index_spec.rb
+++ b/spec/thinking_sphinx/real_time/index_spec.rb
@@ -5,7 +5,9 @@
describe ThinkingSphinx::RealTime::Index do
let(:index) { ThinkingSphinx::RealTime::Index.new :user }
let(:config) { double('config', :settings => {},
- :indices_location => 'location', :next_offset => 8) }
+ :indices_location => 'location', :next_offset => 8,
+ :index_set_class => index_set_class) }
+ let(:index_set_class) { double(:index_set_class, :reference_name => :user) }
before :each do
allow(ThinkingSphinx::Configuration).to receive_messages :instance => config
@@ -61,6 +63,16 @@
it "has the internal deleted attribute by default" do
expect(index.attributes.collect(&:name)).to include('sphinx_deleted')
end
+
+ it "does not have an internal updated_at attribute by default" do
+ expect(index.attributes.collect(&:name)).to_not include('sphinx_updated_at')
+ end
+
+ it "has an internal updated_at attribute if real_time_tidy is true" do
+ config.settings["real_time_tidy"] = true
+
+ expect(index.attributes.collect(&:name)).to include('sphinx_updated_at')
+ end
end
describe '#delta?' do
diff --git a/thinking-sphinx.gemspec b/thinking-sphinx.gemspec
index e41a86832..f08fefb10 100644
--- a/thinking-sphinx.gemspec
+++ b/thinking-sphinx.gemspec
@@ -5,7 +5,7 @@ $:.push File.expand_path('../lib', __FILE__)
Gem::Specification.new do |s|
s.name = 'thinking-sphinx'
- s.version = '5.1.0'
+ s.version = '5.2.0'
s.platform = Gem::Platform::RUBY
s.authors = ["Pat Allan"]
s.email = ["pat@freelancing-gods.com"]