Class: Mailmate::IndexReader
- Inherits:
-
Object
- Object
- Mailmate::IndexReader
- Defined in:
- lib/mailmate/index_reader.rb
Constant Summary collapse
- RECORD_SIZE =
12
Instance Attribute Summary collapse
- #name ⇒ Object readonly
Class Method Summary collapse
-
.for(name) ⇒ Object
Per-process cache of readers keyed by [name, db_headers].
-
.reset!(name = nil) ⇒ Object
Invalidate cached readers.
Instance Method Summary collapse
-
#each_eml_id(&block) ⇒ Object
Iterate every recorded eml-id.
-
#each_record ⇒ Object
Iterate every (eml_id, raw_value) pair, once per on-disk record.
-
#flags_for(eml_id) ⇒ Object
‘#flags.flag` semantics: the cache stores a space-separated list of IMAP keywords.
-
#initialize(name) ⇒ IndexReader
constructor
A new instance of IndexReader.
-
#record_count ⇒ Object
Total number of on-disk records (sum across all ids).
-
#size ⇒ Object
Number of distinct ids in the index.
-
#value_for(eml_id) ⇒ Object
Returns the raw cached value for a given .eml body-part ID, or nil if the id isn’t in this index.
-
#values_for(eml_id) ⇒ Object
Returns every recorded value for an id, in offsets-file order.
Constructor Details
#initialize(name) ⇒ IndexReader
Returns a new instance of IndexReader.
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/mailmate/index_reader.rb', line 79 def initialize(name) @name = name base = "#{Mailmate.config.db_headers}/#{name}" raise ArgumentError, "Index not found: #{name} (looked at #{base}.{cache,offsets})" \ unless File.exist?("#{base}.cache") && File.exist?("#{base}.offsets") @cache_bytes = File.binread("#{base}.cache") @offsets_bytes = File.binread("#{base}.offsets") build_index! end |
Instance Attribute Details
#name ⇒ Object (readonly)
77 78 79 |
# File 'lib/mailmate/index_reader.rb', line 77 def name @name end |
Class Method Details
.for(name) ⇒ Object
Per-process cache of readers keyed by [name, db_headers]. Including db_headers means a Mailmate.config swap (e.g. a test pointing at a different tmpdir) doesn’t return stale readers built from the old path.
52 53 54 55 |
# File 'lib/mailmate/index_reader.rb', line 52 def for(name) @cache ||= {} @cache[cache_key(name)] ||= new(name) end |
.reset!(name = nil) ⇒ Object
Invalidate cached readers. With no argument, drops the entire cache (useful for tests or when MailMate’s database swaps out). With a name, invalidates only entries for that name across all db_headers — the common case (cache-bust after a write) doesn’t need to thread config through.
62 63 64 65 66 67 68 |
# File 'lib/mailmate/index_reader.rb', line 62 def reset!(name = nil) if name.nil? @cache = nil elsif @cache @cache.delete_if { |(n, _dir), _reader| n == name } end end |
Instance Method Details
#each_eml_id(&block) ⇒ Object
Iterate every recorded eml-id. Yields just the id; callers that also want the value should pair this with ‘value_for`. Exists so other gem modules don’t have to reach into ‘@index` directly.
134 135 136 137 |
# File 'lib/mailmate/index_reader.rb', line 134 def each_eml_id(&block) return enum_for(:each_eml_id) unless block @index.each_key(&block) end |
#each_record ⇒ Object
Iterate every (eml_id, raw_value) pair, once per on-disk record. Multi-record ids yield multiple times. The value comes back as the bare cache substring; callers that need parsed form (e.g. flag tokens) should massage it themselves.
143 144 145 146 147 148 |
# File 'lib/mailmate/index_reader.rb', line 143 def each_record return enum_for(:each_record) unless block_given? @index.each do |eml_id, pairs| pairs.each { |(s, e)| yield eml_id, @cache_bytes[s...e] } end end |
#flags_for(eml_id) ⇒ Object
‘#flags.flag` semantics: the cache stores a space-separated list of IMAP keywords. Split into individual flag tokens.
114 115 116 117 118 |
# File 'lib/mailmate/index_reader.rb', line 114 def flags_for(eml_id) v = value_for(eml_id) return [] if v.nil? || v.empty? v.split(/\s+/).reject(&:empty?) end |
#record_count ⇒ Object
Total number of on-disk records (sum across all ids). Diagnostics.
127 128 129 |
# File 'lib/mailmate/index_reader.rb', line 127 def record_count @index.values.sum(&:size) end |
#size ⇒ Object
Number of distinct ids in the index. For multi-record indexes this is smaller than the on-disk record count (use record_count for that).
122 123 124 |
# File 'lib/mailmate/index_reader.rb', line 122 def size @index.size end |
#value_for(eml_id) ⇒ Object
Returns the raw cached value for a given .eml body-part ID, or nil if the id isn’t in this index. Returns the LAST record for the id — for accumulator-style header indexes (‘#flags`, `#source`, `subject`, etc.) that’s the latest state; the older records are stale versions. For body indexes (‘#unquoted#lc`, `#quoted#lc`) last-alone is meaningless — use values_for to read every segment.
96 97 98 99 100 101 |
# File 'lib/mailmate/index_reader.rb', line 96 def value_for(eml_id) pairs = @index[eml_id.to_i] return nil if pairs.nil? || pairs.empty? s, e = pairs[-1] @cache_bytes[s...e] end |
#values_for(eml_id) ⇒ Object
Returns every recorded value for an id, in offsets-file order. Returns
-
if the id isn’t in the index. Use this for body indexes
(#unquoted#lc, #quoted#lc), which store one record per text segment.
106 107 108 109 110 |
# File 'lib/mailmate/index_reader.rb', line 106 def values_for(eml_id) pairs = @index[eml_id.to_i] return [] if pairs.nil? pairs.map { |(s, e)| @cache_bytes[s...e] } end |