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 +3 -0
- data/lib/mail_spy/manager.rb +3 -9
- data/lib/mail_spy/version.rb +1 -1
- data/lib/mail_spy.rb +1 -1
- metadata +28 -18
- data/lib/mail_spy/thread_pool.rb +0 -119
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
|
data/lib/mail_spy/manager.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
109
|
+
wq.join
|
116
110
|
sent
|
117
111
|
end
|
118
112
|
|
data/lib/mail_spy/version.rb
CHANGED
data/lib/mail_spy.rb
CHANGED
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.
|
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:
|
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:
|
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: :
|
90
|
+
type: :runtime
|
91
91
|
version_requirements: *id007
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
|
-
name:
|
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:
|
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:
|
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:
|
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:
|
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
|
144
|
+
version: "0"
|
145
145
|
type: :development
|
146
146
|
version_requirements: *id012
|
147
147
|
- !ruby/object:Gem::Dependency
|
148
|
-
name: spork
|
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:
|
155
|
+
version: 0.9.0.rc
|
156
156
|
type: :development
|
157
157
|
version_requirements: *id013
|
158
158
|
- !ruby/object:Gem::Dependency
|
159
|
-
name:
|
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:
|
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:
|
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
|
data/lib/mail_spy/thread_pool.rb
DELETED
@@ -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
|