ruby 1.8.7 многопоточная почта 'неинициализированная константа (NameError)'

Мой скрипт отправляет электронные письма для списка пользователей. Мне нужна многопоточность, потому что ошибка в 1 адресе приводит к сбою всего приложения. Это моя реализация:

  require 'thread'
  <...>
  lock = Mutex.new
  lock.synchronize {
    @model.certs.each{ |user|
      @threads << Thread.new(user) { |data|
      to = "#{data['name']} #{data['surname']} <#{data['email']}>"
      subject = '<Subject>'
      body = "<Body>"
      view = View.new()
      view.to = to
      view.body = body
      view.subject = subject
      view.attachment = ''
      view.sendMessage()
      @model.sended(data['email'])
      }
    }
  }

  @threads.each { |t|
    begin
      t.join
    rescue => err
      $log.fatal(err)
    end
  }

view.sendMessage состоит:

require 'mail'
require 'net/smtp'
<...>
smtp = Net::SMTP.start(@mailserver)
mail = Mail.new()
mail.from = @from
mail.to = @to
mail.subject = @subject
mail.body = @body
if [email protected]?
  mail.add_file @attachment
end
mail.delivery_method :smtp_connection, {
  :connection => smtp
}
mail.deliver

И иногда выдает такие ошибки, как:

uninitialized constant Mail::Field::FromField (NameError)
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/field.rb:189:in `new_field'

or

uninitialized constant Mail::CommonAddress::AddressList (NameError)
/var/lib/gems/1.8/gems/mail-2.4.4/lib/mail/fields/common/common_address.rb:9:in `parse'

Я понятия не имею, как это можно исправить. Добавление мьютекса не дает результата.


person Michael    schedule 06.05.2013    source источник


Ответы (2)


@FrederickCheung прав насчет требований в потоках. Кроме того, вам действительно нужны потоки? Что не так с:

emails.each do |mail|
  begin
    mail.deliver
  rescue TheCorrectExceptionForInvalidEmails
    puts "invalid e-mail: x"
    method_to_remove_invalid_email_from_database
  end
end

Даже если вы оставите пустой блок для спасения в недействительном электронном письме, он перепрыгнет и продолжит выполнение.

person fotanus    schedule 06.05.2013
comment
Даже если вы не реализуете метод обработки плохого письма, вы все равно можете продолжить отправку. Проверить мои изменения - person fotanus; 06.05.2013
comment
Похоже на мою старую версию кода, из-за которой вылетает все приложение. Я попробую это решение завтра снова. Спасибо. - person Michael; 06.05.2013

Require не является потокобезопасным в ruby. Вы должны убедиться, что все, что вам нужно, уже требуется, прежде чем начинать свои потоки.

Кроме того, ваш мьютекс в настоящее время ничего не делает. Хотя многопоточность может хорошо подходить для такой деятельности, как отправка электронной почты, в которой, вероятно, преобладает сетевая задержка, я бы не сказал, что обработка ошибок является причиной для использования многопоточности (во всяком случае, это усложняет ее).

person Frederick Cheung    schedule 06.05.2013
comment
ИМХО require-error должен быть постоянно, а не периодическим, как в моем случае. Хорошо, я почитаю больше о мьютексе. И какую хорошую практику я должен использовать для обработки ошибок такого типа вместо многопоточности? - person Michael; 06.05.2013
comment
С потоками в require возникают условия гонки - поток 1 находится на полпути к загрузке библиотеки, поэтому поток 2 в конечном итоге использует частично загруженную библиотеку. - person Frederick Cheung; 06.05.2013