Actually looking it is terminating when i call mysql.free after
finishing walking through all of the sends

On Mar 25, 12:42 pm, Miah Petersen <[email protected]> wrote:
> I needed an email queueing system for a project I am writing.  The script
> below runs every minute via a cronjob on one of my servers.  I am using a
> table in mysql to keep track of the number of email bot threads to spawn and
> their current state.  They need to be threaded(or at least run concurrently)
> since some email lists will be longer than others, and some emails have a
> higher priority.  The thought is that this way I can quickly add more email
> threads as is needed, as well as have a simple web ui to check their state
> and turn them on or off as is necessary.
>
> It works perfectly, most of the time.  But sometime, arbitrarily, one of the
> threads does not finish and an email bot state is left as processing.  In
> the log file, it actually says that it completes, but the entry in the
> database still says processing.  Any ideas?
>
> ======== Email Bots Table ===========
> +----+--------+----------------------------------------------+----------------+---------------------+
> | id | status | query_constraints                            | state
>    | updated_at          |
> +----+--------+----------------------------------------------+----------------+---------------------+
> |  1 | on     | select * from email_queue where priority = 0 |
> idle           | 2010-03-25 17:33:14 |
> |  2 | on     | select * from email_queue WHERE priority > 0 |
> idle           | 2010-03-25 17:33:14 |
> +----+--------+----------------------------------------------+----------------+---------------------+
>
> ======== Email bot Script that runs via cronjob ===========
>
> require 'rubygems'
> require 'net/smtp'
> require 'timeout'
> require 'mysql'
> require 'activesupport'
> require 'activerecord'
>
> begin
>   require 'openssl'
> rescue LoadError
> end
>
> ActiveRecord::Base.establish_connection(
>   :adapter => 'mysql',
>   :host => 'localhost',
>   :database => 'adevelopment',
>   :username => 'username',
>   :password => 'password'
> )
>
>   def send_email(from, to, subject, message)
>   msg = <<END_OF_MESSAGE
> From: #{from}
> To: #{to}
> MIME-Version: 1.0
> Content-type: text/html
> Subject: #{subject}
>
> #{message}
> END_OF_MESSAGE
>
>     Net::SMTP.start('server', 25, '<sending domain>','username', 'password',
> :login) do |smtp|
>       smtp.send_message msg, from.gsub(/[^<]+</,'').gsub(/>/,''),
> to.gsub(/[^<]+</,'').gsub(/>/,'')
>     end
>   end
>
>   # gather email bots
>   mysql = ActiveRecord::Base.connection.execute("SELECT * FROM email_bots")
>   emailbots = {}
>   mysql.each_hash do |p|
>     emailbots[p['id']] = p
>   end
>   mysql.free
>
>   threads = []
>   emailbots.each do |emailbot|
>     if emailbot[1]['status'] == 'on' && emailbot[1]['state'] == 'idle'
>       threads << Thread.new{
>         ebot = emailbot[1]
>         ActiveRecord::Base.connection.execute("UPDATE email_bots SET
> state='processing', updated_at=UTC_TIMESTAMP() WHERE id=#{ebot['id']}")
>         sent = ""
>         mysql =
> ActiveRecord::Base.connection.execute(ebot['query_constraints'])
> i = 1
>         mysql.each_hash do |email|
> puts email['id']
>           begin
>             send_email(email['sender'], email['recipient'],
> email['subject'], email['message'])
>             sent += email['id'] + ","
>           rescue Exception => e
>
> ActiveRecord::Base.connection.execute(ActiveRecord::Base.send("sanitize_sql_array",["UPDATE
> email_queue SET error='%s' WHERE id=#{email['id']}", "#{e.message}
> #{e.backtrace.inspect}"]))
>           end
>           i = i + 1
>           if i % 100 == 0
>             if sent != ""
>               ActiveRecord::Base.connection.execute("INSERT INTO email_sent
> (SELECT priority, user_id, #{ebot['id']}, sender, recipient, subject,
> message, error, UTC_TIMESTAMP FROM email_queue WHERE id in
> (#{sent.chop!}))")
>               ActiveRecord::Base.connection.execute("DELETE FROM email_queue
> WHERE id in (#{sent})")
>               sent = ""
>             end
>           end
>         end
>        # the mysql.free is called, but it doesn't run past this.
>         mysql.free
>         if sent != ""
>           ActiveRecord::Base.connection.execute("INSERT INTO email_sent
> (SELECT priority, user_id, #{ebot['id']}, sender, recipient, subject,
> message, error, UTC_TIMESTAMP FROM email_queue WHERE id in
> (#{sent.chop!}))")
>           ActiveRecord::Base.connection.execute("DELETE FROM email_queue
> WHERE id in (#{sent})")
>         end
>         ActiveRecord::Base.connection.execute("UPDATE email_bots SET
> state='idle' WHERE id=#{ebot['id']}")
>       }
>     else
> #  This is a potential work around which i am not too excited about.
> #      mysql =
> ActiveRecord::Base.connection.execute(ebot['query_constraints'])
> #      if mysql.num_rows == 0
> #        ActiveRecord::Base.connection.execute("UPDATE email_bots SET
> current_action='idle' WHERE id=#{ebot['id']}")
>       end
>     end
>   end
>   threads.each { |t|
>     t.join
>   }

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to