Skip to content

Instantly share code, notes, and snippets.

@jhjguxin
Created October 16, 2012 06:07
Show Gist options
  • Save jhjguxin/3897464 to your computer and use it in GitHub Desktop.
Save jhjguxin/3897464 to your computer and use it in GitHub Desktop.
ResqueMailer and whenver base on BBTangCMS and large date export,witch alse a demo about mulit smtp account on rails
....
set :application, "bbtcms"
# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
=begin
task :start, :roles => :app, :except => { :no_release => true } do
#run "cd #{current_path} && passenger start --socket /tmp/passenger.socket --daemonize --environment production"
end
task :stop, :roles => :app, :except => { :no_release => true } do
#run "cd #{current_path} && passenger stop --pid-file tmp/pids/passenger.pid"
end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
=end
desc "start Resque Workers"
task :start_workers, :roles => :db do
#run_remote_rake "resque:restart_workers"
run_remote_rake "COUNT=5 PIDFILE=./resque.pid BACKGROUND=yes QUEUE=#{application} RAILS_ENV=production environment resque:work"
end
desc "stop Resque Workers"
task :stop_workers, :roles => :db do
#run_remote_rake "resque:restart_workers"
run_remote_rake "RAILS_ENV=production resque:stop_workers"
end
desc "Restart Resque Workers"
task :restart_workers, :roles => :db do
#run_remote_rake "resque:restart_workers"
run_remote_rake "RAILS_ENV=production resque:stop_workers"
run_remote_rake "COUNT=5 PIDFILE=./resque.pid BACKGROUND=yes QUEUE=#{application} RAILS_ENV=production environment resque:work"
end
desc "restart Crontab"
task :restart_crontab, :roles => :app do
#stop whenever schedule
run "cd #{current_path}/ && whenever -c #{application}"
#update_crontab
run "cd #{current_path}/ && whenever -i #{current_path}/config/schedule.rb --set environment=#{rails_env} --update-crontab #{application}"
end
desc "Write Crontab"
task :update_crontab, :roles => :app do
run "cd #{current_path}/ && whenever -i #{current_path}/config/schedule.rb --set environment=#{rails_env} --update-crontab #{application}"
end
=begin
desc "reload the database with seed data"
task :seed do
run "cd #{current_path}; bundle exec rake db:seed RAILS_ENV=#{rails_env}"
end
=end
end
after 'deploy:update_code', 'deploy:migrate', "deploy:create_symlink", "deploy:restart_workers", "deploy:restart_crontab", "rvm:trust_rvmrc"
# Deploy with Capistrano
gem 'capistrano'
gem 'rvm-capistrano'
gem "resque", "~> 1.20.0"
gem "resque_mailer", "~> 2.1.0"
#Clean ruby syntax for writing and deploying cron jobs.
gem "whenever", "~> 0.7.3"
class MMBKUser < ActiveRecord::Base
establish_connection "ecshop"
self.table_name = "mmbk_users"
attr_accessible :email, :sex, :birthday, :msn, :qq, :mobile_phone, :City
def to_s
email.present? ? "#{email}" : "mmbkoo user #{id}"
end
end
# encoding: utf-8
class MmbkUserExportReporter
include Mongoid::Document
include Mongoid::Timestamps
#before_validation :set_array
field :plan_count, type: Integer
field :pick_count, type: Integer
field :real_count, type: Integer
field :last_mmbk_user_id, type: Integer
def last_mmbk_user
if "MMBKUser".class_exists? and last_mmbk_user_id.present?
MMBKUser.find_by_id last_mmbk_user_id
end
end
def to_s
"mmbk_user_export_reporter created on #{created_at}" if created_at.present?
end
end
# encoding: utf-8
class MmbkUserExportReporter
include Mongoid::Document
include Mongoid::Timestamps
#before_validation :set_array
field :plan_count, type: Integer
field :pick_count, type: Integer
field :real_count, type: Integer
field :last_mmbk_user_id, type: Integer
def last_mmbk_user
if "MMBKUser".class_exists? and last_mmbk_user_id.present?
MMBKUser.find_by_user_id last_mmbk_user_id
end
end
def to_s
"mmbk_user_export_reporter created on #{created_at}" if created_at.present?
end
end
def newest_obj(mod = "",conditions = [], t_count = "1", unit = "hours")
#User.where("id != ?", exclude_ids)
if mod.present?
mod = mod.classify.constantize if mod.class == String
s_time = t_count.to_i.send(unit).send("ago") if t_count.to_i > 0
s_time ||= 1.hours.ago
mod_list = mod.where(conditions)
if mod_list.present?
mod_list.where(:created_at => s_time .. DateTime.now)
else
[]
end
end
end
def pre_birthday_users(pre_days = 0)
Profile.select(["profiles.id", :birthday, :user_id, :notify_via_email]).compact.collect{|item| item.id if item.birthday_arrive_in?(pre_days.to_i)}.compact
end
def pre_baby_birthday_users(pre_days = 0)
#Baby.select([:birthday, :profile_id])
#Baby.joins(:profile).select(["babies.birthday", :user_id, :notify_via_email])
Baby.joins(:profile).select(["babies.birthday","babies.id", :user_id, :notify_via_email]).compact.collect{|item| item.id if item.birthday_arrive_in?(pre_days.to_i)}.compact
end
def pick_user_and_send_mail(type = "",festival = nil)
# Profile.where("age > 21").find_in_batches
User.joins(:profile).find_in_batches(:batch_size => 500) do |items|
sleep(50) # Make sure it doesn't get too crowded in there!
#items.collect{|item| [item.email,item.profile.notify_via_email]}
items.each do |item|
#UserMail.send("#{type}_notify",item.email,festival).deliver if item.profile.notify_via_email.present?
puts "send mail to #{item}"
UserMail.send("#{type}_notify",item.email,festival).deliver
#UserMail.send("#{type}_notify",item.email,festival)
end
end
end
namespace 'bbtangcms' do
namespace 'notify' do
desc "pick up questions inside a time range and send a mail"
task :new_question_notify => :environment do
#questions = newest_obj(mod = "Question", t_count = "10", unit = "minutes").compact.uniq#params picked follw queue order when method defined
questions = newest_obj(mod = "Question",conditions = [], t_count = "10", unit = "minutes").compact.uniq
questions.each do |question|
UserMail.send_new_question_notify(email = "[email protected]", question_id = question.id ).deliver if question.present?
end
#UserMail.send_new_question_notify(email = "[email protected]", question_id = Question.last.id ).deliver
end
desc "pick up user and send a mail about user_birthday_notify"
task :user_birthday_notify => :environment do
#for test
puts "bein to pick up user and send a mail about user_birthday_notify ..."
#pre_birthday_users.collect{|p| puts "send mail to profile #{p}";UserMail.send("user_birthday_notify",p) if Profile.exists? p}
pre_birthday_users.collect{|p| puts "send mail to profile #{p}";UserMail.send("user_birthday_notify",p).deliver if Profile.exists? p}
end
desc "pick up baby and send a mail about baby_birthday_notify"
task :baby_birthday_notify => :environment do
#for test
puts "bein to pick up baby and send a mail about baby_birthday_notify ..."
#pre_baby_birthday_users.collect{|b| puts "send mail to baby #{b}";UserMail.send("baby_birthday_notify",b) if Baby.exists? b}
pre_baby_birthday_users.collect{|b| puts "send mail to profile #{p}";UserMail.send("baby_birthday_notify",b).deliver if Baby.exists? b}
end
desc "pick up baby and send a mail about baby_birthday_notify"
task :weekly_notify => :environment do
puts "bein to pick up user and send a mail about weekly_notify ..."
pick_user_and_send_mail(type="weekly")
end
desc "pick up user and send a mail about monthly_notify"
task :monthly_notify => :environment do
puts "bein to pick up user and send a mail about monthly_notify ..."
pick_user_and_send_mail(type="monthly")
end
desc "pick up user and send a mail about festival_notify"
task :festival_notify => :environment do
puts "bein to pick up user and send a mail about festival_notify ..."
pick_user_and_send_mail(type="festival",festival = "abc")
end
end
end
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
BBTangCMS::Application.load_tasks
require 'rake/dsl_definition'
require 'resque/tasks'
task "resque:setup" => :environment do
ENV['QUEUE'] ||= '*'
#for redistogo on heroku http://stackoverflow.com/questions/2611747/rails-resque-workers-fail-with-pgerror-server-closed-the-connection-unexpectedl
Resque.before_fork = Proc.new { ActiveRecord::Base.establish_connection }
end
namespace :resque do
desc "let resque workers always load the rails environment"
task :setup => :environment do
end
desc "kill all workers (using -QUIT), god will take care of them"
task :stop_workers => :environment do
pids = Array.new
#application = Rails.application.class.parent_name.downcase
application = "bbtcms" #base on deploy.rb :application
Resque.workers.each do |worker|
if worker.to_s.end_with? application
pids << worker.to_s.split(/:/).second
end
end
if pids.size > 0
system("kill -QUIT #{pids.join(' ')}")
end
# god should handle the restart
end
end
####run below command
#Let's start a worker to run file_serve jobs:
#$ cd app_root
#COUNT=5 PIDFILE=./resque.pid BACKGROUND=yes QUEUE=* RAILS_ENV=production rake environment resque:work
#VVERBOSE=true COUNT=5 PIDFILE=./resque.pid QUEUE=* RAILS_ENV=production rake environment resque:work
#COUNT=5 PIDFILE=./resque.pid QUEUE=* RAILS_ENV=development rake environment resque:work
#COUNT=5 PIDFILE=./resque.pid BACKGROUND=yes QUEUE=bbtangcms RAILS_ENV=development rake environment resque:work
#rake RAILS_ENV=production resque:stop_workers
#load_resque.rb
#require 'resque'
#ActionMailer::Base.delivery_method = :sendmail
#Resque::Mailer.default_queue_name = "#{Rails.application.class.parent_name.downcase}"
Resque::Mailer.default_queue_name = 'bbtcms'
class AsyncMailer < ActionMailer::Base
include Resque::Mailer
self.default :from => BBTangCMS::MetaCache.get_config_data("email_account"),
#:abcc => '[email protected]',
:reply_to => BBTangCMS::MetaCache.get_config_data("email_reply_address"),
:sender => BBTangCMS::MetaCache.get_config_data("email_account")
end
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Example:
#
# set :output, "/path/to/my/cron_log.log"
#
# every 2.hours do
# command "/usr/bin/some_great_command"
# runner "MyModel.some_method"
# rake "some:great:rake:task"
# end
#
# every 4.days do
# runner "AnotherModel.prune_old_records"
# end
# Learn more: http://github.com/javan/whenever
# every 4.days do
# runner "AnotherModel.prune_old_records"
# end
#whenever --update-crontab bbtangcms #appname
=begin
The default job types that ship with Whenever are defined like so:
job_type :command, ":task :output"
job_type :rake, "cd :path && RAILS_ENV=:environment bundle exec rake :task --silent :output"
job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
job_type :script, "cd :path && RAILS_ENV=:environment bundle exec script/:task :output"
=end
#whenever -i config/schedule.rb -s environment=development --update-crontab bbtangcms
set :output, "#{Whenever.path}/log/whenever.log"
#set :output, File.join(Whenever.path, "log", "whenever.log")
every 3.weeks do
rake "bbtangcms:page_request:clean_older"
end
every 1.day do
#command "echo 'today whenever running ..'"
runner "puts '#{Date.today} whenever running ...'"
end
every 10.minutes do
#command "echo 'today whenever running ..'"
rake "bbtangcms:notify:new_question_notify"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron syntax too'"
end
every 1.day, :at => '2:00 am' do
runner "puts '#{DateTime.now} begin to send user_birthday_notify ...'"
rake "bbtangcms:notify:user_birthday_notify"
end
#every '0 3 27-31 * *' do
every '0 3 1 * *' do
runner "puts '#{DateTime.now} begin to send monthly_notify ...'"
#rake "bbtangcms:notify:monthly_notify"
end
every '10 2 ? * MON' do
runner "puts '#{DateTime.now} begin to send weekly_notify ...'"
#rake "bbtangcms:notify:weekly_notify"
end
every 1.day, :at => '1:00 am' do
runner "puts '#{DateTime.now} begin to send user_birthday_notify ...'"
#rake "bbtangcms:notify:user_birthday_notify"
end
every 1.day, :at => '1:30 am' do
runner "puts '#{DateTime.now} begin to send baby_birthday_notify ...'"
#rake "bbtangcms:notify:baby_birthday_notify"
end
every 1.day, :at => '0:30 am' do
rake "assets:precompile"
command "touch #{Whenever.path}/tmp/restart.txt"
end
# encoding: utf-8
#User.where("id > 1781").collect{|u| u.profile.destroy if u.profile.present?;u.destroy}
#User.where("id > 1781").collect{|u| u.profile.delete if u.profile.present?;u.authorizations=nil;u.save;u.delete}
require "logger"
def logger
logger ||= Logger.new("log/export_mmbk_user_#{Date.today.to_s}.log")
logger.level = Logger::INFO
logger
end
def yesterday_export_reporter
if "MmbkUserExportReporter".class_exists?
mmbk_user_export_reporter = MmbkUserExportReporter.last
if mmbk_user_export_reporter.present? and mmbk_user_export_reporter.created_at.to_date.eql? 1.day.ago.to_date
mmbk_user_export_reporter
end
end
end
def today_export_reporter
if "MmbkUserExportReporter".class_exists?
mmbk_user_export_reporter = MmbkUserExportReporter.last
if mmbk_user_export_reporter.present? and mmbk_user_export_reporter.created_at.to_date.eql? DateTime.now.to_date
mmbk_user_export_reporter
end
end
end
def get_last_mmbk_user_by_auth
auth_mmbk = Authorization.provider("mmbkoo").last
if auth_mmbk.present?
last_mmbkuser = MMBKUser.find auth_mmbk.uid.to_i
end
end
def is_last_auth_mmbk_yesterday?
auth_mmbk = Authorization.provider("mmbkoo").last
(auth_mmbk.created_at.to_date >= 1.day.ago.to_date) if auth_mmbk.present?
end
def find_mmbk_user
if "MMBKUser".class_exists?
logger.info "found MMBKUser model , then try to pick user we need ... "
#MMBKUser.where("email is not NULL")
#MMBKUser.select([:email, :sex, :birthday, :msn, :qq, :mobile_phone, :City])
count = rand(200..300)
auth_mmbk = Authorization.provider("mmbkoo").last
last_mmbkuser = yesterday_export_reporter.last_mmbk_user if yesterday_export_reporter.present?
last_mmbkuser ||= get_last_mmbk_user_by_auth
unless is_last_auth_mmbk_yesterday?
now_time = DateTime.now
#如果出现几天没有导入用户则,以(天数-1)乘以最小范围值
distance_day = (now_time.year - auth_mmbk.created_at.year) * now_time.yday + (now_time.month - auth_mmbk.created_at.month) * now_time.mday + (now_time.day - auth_mmbk.created_at.day)
logger.info "you last export at #{distance_day} ago, so add #{distance_day}*200 to plan_count"
count = count + (distance_day - 1)*200
end
if auth_mmbk.present?
if MMBKUser.exists? auth_mmbk.uid.to_i
last_mmbkuser = MMBKUser.find auth_mmbk.uid.to_i
logger.info "last mmbk user on bbtang.com is found email: #{last_mmbkuser.email} user_id: #{last_mmbkuser.user_id} ... "
end
if last_mmbkuser.present? and auth_mmbk.created_at.today?
#today_mmbk_users = MMBKUser.limit(count).where("email is not NULL and email != ''")
puts "already export today ...."
logger.error "#{Date.today} already export mmbk users, task will exit ...."
today_mmbk_users = []
else
logger.info "today plan to export #{count} user ..."
today_mmbk_users = MMBKUser.limit(count).where("email is not NULL and email != '' and user_id > #{last_mmbkuser.id}")
logger.info "create today's MmbkUserExportReporter record ..."
MmbkUserExportReporter.create(plan_count:count)
today_mmbk_users
end
else
logger.info "the first export ..."
today_mmbk_users = MMBKUser.limit(count).where("email is not NULL and email != ''")
end
else
logger.error "MMBKUser model not defined ..."
end
end
def export_mmbk_user
=begin
#can not work with limit option,also same as 'find_each'
#MMBKUser.limit(count).where("email is not NULL and email != ''").find_in_batches(:batch_size => 1000) do |mmbk_users|
#sleep(10) # Make sure it doesn't get too crowded in there!
mmbk_users.each do |mmbk_user|
if mmbk_user.valid?
logger.info "pick mmbk_user user_id: #{mmbk_user.user_id} email #{mmbk_user.email}, then try to export to bbtang.com ..."
export_user(mmbk_user: mmbk_user)
end
end
end
=end
real_count = 0
today_mmbk_users = find_mmbk_user
if today_mmbk_users.present?
today_mmbk_users.each do |mmbk_user|
if mmbk_user.valid? and not User.exists?(email: mmbk_user.email.strip)
real_count += 1
logger.info "pick mmbk_user user_id: #{mmbk_user.user_id} email #{mmbk_user.email}, then try to export to bbtang.com ..."
export_user(mmbk_user: mmbk_user)
end
end
if today_export_reporter.present?
logger.info "all user selected already export to bbtang.com now update mmbk_user_export_reporter."
today_export_reporter.update_attributes(pick_count: today_mmbk_users.count, real_count: real_count, last_mmbk_user_id: today_mmbk_users.last.user_id)
logger.info "today's reporter #{today_export_reporter.to_json}"
puts "today's reporter #{today_export_reporter.to_json}"
else
logger.info "today pick (#{today_mmbk_users.count}) users, really export (#{real_count}) users."
puts "today pick (#{today_mmbk_users.count}) users, really export (#{real_count}) users."
end
end
end
def generate_reset_password_token(user)
if user.present?
user.reset_password_token = user.class.reset_password_token
user.reset_password_sent_at = Time.now.utc
user.reset_password_token
end
end
def get_profile_date(params = {})
mmbk_user = params.delete(:mmbk_user)
if mmbk_user.present? and mmbk_user.class.to_s.eql? "MMBKUser"
profile = {}
[:birthday, :msn, :qq, :mobile_phone, :City, :sex].each do |col|
if mmbk_user.send(col).present?
coll_name = col
case coll_name
when :birthday
#birthday = Time.at(mmbk_user.send(coll_name))
profile.reverse_merge!(coll_name => mmbk_user.send(coll_name)) if mmbk_user.send(coll_name).present?
when :City
profile.reverse_merge!(:city => mmbk_user.send(coll_name).strip.gsub("f",""))
when :sex
profile.reverse_merge!(:gender => mmbk_user.send(coll_name))
when :mobile_phone
profile.reverse_merge!(:phone => mmbk_user.send(coll_name))
else
profile.reverse_merge!(coll_name => mmbk_user.send(coll_name).strip)
end
end
end
profile
end
end
def export_user(params = {})
mmbk_user = params.delete(:mmbk_user)
if mmbk_user.present? and mmbk_user.class.to_s.eql? "MMBKUser"
if not User.exists?(email: mmbk_user.email.strip)
logger.info "create user #{mmbk_user.email}"
password = Devise.friendly_token[0,10]
user = User.new(:email => mmbk_user.email , :password => password)
#user.password = password
generate_reset_password_token(user)
user.skip_confirmation!
ActiveRecord::Base.transaction do
#user.save
user.create_oauth_user({provider: "mmbkoo", uid: mmbk_user.id}) if User.authorization(provider: "mmbkoo", uid: "#{mmbk_user.id}").empty?
user.reset_authentication_token!
#([:email, :sex, :birthday, :msn, :qq, :mobile_phone, :City])
profile_date = get_profile_date(mmbk_user: mmbk_user)
#profile_date.merge!(nickname: "mmbkoo",user_id: user.id)
profile_date.merge!(nickname: "mmbkoo",user_id: user.id)
profile = Profile.new(profile_date)
profile.save
end
if user.valid? and user.profile.present?
if Rails.env.production?
logger.info "send mail about 'welcome_mmbkoo_user' to #{user.email} ..."
mail = MMBKUserMail.welcome_mmbkoo_user(user.id)
mail.deliver
end
end
else
logger.warn "user #{mmbk_user.email} already exists, skip ..."
end
end
end
#rake bbtangcms:notify:export_mmbk_user
namespace 'bbtangcms' do
namespace 'user' do
desc "export user in mmbkoo to bbtang"
task :export_mmbk_user => :environment do
logger.info "begin to export user in mmbkoo to bbtang ..."
export_mmbk_user
end
end
end
=begin
def generate_reset_password_token(user)
if user.present?
user.reset_password_token = user.class.reset_password_token
user.reset_password_sent_at = Time.now.utc
user.reset_password_token
end
end
emails = %w([email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected])
users=emails.collect{|email| User.find_by_email email if User.exists? email: email}.compact
users.collect{|u| generate_reset_password_token(u);u.save}
users.each do |u|
email = MMBKUserMail.welcome_mmbkoo_user(u.id)
email.deliver
end
##
users = User.where("id >=1957 and id <= 2118")
users.each do |user|
mmbk_user = MMBKUser.find_by_email user.email
if mmbk_user.present? and User.authorization(provider: "mmbkoo", uid: "#{mmbk_user.id}").empty?
user.create_oauth_user({provider: "bbmkoo", uid: mmbk_user.id})
end
end
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment