full_search 0.4.6 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffdca4041a68a79686da2b8d636b3feadb88d39fd6ca2ff8f3c6ec955d52355c
4
- data.tar.gz: 8438b904a538c0d8c8e0250bf751209b44f8a095aacfc1089cb180a5cbb21d8f
3
+ metadata.gz: f50c2f24f4b4929d3da0744d93e33a0b6c5a6ba3743c4542612c6e1007687691
4
+ data.tar.gz: d497857811078992322ad4cd081e41aa476878c0950b71a2ec5bcd7a76ff8db2
5
5
  SHA512:
6
- metadata.gz: 447a5e7b51909e3098a38439935facf534ad7a97c84eb399af7fbd5e844c966787ac74651a58993000d12b0c18d3a6851fe3ea1e32b854629ff97b5c9e1906a0
7
- data.tar.gz: d43d646f9e95ad6bc8d4425c8601b9c5f2695f106965cba1b53881cf8e155581a3421055f1b6babc0468aaf0a02c589e1e615f95dfecb42cd776adebae320bb5
6
+ metadata.gz: bf77188446fed43a0e9f69826f85ced628f5960d493cbd96d721730e9fd9d8c92ffe5c58412aee47e81feb01adca00e2e7b7641f85ea01fe2c98fcaaca05b5f1
7
+ data.tar.gz: 89e0b8dc7ee2b44391deb5c339e2b048c836431a5997ab19c281285b1fef79fcfe5ad4fea02793a672643899e08e5276a12dbadacf51cb3411853d389c6fbbf7
@@ -167,8 +167,8 @@ module FullSearch
167
167
 
168
168
  conn = connection
169
169
  begin
170
- conn.execute("DELETE FROM #{qt(fts_table_name(model))};")
171
- conn.execute("DELETE FROM #{qt(trigram_table_name(model))};") if trigram_table_needed?(model) && trigram_table_exists?(model)
170
+ with_busy_retry { conn.execute("DELETE FROM #{qt(fts_table_name(model))};") }
171
+ with_busy_retry { conn.execute("DELETE FROM #{qt(trigram_table_name(model))};") } if trigram_table_needed?(model) && trigram_table_exists?(model)
172
172
  rescue ActiveRecord::StatementInvalid => e
173
173
  raise unless e.message.match?(/fts5: corruption|invalid fts5 file format|malformed database schema/i)
174
174
 
@@ -191,12 +191,12 @@ module FullSearch
191
191
  # drop the shadow tables directly, then drop the (now-empty) virtual
192
192
  # table wrapper, so the caller can recreate a clean index.
193
193
  def drop_fts_table_safely!(table_name)
194
- connection.execute("DROP TABLE IF EXISTS #{qt(table_name)};")
194
+ with_busy_retry { connection.execute("DROP TABLE IF EXISTS #{qt(table_name)};") }
195
195
  rescue ActiveRecord::StatementInvalid => e
196
196
  raise unless e.message.match?(/fts5: corruption|invalid fts5 file format|malformed database schema/i)
197
197
 
198
198
  drop_shadow_tables!(table_name)
199
- connection.execute("DROP TABLE IF EXISTS #{qt(table_name)};")
199
+ with_busy_retry { connection.execute("DROP TABLE IF EXISTS #{qt(table_name)};") }
200
200
  end
201
201
 
202
202
  # FTS5 stores its index data in a fixed set of shadow tables named
@@ -249,12 +249,14 @@ module FullSearch
249
249
  def healthy?(model)
250
250
  return false unless table_exists?(model)
251
251
 
252
- connection.execute("SELECT count(*) FROM #{qt(fts_table_name(model))}")
253
- true
254
- rescue ActiveRecord::StatementInvalid => e
255
- raise unless e.message.match?(/fts5: corruption|invalid fts5 file format|malformed database schema/i)
252
+ begin
253
+ with_busy_retry { connection.execute("SELECT count(*) FROM #{qt(fts_table_name(model))}") }
254
+ true
255
+ rescue ActiveRecord::StatementInvalid => e
256
+ raise unless e.message.match?(/fts5: corruption|invalid fts5 file format|malformed database schema/i)
256
257
 
257
- false
258
+ false
259
+ end
258
260
  end
259
261
 
260
262
  def trigram_table_needed?(model)
@@ -285,6 +287,22 @@ module FullSearch
285
287
 
286
288
  private
287
289
 
290
+ BUSY_RETRIES = 3
291
+ BUSY_BACKOFF = 0.1
292
+
293
+ def with_busy_retry
294
+ attempts = 0
295
+ begin
296
+ yield
297
+ rescue ActiveRecord::StatementInvalid => e
298
+ raise unless e.message.match?(/database is locked/i) && attempts < BUSY_RETRIES
299
+ attempts += 1
300
+ sleep(BUSY_BACKOFF * attempts)
301
+ IndexCache.clear!
302
+ retry
303
+ end
304
+ end
305
+
288
306
  def connection
289
307
  ActiveRecord::Base.connection
290
308
  end
@@ -85,7 +85,8 @@ module FullSearch
85
85
  def check_stale_config!
86
86
  if FullSearch::Index.missing_table?(model)
87
87
  if FullSearch.config.auto_rebuild_missing_tables
88
- FullSearch::Index.rebuild!(model)
88
+ FullSearch.logger.info("[full_search] Auto-creating missing FTS table for #{model.table_name}")
89
+ FullSearch::Index.ensure_table!(model)
89
90
  return
90
91
  end
91
92
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FullSearch
4
- VERSION = "0.4.6"
4
+ VERSION = "0.4.8"
5
5
  end
data/lib/full_search.rb CHANGED
@@ -72,6 +72,16 @@ module FullSearch
72
72
  def bulk_importing?(model)
73
73
  BulkImport.bulk_importing?(model)
74
74
  end
75
+
76
+ def logger
77
+ return @logger if defined?(@logger) && @logger
78
+
79
+ @logger = if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
80
+ Rails.logger
81
+ else
82
+ Logger.new(File::NULL)
83
+ end
84
+ end
75
85
  end
76
86
  end
77
87
 
@@ -5,6 +5,9 @@ FullSearch.configure do |config|
5
5
 
6
6
  config.auto_rebuild_on_stale_query = Rails.env.local?
7
7
 
8
+ # Auto-create missing FTS tables on first query in dev/test instead of raising.
9
+ config.auto_rebuild_missing_tables = Rails.env.local?
10
+
8
11
  config.stale_query_behavior = Rails.env.production? ? :log_and_fallback : :raise
9
12
 
10
13
  config.lock_rebuilds = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: full_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben D'Angelo
@@ -189,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
189
  - !ruby/object:Gem::Version
190
190
  version: '2.0'
191
191
  requirements: []
192
- rubygems_version: 4.0.15
192
+ rubygems_version: 4.0.10
193
193
  specification_version: 4
194
194
  summary: SQLite FTS5 full-text search for Rails/ActiveRecord
195
195
  test_files: []