vmail 0.8.7 → 0.8.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.
@@ -28,10 +28,16 @@ module Vmail
28
28
  @mailbox = nil
29
29
  @logger = Logger.new(config['logfile'] || STDERR)
30
30
  @logger.level = Logger::DEBUG
31
- @current_mail = nil
32
- @current_message_index = nil
33
31
  @imap_server = config['server'] || 'imap.gmail.com'
34
32
  @imap_port = config['port'] || 993
33
+ @current_mail = nil
34
+ @current_message_index = nil
35
+ end
36
+
37
+ # holds mail objects keyed by [mailbox, uid]
38
+ # TODO don't cache a mail if too large; or come up with a way to purge
39
+ def message_cache
40
+ @message_cache ||= {}
35
41
  end
36
42
 
37
43
  def open
@@ -361,27 +367,34 @@ module Vmail
361
367
 
362
368
  def show_message(index, raw=false)
363
369
  return if index.to_i < 0
364
- log "showing message at #{index}"
365
370
  return @current_mail.to_s if raw
366
371
  index = index.to_i
367
372
  if index == @current_message_index
368
373
  return @current_message
369
374
  end
375
+
376
+ prefetch_adjacent(index)
377
+
370
378
  envelope_data = @message_list[index]
371
379
  seqno = envelope_data[:seqno]
372
380
  uid = envelope_data[:uid]
373
- log "showing message seqno: #{seqno} uid #{uid}"
374
- fetch_data = reconnect_if_necessary do
375
- @imap.uid_fetch(uid, ["FLAGS", "RFC822", "RFC822.SIZE"])[0]
376
- end
377
- res = fetch_data.attr["RFC822"]
378
- mail = Mail.new(res)
381
+ log "showing message index: #{index} seqno: #{seqno} uid #{uid}"
382
+
383
+ data = if x = message_cache[[@mailbox, uid]]
384
+ log "- message cache hit"
385
+ x
386
+ else
387
+ log "- fetching and storing to message_cache[[#{@mailbox}, #{uid}]]"
388
+ fetch_and_cache(uid)
389
+ end
390
+ # pre-fetch prev and next
391
+
392
+ mail = data[:mail]
393
+ size = data[:size]
379
394
  @current_message_index = index
380
395
  @current_mail = mail # used later to show raw message or extract attachments if any
381
- log "saving current mail with parts: #{@current_mail.parts.inspect}"
382
396
  formatter = Vmail::MessageFormatter.new(mail)
383
397
  out = formatter.process_body
384
- size = fetch_data.attr["RFC822.SIZE"]
385
398
  @current_message = <<-EOF
386
399
  #{@mailbox} seqno:#{envelope_data[:seqno]} uid:#{uid} #{number_to_human_size size} #{format_parts_info(formatter.list_parts)}
387
400
  #{divider '-'}
@@ -391,7 +404,29 @@ module Vmail
391
404
  EOF
392
405
  rescue
393
406
  log "parsing error"
394
- "Error encountered parsing this message:\n#{$!}"
407
+ "Error encountered parsing this message:\n#{$!}\n#{$!.backtrace.join("\n")}"
408
+ end
409
+
410
+ def fetch_and_cache(uid)
411
+ return if message_cache[[@mailbox, uid]]
412
+ fetch_data = reconnect_if_necessary do
413
+ @imap.uid_fetch(uid, ["FLAGS", "RFC822", "RFC822.SIZE"])[0]
414
+ end
415
+ d = {:mail => Mail.new(fetch_data.attr['RFC822']), :size => fetch_data.attr["RFC822.SIZE"]}
416
+ log "storing message_cache[[#{@mailbox}, #{uid}]]"
417
+ message_cache[[@mailbox, uid]] = d
418
+ d
419
+ end
420
+
421
+ def prefetch_adjacent(index)
422
+ Thread.new do
423
+ [index + 1, index - 1].each do |idx|
424
+ envelope_data = @message_list[idx]
425
+ next unless envelope_data
426
+ uid = envelope_data[:uid]
427
+ fetch_and_cache(uid)
428
+ end
429
+ end
395
430
  end
396
431
 
397
432
  def format_parts_info(parts)
@@ -1,3 +1,3 @@
1
1
  module Vmail
2
- VERSION = "0.8.7"
2
+ VERSION = "0.8.8"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 8
8
- - 7
9
- version: 0.8.7
8
+ - 8
9
+ version: 0.8.8
10
10
  platform: ruby
11
11
  authors:
12
12
  - Daniel Choi