mail_spy 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -15,6 +15,9 @@ Add gem "mailspy" to your Gemfile
15
15
  If you haven't already create a mongoid.yml file for the mongodb connection
16
16
  rails generate mongoid:config
17
17
 
18
+ If you are going to be sending on one machine make sure to scale up the pool
19
+ from the default of 1 to 10+ to get good performance. Timeouts are also a good idea
20
+
18
21
  Create the mongoid configuration for the mongo db
19
22
 
20
23
  rails g mail_spy:initializer
@@ -73,7 +73,7 @@ module MailSpy
73
73
  def send_outstanding_emails(step=100, num_threads=50)
74
74
  raise "No Email service providers installed" unless MailSpy.esps.present?
75
75
 
76
- pool = MailSpy::ThreadPool.new(num_threads)
76
+ wq = WorkQueue.new(num_threads, step*2)
77
77
  offset = 0
78
78
  sent = 0
79
79
 
@@ -84,14 +84,13 @@ module MailSpy
84
84
  pony_hash[pony_key] = value if value.present?
85
85
  end
86
86
 
87
-
88
87
  while true
89
88
  emails = MailSpy::Email.
90
89
  limit(step).offset(offset).
91
90
  where(:schedule_at.lte => DateTime.now, :sent => false, :failed => false).all
92
91
  break if emails.blank?
93
92
  emails.each do |email|
94
- pool.schedule do
93
+ wq.enqueue_b do
95
94
  begin
96
95
  MailSpy::CoreMailer.template(email).deliver
97
96
  email.update_attribute(:sent, true)
@@ -103,16 +102,11 @@ module MailSpy
103
102
  email.save!
104
103
  end
105
104
  end
106
-
107
- while(pool.job_queue_size > (2 * num_threads))
108
- sleep(1)
109
- end
110
-
111
105
  end
112
106
  offset += step
113
107
  end
114
108
 
115
- pool.shutdown
109
+ wq.join
116
110
  sent
117
111
  end
118
112
 
@@ -1,3 +1,3 @@
1
1
  module MailSpy
2
- VERSION = "0.0.12"
2
+ VERSION = "0.0.13"
3
3
  end
data/lib/mail_spy.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'pp' #For debugging
2
2
  require 'aws-sdk'
3
3
  require 'mail_spy/sendgrid/smtp_api_header'
4
- require 'mail_spy/thread_pool'
4
+ require 'work_queue'
5
5
  require "mongoid"
6
6
  require "mail_spy/engine"
7
7
  require "mail_spy/manager"
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mail_spy
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.12
5
+ version: 0.0.13
6
6
  platform: ruby
7
7
  authors:
8
8
  - Timothy Cardenas
@@ -68,7 +68,7 @@ dependencies:
68
68
  type: :runtime
69
69
  version_requirements: *id005
70
70
  - !ruby/object:Gem::Dependency
71
- name: jquery-rails
71
+ name: work_queue
72
72
  prerelease: false
73
73
  requirement: &id006 !ruby/object:Gem::Requirement
74
74
  none: false
@@ -79,7 +79,7 @@ dependencies:
79
79
  type: :runtime
80
80
  version_requirements: *id006
81
81
  - !ruby/object:Gem::Dependency
82
- name: sqlite3
82
+ name: jquery-rails
83
83
  prerelease: false
84
84
  requirement: &id007 !ruby/object:Gem::Requirement
85
85
  none: false
@@ -87,10 +87,10 @@ dependencies:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: "0"
90
- type: :development
90
+ type: :runtime
91
91
  version_requirements: *id007
92
92
  - !ruby/object:Gem::Dependency
93
- name: turn
93
+ name: sqlite3
94
94
  prerelease: false
95
95
  requirement: &id008 !ruby/object:Gem::Requirement
96
96
  none: false
@@ -101,7 +101,7 @@ dependencies:
101
101
  type: :development
102
102
  version_requirements: *id008
103
103
  - !ruby/object:Gem::Dependency
104
- name: rr
104
+ name: turn
105
105
  prerelease: false
106
106
  requirement: &id009 !ruby/object:Gem::Requirement
107
107
  none: false
@@ -112,7 +112,7 @@ dependencies:
112
112
  type: :development
113
113
  version_requirements: *id009
114
114
  - !ruby/object:Gem::Dependency
115
- name: factory_girl
115
+ name: rr
116
116
  prerelease: false
117
117
  requirement: &id010 !ruby/object:Gem::Requirement
118
118
  none: false
@@ -123,7 +123,7 @@ dependencies:
123
123
  type: :development
124
124
  version_requirements: *id010
125
125
  - !ruby/object:Gem::Dependency
126
- name: factory_girl_rails
126
+ name: factory_girl
127
127
  prerelease: false
128
128
  requirement: &id011 !ruby/object:Gem::Requirement
129
129
  none: false
@@ -134,29 +134,29 @@ dependencies:
134
134
  type: :development
135
135
  version_requirements: *id011
136
136
  - !ruby/object:Gem::Dependency
137
- name: spork
137
+ name: factory_girl_rails
138
138
  prerelease: false
139
139
  requirement: &id012 !ruby/object:Gem::Requirement
140
140
  none: false
141
141
  requirements:
142
- - - ">"
142
+ - - ">="
143
143
  - !ruby/object:Gem::Version
144
- version: 0.9.0.rc
144
+ version: "0"
145
145
  type: :development
146
146
  version_requirements: *id012
147
147
  - !ruby/object:Gem::Dependency
148
- name: spork-testunit
148
+ name: spork
149
149
  prerelease: false
150
150
  requirement: &id013 !ruby/object:Gem::Requirement
151
151
  none: false
152
152
  requirements:
153
- - - ">="
153
+ - - ">"
154
154
  - !ruby/object:Gem::Version
155
- version: "0"
155
+ version: 0.9.0.rc
156
156
  type: :development
157
157
  version_requirements: *id013
158
158
  - !ruby/object:Gem::Dependency
159
- name: ruby-prof
159
+ name: spork-testunit
160
160
  prerelease: false
161
161
  requirement: &id014 !ruby/object:Gem::Requirement
162
162
  none: false
@@ -167,7 +167,7 @@ dependencies:
167
167
  type: :development
168
168
  version_requirements: *id014
169
169
  - !ruby/object:Gem::Dependency
170
- name: minitest
170
+ name: ruby-prof
171
171
  prerelease: false
172
172
  requirement: &id015 !ruby/object:Gem::Requirement
173
173
  none: false
@@ -178,7 +178,7 @@ dependencies:
178
178
  type: :development
179
179
  version_requirements: *id015
180
180
  - !ruby/object:Gem::Dependency
181
- name: timecop
181
+ name: minitest
182
182
  prerelease: false
183
183
  requirement: &id016 !ruby/object:Gem::Requirement
184
184
  none: false
@@ -188,6 +188,17 @@ dependencies:
188
188
  version: "0"
189
189
  type: :development
190
190
  version_requirements: *id016
191
+ - !ruby/object:Gem::Dependency
192
+ name: timecop
193
+ prerelease: false
194
+ requirement: &id017 !ruby/object:Gem::Requirement
195
+ none: false
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: "0"
200
+ type: :development
201
+ version_requirements: *id017
191
202
  description: Mailspy allows for quick and easy creation, sending and tracking of email campaigns
192
203
  email:
193
204
  - trcarden@gmail.com
@@ -225,7 +236,6 @@ files:
225
236
  - lib/mail_spy/engine.rb
226
237
  - lib/mail_spy/manager.rb
227
238
  - lib/mail_spy/sendgrid/smtp_api_header.rb
228
- - lib/mail_spy/thread_pool.rb
229
239
  - lib/mail_spy/version.rb
230
240
  - lib/mail_spy.rb
231
241
  - lib/tasks/mail_spy_tasks.rake
@@ -1,119 +0,0 @@
1
- # Ruby Thread ThreadPool
2
- # ================
3
- # A thread pool is useful when you wish to do some work in a thread, but do
4
- # not know how much work you will be doing in advance. Spawning one thread
5
- # for each task is potentially expensive, as threads are not free.
6
- #
7
- # In this case, it might be more beneficial to start a predefined set of
8
- # threads and then hand off work to them as it becomes available. This is
9
- # the pure essence of what a thread pool is: an array of threads, all just
10
- # waiting to do some work for you!
11
- #
12
- # Prerequisites
13
- # -------------
14
-
15
- # We need the [Queue](http://rdoc.info/stdlib/thread/1.9.2/Queue), as our
16
- # thread pool is largely dependent on it. Thanks to this, the implementation
17
- # becomes very simple!
18
- require 'thread'
19
-
20
- module MailSpy
21
- # Public Interface
22
- # ----------------
23
-
24
- # `ThreadPool` is our thread pool class. It will allow us to do three operations:
25
- #
26
- # - `.new(size)` creates a thread pool of a given size
27
- # - `#schedule(*args, &job)` schedules a new job to be executed
28
- # - `#shutdown` shuts down all threads (after letting them finish working, of course)
29
- class ThreadPool
30
-
31
- # ### initialization, or `ThreadPool.new(size)`
32
- # Creating a new `ThreadPool` involves a certain amount of work. First, however,
33
- # we need to define its’ `size`. It defines how many threads we will have
34
- # working internally.
35
- #
36
- # Which size is best for you is hard to answer. You do not want it to be
37
- # too low, as then you won’t be able to do as many things concurrently.
38
- # However, if you make it too high Ruby will spend too much time switching
39
- # between threads, and that will also degrade performance!
40
- def initialize(size)
41
- # Before we do anything else, we need to store some information about
42
- # our pool. `@size` is useful later, when we want to shut our pool down,
43
- # and `@jobs` is the heart of our pool that allows us to schedule work.
44
- @size = size
45
- @jobs = Queue.new
46
-
47
- # #### Creating our pool of threads
48
- # Once preparation is done, it’s time to create our pool of threads.
49
- # Each thread store its’ index in a thread-local variable, in case we
50
- # need to know which thread a job is executing in later on.
51
- @pool = Array.new(@size) do |i|
52
- Thread.new do
53
- Thread.current[:id] = i
54
-
55
- # We start off by defining a `catch` around our worker loop. This
56
- # way we’ve provided a method for graceful shutdown of our threads.
57
- # Shutting down is merely a `#schedule { throw :exit }` away!
58
- catch(:exit) do
59
- # The worker thread life-cycle is very simple. We continuously wait
60
- # for tasks to be put into our job `Queue`. If the `Queue` is empty,
61
- # we will wait until it’s not.
62
- loop do
63
- # Once we have a piece of work to be done, we will pull out the
64
- # information we need and get to work.
65
- job, args = @jobs.pop
66
- job.call(*args)
67
- end
68
- end
69
- end
70
- end
71
- end
72
-
73
- def job_queue_size
74
- @jobs.size
75
- end
76
-
77
- # ### Work scheduling
78
-
79
- # To schedule a piece of work to be done is to say to the `ThreadPool` that you
80
- # want something done.
81
- def schedule(*args, &block)
82
- # Your given task will not be run immediately; rather, it will be put
83
- # into the work `Queue` and executed once a thread is ready to work.
84
- @jobs << [block, args]
85
- end
86
-
87
- # ### Graceful shutdown
88
-
89
- # If you ever wish to close down your application, I took the liberty of
90
- # making it easy for you to wait for any currently executing jobs to finish
91
- # before you exit.
92
- def shutdown
93
- # A graceful shutdown involves threads exiting cleanly themselves, and
94
- # since we’ve defined a `catch`-handler around the threads’ worker loop
95
- # it is simply a matter of throwing `:exit`. Thus, if we throw one `:exit`
96
- # for each thread in our pool, they will all exit eventually!
97
- @size.times do
98
- schedule { throw :exit }
99
- end
100
-
101
- # And now one final thing: wait for our `throw :exit` jobs to be run on
102
- # all our worker threads. This call will not return until all worker threads
103
- # have exited.
104
- @pool.map(&:join)
105
- end
106
- end
107
- end
108
- # example
109
- #if $0 == __FILE__
110
- # p = Pool.new(10)
111
- #
112
- # 20.times do |i|
113
- # p.schedule do
114
- # sleep rand(4) + 2
115
- # puts "Job #{i} finished by thread #{Thread.current[:id]}"
116
- # end
117
- # end
118
- # at_exit { p.shutdown }
119
- #end