inbox-sync 0.3.0 → 0.4.0
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.
- data/README.md +4 -0
- data/lib/inbox-sync/config.rb +1 -0
- data/lib/inbox-sync/runner.rb +25 -13
- data/lib/inbox-sync/sync/mail_item_group.rb +46 -0
- data/lib/inbox-sync/sync.rb +38 -34
- data/lib/inbox-sync/version.rb +1 -1
- data/test/config_test.rb +5 -0
- data/test/sync/login_test.rb +0 -62
- data/test/sync/mail_item_group_test.rb +19 -0
- metadata +7 -4
data/README.md
CHANGED
@@ -95,6 +95,10 @@ The (optional) folder on the source to create and archive (move) source inbox me
|
|
95
95
|
|
96
96
|
A logger to use. Defaults to ruby's `Logger` on `STDOUT`.
|
97
97
|
|
98
|
+
### `max_threads`
|
99
|
+
|
100
|
+
This is the number of threads to sync mail items with. Each time a sync is run, the number of mail items that need to sync'd will be broken into `max_threads` groups and each group will sync its mail items in its own thread. The default is `1` which means each message will be sync'd sequentially.
|
101
|
+
|
98
102
|
## Running
|
99
103
|
|
100
104
|
InboxSync provides a `Runner` class that will loop indefinitely, running syncs every `:interval` seconds. Stick it in a daemon, a rake task, a CLI, or whatever depending on how you want to invoke it. Here is an example using it in a basic ruby script:
|
data/lib/inbox-sync/config.rb
CHANGED
@@ -16,6 +16,7 @@ module InboxSync
|
|
16
16
|
opt :archive_folder, :default => 'Archived'
|
17
17
|
opt :logger, Logger, :required => true, :default => STDOUT
|
18
18
|
opt :filters, :default => [], :required => true
|
19
|
+
opt :max_threads, :default => 1, :required => true
|
19
20
|
|
20
21
|
def filter(*args, &block)
|
21
22
|
filters << Filter.new(*args, &block)
|
data/lib/inbox-sync/runner.rb
CHANGED
@@ -17,6 +17,7 @@ module InboxSync
|
|
17
17
|
@logger = opts[:logger] || Logger.new(STDOUT)
|
18
18
|
@shutdown = false
|
19
19
|
@running_syncs_thread = nil
|
20
|
+
@sync_groups = []
|
20
21
|
|
21
22
|
Signal.trap('SIGINT', lambda{ raise Interrupt, 'SIGINT' })
|
22
23
|
Signal.trap('SIGQUIT', lambda{ raise Interrupt, 'SIGQUIT' })
|
@@ -93,7 +94,10 @@ module InboxSync
|
|
93
94
|
thread_log "starting syncs..."
|
94
95
|
|
95
96
|
begin
|
96
|
-
|
97
|
+
@syncs.each do |sync|
|
98
|
+
run_threaded_sync(sync) if !self.shutdown?
|
99
|
+
end
|
100
|
+
GC.start
|
97
101
|
rescue Exception => err
|
98
102
|
thread_log_error(err, :error)
|
99
103
|
end
|
@@ -101,22 +105,30 @@ module InboxSync
|
|
101
105
|
thread_log "...syncs finished"
|
102
106
|
end
|
103
107
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
def run_threaded_sync(sync)
|
109
|
+
begin
|
110
|
+
sync.setup
|
111
|
+
@sync_groups = sync.mail_item_groups
|
112
|
+
thread_log "starting #{@sync_groups.size} sync threads..."
|
113
|
+
@sync_groups.each do |group|
|
114
|
+
thread_log "starting #{group.id} sync thread", :debug
|
115
|
+
group.run(self)
|
116
|
+
sleep(1)
|
111
117
|
end
|
118
|
+
rescue Exception => err
|
119
|
+
run_sync_handle_error(sync, err)
|
120
|
+
end
|
112
121
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
122
|
+
begin
|
123
|
+
@sync_groups.each do |group|
|
124
|
+
thread_log "waiting for #{group.id} sync thread to join...", :debug
|
125
|
+
group.join
|
117
126
|
end
|
127
|
+
thread_log "... all #{@sync_groups.size} sync threads are finished"
|
128
|
+
sync.teardown
|
129
|
+
rescue Exception => err
|
130
|
+
run_sync_handle_error(sync, err)
|
118
131
|
end
|
119
|
-
GC.start
|
120
132
|
end
|
121
133
|
|
122
134
|
def run_sync_handle_error(sync, err)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module InboxSync
|
2
|
+
class Sync; end
|
3
|
+
|
4
|
+
class Sync::MailItemGroup
|
5
|
+
|
6
|
+
attr_reader :thread, :items
|
7
|
+
|
8
|
+
def initialize(sync)
|
9
|
+
@sync = sync
|
10
|
+
@thread = nil
|
11
|
+
@items = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def id
|
15
|
+
"#<#{self.class}:#{'0x%x' % (self.object_id << 1)}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(mail_item)
|
19
|
+
@items << mail_item
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(runner=nil)
|
23
|
+
@runner = runner
|
24
|
+
@thread = Thread.new { run_items_thread }
|
25
|
+
end
|
26
|
+
|
27
|
+
def join
|
28
|
+
@thread.join
|
29
|
+
@runner = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def run_items_thread
|
35
|
+
@items.each do |item|
|
36
|
+
if @runner && @runner.shutdown?
|
37
|
+
@sync.logger.debug "* the runner has been shutdown - aborting #{id} sync thread"
|
38
|
+
break
|
39
|
+
end
|
40
|
+
@sync.run(item)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/lib/inbox-sync/sync.rb
CHANGED
@@ -3,6 +3,7 @@ require 'net/smtp'
|
|
3
3
|
|
4
4
|
require 'inbox-sync/config'
|
5
5
|
require 'inbox-sync/filter_actions'
|
6
|
+
require 'inbox-sync/sync/mail_item_group'
|
6
7
|
require 'inbox-sync/notice/sync_mail_item_error'
|
7
8
|
|
8
9
|
module InboxSync
|
@@ -53,25 +54,36 @@ module InboxSync
|
|
53
54
|
logger.info "=== #{config_log_detail(@config.source)} sync finished. ==="
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
57
|
+
# this splits the mail_items list into `@config.max_threads` lists
|
58
|
+
# this spreads mails evenly across the groups with earlier items
|
59
|
+
# appearing earliest in each list
|
60
|
+
|
61
|
+
def mail_item_groups
|
62
|
+
num_groups = @config.max_threads
|
63
|
+
groups = []
|
64
|
+
num_groups.times { groups << MailItemGroup.new(self) }
|
65
|
+
get_mail_items.each_with_index do |item, i|
|
66
|
+
groups[i % num_groups].add(item)
|
67
|
+
end
|
68
|
+
groups
|
69
|
+
end
|
70
|
+
|
71
|
+
def run(mail_item)
|
72
|
+
begin
|
73
|
+
logger.debug "** #{mail_item.inspect}"
|
74
|
+
response = send_to_dest(mail_item)
|
75
|
+
dest_uid = parse_append_response_uid(response)
|
76
|
+
apply_dest_filters(dest_uid)
|
77
|
+
rescue Exception => err
|
78
|
+
log_error(err)
|
79
|
+
notify(Notice::SyncMailItemError.new(@notify_smtp, @config.notify, {
|
80
|
+
:error => err,
|
81
|
+
:mail_item => mail_item,
|
82
|
+
:sync => self
|
83
|
+
}))
|
84
|
+
ensure
|
85
|
+
archive_on_source(mail_item)
|
86
|
+
mail_item = nil
|
75
87
|
end
|
76
88
|
end
|
77
89
|
|
@@ -98,21 +110,6 @@ module InboxSync
|
|
98
110
|
true
|
99
111
|
end
|
100
112
|
|
101
|
-
def each_source_mail_item(runner=nil)
|
102
|
-
logger.info "* find: #{config_log_detail(@config.source)}, #{@config.source.inbox.inspect}..."
|
103
|
-
items = MailItem.find(@source_imap)
|
104
|
-
logger.info "* ...found #{items.size} mail items"
|
105
|
-
|
106
|
-
items.each do |mail_item|
|
107
|
-
if runner && runner.shutdown?
|
108
|
-
logger.info "* the runner has been shutdown - aborting the sync"
|
109
|
-
break
|
110
|
-
end
|
111
|
-
yield mail_item
|
112
|
-
end
|
113
|
-
items = nil
|
114
|
-
end
|
115
|
-
|
116
113
|
# Send a mail item to the destination:
|
117
114
|
# The idea here is that destinations may not accept corrupted or invalid
|
118
115
|
# mail items. If appending the original mail item in any way fails,
|
@@ -223,6 +220,13 @@ module InboxSync
|
|
223
220
|
end
|
224
221
|
end
|
225
222
|
|
223
|
+
def get_mail_items
|
224
|
+
logger.info "* find: #{config_log_detail(@config.source)}, #{@config.source.inbox.inspect}..."
|
225
|
+
items = MailItem.find(@source_imap)
|
226
|
+
logger.info "* ...found #{items.size} mail items"
|
227
|
+
items
|
228
|
+
end
|
229
|
+
|
226
230
|
def logout_imap(imap, config)
|
227
231
|
logger.debug "* LOGOUT: #{config_log_detail(config)}"
|
228
232
|
imap.logout
|
data/lib/inbox-sync/version.rb
CHANGED
data/test/config_test.rb
CHANGED
@@ -42,6 +42,11 @@ module InboxSync
|
|
42
42
|
:required => true
|
43
43
|
}
|
44
44
|
|
45
|
+
should have_option :max_threads, {
|
46
|
+
:default => 1,
|
47
|
+
:required => true
|
48
|
+
}
|
49
|
+
|
45
50
|
should have_instance_methods :validate!, :filter
|
46
51
|
should have_instance_methods :contains, :like, :includes, :inc
|
47
52
|
should have_instance_methods :starts_with, :ends_with, :sw, :ew
|
data/test/sync/login_test.rb
CHANGED
@@ -45,66 +45,4 @@ module InboxSync
|
|
45
45
|
|
46
46
|
end
|
47
47
|
|
48
|
-
class LoggedInTests < ConfiguredSyncTests
|
49
|
-
desc 'and is logged in and ready to run'
|
50
|
-
before do
|
51
|
-
reset_source_inbox(@sync)
|
52
|
-
reset_source_archive(@sync)
|
53
|
-
|
54
|
-
@sync_archive_folder = @sync.config.archive_folder
|
55
|
-
@mail_item = MailItem.find(@sync.source_imap).first
|
56
|
-
end
|
57
|
-
|
58
|
-
after do
|
59
|
-
@sync.config.archive_folder = @sync_archive_folder
|
60
|
-
@sync.source_imap.select(@sync.config.source.inbox)
|
61
|
-
|
62
|
-
reset_source_archive(@sync)
|
63
|
-
end
|
64
|
-
|
65
|
-
should "run without any errors" do
|
66
|
-
assert_nothing_raised do
|
67
|
-
subject.run
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
# class ArchiveTests < RunTests
|
74
|
-
# should "remove the message from the inbox" do
|
75
|
-
# @sync.archive_from_source(@mail_item)
|
76
|
-
|
77
|
-
# assert_not_included @mail_item.uid, @sync.source_imap.uid_search(['ALL'])
|
78
|
-
# assert_empty @sync.source_imap.uid_search(['ALL'])
|
79
|
-
# end
|
80
|
-
|
81
|
-
# should "move it to the archive folder" do
|
82
|
-
# @sync.archive_from_source(@mail_item)
|
83
|
-
# @sync.source_imap.select(@sync.config.archive_folder)
|
84
|
-
|
85
|
-
# assert_equal 1, @sync.source_imap.uid_search(['ALL']).size
|
86
|
-
# end
|
87
|
-
|
88
|
-
# should "not archive if no archive folder configured" do
|
89
|
-
# @sync.config.archive_folder = nil
|
90
|
-
# @sync.archive_from_source(@mail_item)
|
91
|
-
# @sync.source_imap.select(@sync.config.source.inbox)
|
92
|
-
|
93
|
-
# assert_not_included @mail_item.uid, @sync.source_imap.uid_search(['ALL'])
|
94
|
-
# end
|
95
|
-
|
96
|
-
# end
|
97
|
-
|
98
|
-
# class AppendTests < LoggedInTests
|
99
|
-
# should "append a source msg onto the dest" do
|
100
|
-
# assert_nothing_raised do
|
101
|
-
# @sync.append_to_dest(test_mail_item)
|
102
|
-
# end
|
103
|
-
# end
|
104
|
-
|
105
|
-
# should "parse the destination UID when appending mail items" do
|
106
|
-
# assert_match /\A\d+\Z/, @sync.append_to_dest(test_mail_item)
|
107
|
-
# end
|
108
|
-
# end
|
109
|
-
|
110
48
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'assert'
|
2
|
+
|
3
|
+
require 'inbox-sync/sync/mail_item_group'
|
4
|
+
|
5
|
+
module InboxSync
|
6
|
+
|
7
|
+
class SyncMailItemGroupTests < Assert::Context
|
8
|
+
desc "a runner mail item group"
|
9
|
+
before do
|
10
|
+
@group = Sync::MailItemGroup.new('dummy sync')
|
11
|
+
end
|
12
|
+
subject { @group }
|
13
|
+
|
14
|
+
should have_readers :thread, :items
|
15
|
+
should have_instance_methods :id, :add, :run, :join
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inbox-sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kelly Redding
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-16 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :development
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/inbox-sync/notice/sync_mail_item_error.rb
|
92
92
|
- lib/inbox-sync/runner.rb
|
93
93
|
- lib/inbox-sync/sync.rb
|
94
|
+
- lib/inbox-sync/sync/mail_item_group.rb
|
94
95
|
- lib/inbox-sync/version.rb
|
95
96
|
- log/.gitkeep
|
96
97
|
- test/config/filter_test.rb
|
@@ -102,6 +103,7 @@ files:
|
|
102
103
|
- test/runner_test.rb
|
103
104
|
- test/sync/basic_test.rb
|
104
105
|
- test/sync/login_test.rb
|
106
|
+
- test/sync/mail_item_group_test.rb
|
105
107
|
homepage: http://github.com/kellyredding/inbox-sync
|
106
108
|
licenses: []
|
107
109
|
|
@@ -145,3 +147,4 @@ test_files:
|
|
145
147
|
- test/runner_test.rb
|
146
148
|
- test/sync/basic_test.rb
|
147
149
|
- test/sync/login_test.rb
|
150
|
+
- test/sync/mail_item_group_test.rb
|