mail_spy 0.0.12 → 0.0.13

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.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