Class: Wp2txt::IndexCache
- Inherits:
-
Object
- Object
- Wp2txt::IndexCache
- Defined in:
- lib/wp2txt/index_cache.rb
Overview
SQLite-based cache for multistream index Dramatically speeds up repeated index access by storing parsed entries in SQLite
Constant Summary collapse
- CACHE_VERSION =
1- CACHE_SUFFIX =
".sqlite3"
Instance Attribute Summary collapse
-
#cache_path ⇒ Object
readonly
Returns the value of attribute cache_path.
-
#source_path ⇒ Object
readonly
Returns the value of attribute source_path.
Instance Method Summary collapse
-
#clear! ⇒ Object
Delete cache file.
-
#find_by_titles(titles) ⇒ Hash
Find entries by titles (efficient batch lookup).
-
#initialize(source_path, cache_dir: nil) ⇒ IndexCache
constructor
A new instance of IndexCache.
-
#load ⇒ Hash
Load index entries from cache.
-
#save(entries_by_title, stream_offsets) ⇒ Object
Save index entries to cache.
-
#stats ⇒ Object
Get cache statistics.
-
#valid? ⇒ Boolean
Check if cache exists and is valid for the current source file.
Constructor Details
#initialize(source_path, cache_dir: nil) ⇒ IndexCache
Returns a new instance of IndexCache.
16 17 18 19 20 21 |
# File 'lib/wp2txt/index_cache.rb', line 16 def initialize(source_path, cache_dir: nil) @source_path = source_path @cache_dir = cache_dir || default_cache_dir @cache_path = build_cache_path @db = nil end |
Instance Attribute Details
#cache_path ⇒ Object (readonly)
Returns the value of attribute cache_path.
14 15 16 |
# File 'lib/wp2txt/index_cache.rb', line 14 def cache_path @cache_path end |
#source_path ⇒ Object (readonly)
Returns the value of attribute source_path.
14 15 16 |
# File 'lib/wp2txt/index_cache.rb', line 14 def source_path @source_path end |
Instance Method Details
#clear! ⇒ Object
Delete cache file
183 184 185 |
# File 'lib/wp2txt/index_cache.rb', line 183 def clear! FileUtils.rm_f(@cache_path) end |
#find_by_titles(titles) ⇒ Hash
Find entries by titles (efficient batch lookup)
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/wp2txt/index_cache.rb', line 135 def find_by_titles(titles) return {} if titles.empty? return {} unless valid? results = {} open_db begin # Use IN clause with placeholders for batch lookup placeholders = titles.map { "?" }.join(",") sql = "SELECT title, page_id, byte_offset FROM index_entries WHERE title IN (#{placeholders})" # SQLite3 2.x requires bind variables as an array @db.execute(sql, titles) do |row| title, page_id, offset = row results[title] = { offset: offset, page_id: page_id, title: title } end results ensure close_db end end |
#load ⇒ Hash
Load index entries from cache
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/wp2txt/index_cache.rb', line 52 def load return nil unless valid? entries_by_title = {} entries_by_id = {} stream_offsets = [] open_db begin # Load all entries @db.execute("SELECT title, page_id, byte_offset FROM index_entries") do |row| title, page_id, offset = row entry = { offset: offset, page_id: page_id, title: title } entries_by_title[title] = entry entries_by_id[page_id] = entry end # Load stream offsets @db.execute("SELECT byte_offset FROM stream_offsets ORDER BY byte_offset") do |row| stream_offsets << row[0] end { entries_by_title: entries_by_title, entries_by_id: entries_by_id, stream_offsets: stream_offsets } ensure close_db end end |
#save(entries_by_title, stream_offsets) ⇒ Object
Save index entries to cache
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/wp2txt/index_cache.rb', line 83 def save(entries_by_title, stream_offsets) FileUtils.mkdir_p(File.dirname(@cache_path)) # Remove old cache if exists FileUtils.rm_f(@cache_path) open_db begin create_schema # Use transaction for better performance @db.execute("BEGIN TRANSACTION") # Save metadata source_stat = File.stat(@source_path) ( source_path: @source_path, source_mtime: source_stat.mtime.to_i, source_size: source_stat.size, cache_version: CACHE_VERSION, entry_count: entries_by_title.size ) # Save entries in batches for performance stmt = @db.prepare("INSERT INTO index_entries (title, page_id, byte_offset) VALUES (?, ?, ?)") entries_by_title.each do |title, entry| stmt.execute([title, entry[:page_id], entry[:offset]]) end stmt.close # Save stream offsets stmt = @db.prepare("INSERT INTO stream_offsets (byte_offset) VALUES (?)") stream_offsets.each do |offset| stmt.execute([offset]) end stmt.close @db.execute("COMMIT") true rescue SQLite3::Exception => e @db.execute("ROLLBACK") rescue nil FileUtils.rm_f(@cache_path) raise e ensure close_db end end |
#stats ⇒ Object
Get cache statistics
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/wp2txt/index_cache.rb', line 159 def stats return nil unless File.exist?(@cache_path) open_db begin = entry_count = @db.get_first_value("SELECT COUNT(*) FROM index_entries") stream_count = @db.get_first_value("SELECT COUNT(*) FROM stream_offsets") { cache_path: @cache_path, cache_size: File.size(@cache_path), entry_count: entry_count, stream_count: stream_count, source_path: [:source_path], source_mtime: [:source_mtime] ? Time.at([:source_mtime].to_i) : nil, cache_version: [:cache_version] } ensure close_db end end |
#valid? ⇒ Boolean
Check if cache exists and is valid for the current source file
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/wp2txt/index_cache.rb', line 25 def valid? return false unless File.exist?(@cache_path) return false unless File.exist?(@source_path) begin open_db = return false unless # Check cache version return false if [:cache_version].to_i != CACHE_VERSION # Check source file hasn't changed source_stat = File.stat(@source_path) return false if [:source_mtime].to_i != source_stat.mtime.to_i return false if [:source_size].to_i != source_stat.size true rescue SQLite3::Exception false ensure close_db end end |