mailcannon 0.0.8.pre.1 → 0.0.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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailcannon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8.pre.1
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Martins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-05 00:00:00.000000000 Z
11
+ date: 2014-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: librato-metrics
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: airbrake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: vcr
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -278,20 +306,16 @@ files:
278
306
  - lib/mailcannon.rb
279
307
  - lib/mailcannon/adapter.rb
280
308
  - lib/mailcannon/adapters/sendgrid_web.rb
309
+ - lib/mailcannon/airbrake.rb
281
310
  - lib/mailcannon/envelope.rb
282
311
  - lib/mailcannon/envelope_bag.rb
283
- - lib/mailcannon/envelope_bag_map_reduce.rb
284
- - lib/mailcannon/envelope_bag_statistic.rb
285
312
  - lib/mailcannon/event.rb
286
313
  - lib/mailcannon/hash.rb
314
+ - lib/mailcannon/librato.rb
287
315
  - lib/mailcannon/mail.rb
288
- - lib/mailcannon/reduces/envelope_bag_map.js
289
- - lib/mailcannon/reduces/envelope_bag_reduce.js
290
- - lib/mailcannon/sendgrid_event.rb
291
316
  - lib/mailcannon/stamp.rb
292
317
  - lib/mailcannon/version.rb
293
318
  - lib/mailcannon/workers/barrel.rb
294
- - lib/mailcannon/workers/envelope_bag_reduce_job.rb
295
319
  - mailcannon.gemspec
296
320
  - spec/factories/envelope.rb
297
321
  - spec/factories/envelope_bag.rb
@@ -300,16 +324,14 @@ files:
300
324
  - spec/fixtures/cassettes/mailcannon_adapter_sendgrid_send_bulk.yml
301
325
  - spec/fixtures/cassettes/mailcannon_integration_1k.yml
302
326
  - spec/integration/1k_spec.rb
303
- - spec/integration/full_stack_stats_spec.rb
304
327
  - spec/integration/xsmtpapi_spec.rb
305
328
  - spec/mailcannon/adapters/sendgrid_spec.rb
306
- - spec/mailcannon/envelope_bag_map_reduce_spec.rb
329
+ - spec/mailcannon/airbrake_spec.rb
307
330
  - spec/mailcannon/envelope_bag_spec.rb
308
- - spec/mailcannon/envelope_bag_statistic_spec.rb
309
331
  - spec/mailcannon/envelope_spec.rb
332
+ - spec/mailcannon/librato_spec.rb
310
333
  - spec/mailcannon/stamp_spec.rb
311
334
  - spec/mailcannon/workers/barrel_spec.rb
312
- - spec/mailcannon/workers/envelope_bag_reduce_job_spec.rb
313
335
  - spec/mailcannon_spec.rb
314
336
  - spec/spec_helper.rb
315
337
  - spec/support/mongoid.yml
@@ -330,9 +352,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
330
352
  version: 1.9.3
331
353
  required_rubygems_version: !ruby/object:Gem::Requirement
332
354
  requirements:
333
- - - '>'
355
+ - - '>='
334
356
  - !ruby/object:Gem::Version
335
- version: 1.3.1
357
+ version: '0'
336
358
  requirements: []
337
359
  rubyforge_project:
338
360
  rubygems_version: 2.0.14
@@ -347,16 +369,14 @@ test_files:
347
369
  - spec/fixtures/cassettes/mailcannon_adapter_sendgrid_send_bulk.yml
348
370
  - spec/fixtures/cassettes/mailcannon_integration_1k.yml
349
371
  - spec/integration/1k_spec.rb
350
- - spec/integration/full_stack_stats_spec.rb
351
372
  - spec/integration/xsmtpapi_spec.rb
352
373
  - spec/mailcannon/adapters/sendgrid_spec.rb
353
- - spec/mailcannon/envelope_bag_map_reduce_spec.rb
374
+ - spec/mailcannon/airbrake_spec.rb
354
375
  - spec/mailcannon/envelope_bag_spec.rb
355
- - spec/mailcannon/envelope_bag_statistic_spec.rb
356
376
  - spec/mailcannon/envelope_spec.rb
377
+ - spec/mailcannon/librato_spec.rb
357
378
  - spec/mailcannon/stamp_spec.rb
358
379
  - spec/mailcannon/workers/barrel_spec.rb
359
- - spec/mailcannon/workers/envelope_bag_reduce_job_spec.rb
360
380
  - spec/mailcannon_spec.rb
361
381
  - spec/spec_helper.rb
362
382
  - spec/support/mongoid.yml
@@ -1,106 +0,0 @@
1
- module MailCannon::EnvelopeBagMapReduce
2
- module ClassMethods
3
-
4
- def find_gem_root_path
5
- path = ""
6
- begin
7
- spec = Gem::Specification.find_by_name("mailcannon")
8
- path = spec.gem_dir
9
- rescue LoadError => e
10
- raise unless e.message =~ /mailcannon/
11
- puts 'mailcannon gem path not found'
12
- end
13
- path
14
- end
15
-
16
- def reduce_statistics_for_envelope_bag(id)
17
- events = change_events_status_for_envelope_bag(id, nil, :lock)
18
- result = events.map_reduce(self.js_map, self.js_reduce).out(merge: "mail_cannon_envelope_bag_statistics")
19
- set_events_to(events,:processed)
20
- {raw: result.raw, count: events.count}
21
- end
22
-
23
- def statistics_for_envelope(id)
24
- self.stats
25
- end
26
-
27
- def js_map
28
- root_path = find_gem_root_path
29
- root_path += "/" unless root_path.empty?
30
- @js_map ||= File.read("#{root_path}lib/mailcannon/reduces/envelope_bag_map.js")
31
- #TODO cache this
32
- @js_map
33
- end
34
-
35
- def js_reduce
36
- root_path = find_gem_root_path
37
- root_path += "/" unless root_path.empty?
38
- @js_reduce ||= File.read("#{root_path}lib/mailcannon/reduces/envelope_bag_reduce.js")
39
- #TODO cache this
40
- @js_reduce
41
- end
42
-
43
- # [from|to]sym = :new, :lock, :processed
44
- def change_events_status_for_envelope_bag(id, from_sym, to_sym)
45
- from_status = processed_status_for(from_sym)
46
- to_status = processed_status_for(to_sym)
47
- if from_sym
48
- query = MailCannon::SendgridEvent.where(envelope_bag_id: id, processed: from_status)
49
- else
50
- query = MailCannon::SendgridEvent.where(envelope_bag_id: id)
51
- end
52
- if query.kind_of?(Mongoid::Criteria)
53
- query.update_all(processed: to_status)
54
- else
55
- query.processed=to_status
56
- query.save
57
- end
58
- query
59
- end
60
-
61
- #private
62
- def set_events_to(events,status)
63
- status = processed_status_for(status)
64
- if events.kind_of?(Mongoid::Criteria)
65
- events.update_all(processed: status)
66
- else
67
- events.processed=status
68
- events.save
69
- end
70
- end
71
-
72
- def processed_status_for(input)
73
- status_map = {
74
- lock: false,
75
- processed: true,
76
- new: nil
77
- }
78
- if [false,true,nil].include?(input)
79
- status_map = status_map.invert
80
- raise "Unexpected input(#{input})" unless status_map.has_key?(input)
81
- end
82
- status_map[input]
83
- end
84
-
85
- end
86
-
87
- module InstanceMethods
88
- def reduce_statistics
89
- self.class.reduce_statistics_for_envelope_bag(self.id)
90
- end
91
-
92
- def statistics
93
- self.class.statistics_for_envelope(self.id)
94
- end
95
-
96
- def change_events_status(from_sym, to_sym)
97
- self.set_processed_status_for_envelope(self.id, from_sym, to_sym)
98
- end
99
- end
100
-
101
- def self.included(receiver)
102
- receiver.extend ClassMethods
103
- receiver.send :include, InstanceMethods
104
- end
105
- end
106
-
@@ -1,5 +0,0 @@
1
- # Holds information about a recipient's email event, like deliveries and bounces.
2
- class MailCannon::EnvelopeBagStatistic
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
- end
@@ -1,3 +0,0 @@
1
- function () {
2
- emit(this.envelope_bag_id, { target_id: this.target_id, event: this.event, type: this.type });
3
- }
@@ -1,116 +0,0 @@
1
- function (key, values) {
2
- var result = {
3
- 'posted': {
4
- 'count': 0,
5
- 'targets': []
6
- },
7
- 'processed': {
8
- 'count': 0,
9
- 'targets': []
10
- },
11
- 'delivered': {
12
- 'count': 0,
13
- 'targets': []
14
- },
15
- 'open': {
16
- 'count': 0,
17
- 'targets': []
18
- },
19
- 'click': {
20
- 'count': 0,
21
- 'targets': []
22
- },
23
- 'deferred': {
24
- 'count': 0,
25
- 'targets': []
26
- },
27
- 'spam_report': {
28
- 'count': 0,
29
- 'targets': []
30
- },
31
- 'spam': {
32
- 'count': 0,
33
- 'targets': []
34
- },
35
- 'unsubscribe': {
36
- 'count': 0,
37
- 'targets': []
38
- },
39
- 'drop': {
40
- 'count': 0,
41
- 'targets': []
42
- },
43
- 'hard_bounce': {
44
- 'count': 0,
45
- 'targets': []
46
- },
47
- 'soft_bounce': {
48
- 'count': 0,
49
- 'targets': []
50
- },
51
- 'unknown': {
52
- 'count': 0,
53
- 'targets': []
54
- }
55
- };
56
-
57
- values.forEach(function(value) {
58
- switch (value['event']) {
59
- case 'posted':
60
- result['posted']['count']++;
61
- result['posted']['targets'].push(value['target_id']);
62
- break;
63
- case 'processed':
64
- result['processed']['count']++;
65
- result['processed']['targets'].push(value['target_id']);
66
- break;
67
- case 'delivered':
68
- result['delivered']['count']++;
69
- result['delivered']['targets'].push(value['target_id']);
70
- break;
71
- case 'open':
72
- result['open']['count']++;
73
- result['open']['targets'].push(value['target_id']);
74
- break;
75
- case 'click':
76
- result['click']['count']++;
77
- result['click']['targets'].push(value['target_id']);
78
- break;
79
- case 'deferred':
80
- result['deferred']['count']++;
81
- result['deferred']['targets'].push(value['target_id']);
82
- break;
83
- case 'spam_report':
84
- result['spam_report']['count']++;
85
- result['spam_report']['targets'].push(value['target_id']);
86
- break;
87
- case 'spam':
88
- result['spam']['count']++;
89
- result['spam']['targets'].push(value['target_id']);
90
- break;
91
- case 'unsubscribe':
92
- result['unsubscribe']['count']++;
93
- result['unsubscribe']['targets'].push(value['target_id']);
94
- break;
95
- case 'drop':
96
- result['drop']['count']++;
97
- result['drop']['targets'].push(value['target_id']);
98
- break;
99
- case 'bounce':
100
- if(value['type'] == "bounce"){
101
- result['hard_bounce']['count']++;
102
- result['hard_bounce']['targets'].push(value['target_id']);
103
- }
104
- else {
105
- result['soft_bounce']['count']++;
106
- result['soft_bounce']['targets'].push(value['target_id']);
107
- }
108
- break;
109
- default:
110
- result['unknown']['count']++;
111
- result['unknown']['targets'].push(value['target_id']);
112
- break;
113
- }
114
- });
115
- return result;
116
- }
@@ -1,18 +0,0 @@
1
- class MailCannon::SendgridEvent
2
- include Mongoid::Document
3
- field :envelope_id, type: String
4
- field :envelope_bag_id, type: String
5
- field :email, type: String
6
- field :timestamp, type: String
7
- field :unique_arg, type: String
8
- field :event, type: String
9
- field :type, type: String
10
- field :processed, type: Boolean, default: nil
11
-
12
- belongs_to :envelope
13
- belongs_to :envelope_bag
14
-
15
- def self.insert_bulk(tha_huge_string)
16
- MailCannon::SendgridEvent.collection.insert(tha_huge_string)
17
- end
18
- end
@@ -1,11 +0,0 @@
1
- class MailCannon::EnvelopeBagReduceJob
2
- include Sidekiq::Worker
3
-
4
- def perform(envelope_bag_ids)
5
- envelope_bag_ids.each do |id|
6
- id = id['$oid'] if id['$oid']
7
- MailCannon::EnvelopeBag.reduce_statistics_for_envelope_bag(id)
8
- end
9
- end
10
-
11
- end
@@ -1,118 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe 'full stack test' do
4
- describe "should send 2 envelopes, receive correct statistics and map/reduce data correctly" do
5
-
6
- let(:expected_hash_a){
7
- {
8
- "posted"=>{"count"=>1.0, "targets"=>["1"]},
9
- "processed"=>{"count"=>1.0, "targets"=>["2"]},
10
- "delivered"=>{"count"=>1.0, "targets"=>["3"]},
11
- "open" => {"count"=>1.0, "targets"=>["4"]},
12
- "click"=>{"count"=>1.0, "targets"=>["5"]},
13
- "deferred"=>{"count"=>1.0, "targets"=>["6"]},
14
- "spam_report"=>{"count"=>1.0, "targets"=>["7"]},
15
- "spam"=>{"count"=>1.0, "targets"=>["8"]},
16
- "unsubscribe"=>{"count"=>1.0, "targets"=>["9"]},
17
- "drop"=>{"count"=>1.0, "targets"=>["10"]},
18
- "hard_bounce" => {"count"=>1.0, "targets"=>["11"]},
19
- "soft_bounce"=>{"count"=>1.0, "targets"=>["12"]},
20
- "unknown"=>{"count"=>1.0, "targets"=>["13"]}
21
- }
22
- }
23
-
24
- let(:expected_hash_b){
25
- {
26
- "posted"=>{"count"=>2.0, "targets"=>["1", "1" ]},
27
- "processed"=>{"count"=>2.0, "targets"=>["2", "2"]},
28
- "delivered"=>{"count"=>2.0, "targets"=>["3", "3"]},
29
- "open" => {"count"=>2.0, "targets"=>["4", "4"]},
30
- "click"=>{"count"=>2.0, "targets"=>["5","5"]},
31
- "deferred"=>{"count"=>2.0, "targets"=>["6", "6"]},
32
- "spam_report"=>{"count"=>2.0, "targets"=>["7", "7"]},
33
- "spam"=>{"count"=>2.0, "targets"=>["8", "8"]},
34
- "unsubscribe"=>{"count"=>2.0, "targets"=>["9", "9"]},
35
- "drop"=>{"count"=>2.0, "targets"=>["10", "10"]},
36
- "hard_bounce" => {"count"=>2.0, "targets"=>["11", "11"]},
37
- "soft_bounce"=>{"count"=>2.0, "targets"=>["12", "12"]},
38
- "unknown"=>{"count"=>2.0, "targets"=>["13", "13"]}
39
- }
40
- }
41
-
42
- context "send emails and map reduce" do
43
- let(:envelope_bag) { build(:empty_envelope_bag)}
44
- let!(:envelope_a) { build(:envelope_multi) }
45
- let!(:envelope_b) { build(:envelope_multi) }
46
-
47
- it "sends http request for Sendgrid web API" do
48
- envelope_bag.save
49
- envelope_bag.envelopes << envelope_a
50
- envelope_bag.envelopes << envelope_b
51
- VCR.use_cassette('mailcannon_adapter_sendgrid_send_bulk') do
52
- Sidekiq::Testing.inline! do
53
- bm = Benchmark.measure do
54
- envelope_a.send_bulk!
55
- end
56
- end
57
- end
58
-
59
- envelope_a_hash = [
60
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'posted', target_id: '1'},
61
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'processed', target_id: '2'},
62
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'delivered', target_id: '3'},
63
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'open', target_id: '4'},
64
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'click', type: 'bounce', target_id: '5'},
65
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'deferred', type: 'expected', target_id: '6'},
66
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'spam_report', target_id: '7'},
67
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'spam', target_id: '8'},
68
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'unsubscribe', target_id: '9'},
69
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'drop', target_id: '10'},
70
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'bounce', type: 'bounce', target_id: '11'},
71
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'bounce', type: 'expected', target_id: '12'},
72
- {envelope_id: envelope_a.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'gfyigad', target_id: '13'},
73
- ]
74
- MailCannon::SendgridEvent.insert_bulk(envelope_a_hash)
75
-
76
- Sidekiq::Testing.inline! do
77
- MailCannon::EnvelopeBagReduceJob.perform_async([envelope_bag.id])
78
- end
79
-
80
- expect(envelope_a.reload.sendgrid_events.where(processed: true).count).to eq(13)
81
- expect(envelope_bag.stats).to eq(expected_hash_a)
82
-
83
- VCR.use_cassette('mailcannon_adapter_sendgrid_send_bulk') do
84
- Sidekiq::Testing.inline! do
85
- bm = Benchmark.measure do
86
- envelope_b.send_bulk!
87
- end
88
- end
89
- end
90
-
91
- envelope_b_hash = [
92
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'posted', target_id: '1'},
93
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'processed', target_id: '2'},
94
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'delivered', target_id: '3'},
95
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'open', target_id: '4'},
96
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'click', type: 'bounce', target_id: '5'},
97
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'deferred', type: 'expected', target_id: '6'},
98
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'spam_report', target_id: '7'},
99
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'spam', target_id: '8'},
100
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo1@bar.com', timestamp: 1322000092, unique_arg: 'my unique arg', event: 'unsubscribe', target_id: '9'},
101
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo2@bar.com', timestamp: 1322000093, unique_arg: 'my unique arg', event: 'drop', target_id: '10'},
102
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'bounce', type: 'bounce', target_id: '11'},
103
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'bounce', type: 'expected', target_id: '12'},
104
- {envelope_id: envelope_b.id, envelope_bag_id: envelope_bag.id, email: 'foo3@bar.com', timestamp: 1322000094, unique_arg: 'my unique arg', event: 'gfyigad', target_id: '13'},
105
- ]
106
- MailCannon::SendgridEvent.insert_bulk(envelope_b_hash)
107
-
108
- Sidekiq::Testing.inline! do
109
- MailCannon::EnvelopeBagReduceJob.perform_async([envelope_bag.id])
110
- end
111
-
112
- expect(envelope_b.reload.sendgrid_events.where(processed: true).count).to eq(13)
113
- expect(envelope_bag.stats).to eq(expected_hash_b)
114
- end
115
- end
116
-
117
- end
118
- end