vmail 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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