jam-cloud/ruby/lib/jam_ruby/models/email_batch_scheduled_sessi...

150 lines
4.6 KiB
Ruby

module JamRuby
class EmailBatchScheduledSessions < EmailBatchPeriodic
BATCH_SIZE = 500
SINCE_DAYS = 2
MIN_HOURS_START = 2
TMP_SESS = 'tmp_candidate_sessions'
TMP_RECIP = 'tmp_candidate_recipients'
TMP_MATCH = 'tmp_matches'
def self.subject
"New sessions have been scheduled that may be a good match for you!"
end
# inserts eligible sessions to temp table
def _collect_eligible_sessions
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_SESS}")
sql =<<SQL
SELECT
msess.id AS session_id,
msess.user_id AS creator_id,
users.last_jam_locidispid AS creator_score_idx,
rs.instrument_id
INTO TEMP TABLE #{TMP_SESS}
FROM music_sessions msess
INNER JOIN users ON users.id = msess.user_id
INNER JOIN rsvp_slots AS rs ON rs.music_session_id = msess.id
LEFT JOIN rsvp_requests_rsvp_slots AS rrrs ON rrrs.rsvp_slot_id = rs.id
WHERE
musician_access = 't' AND
approval_required = 'f' AND
msess.created_at > '#{time_since_last_batch(SINCE_DAYS)}' AND
msess.created_at < '#{self.created_at}' AND
scheduled_start >= '#{Time.now() + MIN_HOURS_START.hours}' AND
(rrrs.rsvp_slot_id IS NULL OR rrrs.chosen != 't')
SQL
ActiveRecord::Base.connection.execute(sql)
end
def _collect_eligible_recipients
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_RECIP}")
# load eligible recipients into tmp table
sql =<<SQL
SELECT
users.id AS receiver_id,
users.last_jam_locidispid AS receiver_score_idx
INTO TEMP TABLE #{TMP_RECIP}
FROM users
INNER JOIN musicians_instruments AS mi ON mi.user_id = users.id
INNER JOIN #{TMP_SESS} ON #{TMP_SESS}.instrument_id = mi.instrument_id
WHERE
users.musician = 't' AND
users.subscribe_email = 't'
SQL
ActiveRecord::Base.connection.execute(sql)
end
def _collect_scored_recipients
ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_MATCH}")
sql =<<SQL
SELECT
DISTINCT #{TMP_RECIP}.receiver_id,
#{TMP_SESS}.session_id,
scores.score AS latency
INTO TEMP TABLE #{TMP_MATCH}
FROM scores
INNER JOIN #{TMP_SESS} ON #{TMP_SESS}.creator_score_idx = scores.alocidispid
INNER JOIN #{TMP_RECIP} ON #{TMP_RECIP}.receiver_score_idx = scores.blocidispid
WHERE
scores.score < #{Score::MAX_YELLOW_LATENCY} AND
#{TMP_RECIP}.receiver_id != #{TMP_SESS}.creator_id
GROUP BY
#{TMP_RECIP}.receiver_id,
#{TMP_SESS}.session_id,
latency
SQL
ActiveRecord::Base.connection.execute(sql)
end
# select recipients whose score is below minimum threshold
def _select_scored_recipients(offset=0)
if 0 > offset
sql = "SELECT COUNT(DISTINCT receiver_id) AS num FROM #{TMP_MATCH}"
rr = ActiveRecord::Base.connection.execute(sql)
return 0 < rr.count ? rr[0]['num'].to_i : 0
else
sql =<<SQL
SELECT DISTINCT receiver_id
FROM #{TMP_MATCH}
ORDER BY receiver_id ASC
LIMIT #{@per_page}
OFFSET #{offset}
SQL
return ActiveRecord::Base.connection.execute(sql)
end
end
def fetch_recipients(per_page=500)
objs = []
# load eligible sessions into tmp table
self._collect_eligible_sessions
# load eligible mail recipients into tmp table
self._collect_eligible_recipients
# load mail recipients with minimum score into tmp table
self._collect_scored_recipients
@per_page = per_page
num_recip = _select_scored_recipients(-1)
loops = (num_recip / @per_page) + (num_recip % @per_page) - 1
0.upto(loops) do |nn|
offset = nn * @per_page
# now just get the sessions/latency for each distinct mail recipient
_select_scored_recipients(offset).each do |result|
receiver = User.find_by_id(result['receiver_id'])
sessions = MusicSession.select("music_sessions.*, #{TMP_MATCH}.latency")
.joins("INNER JOIN #{TMP_MATCH} ON #{TMP_MATCH}.session_id = music_sessions.id")
.where(["#{TMP_MATCH}.receiver_id = ?", receiver.id])
.includes([:genre, :creator])
block_given? ? yield(receiver, sessions) : objs << [receiver, sessions]
end
end
objs
end
def deliver_batch_sets!
self.opt_in_count = 0
self.fetch_recipients do |receiver, sessions_and_latency|
self.opt_in_count += 1
bset = EmailBatchSet.scheduled_session_set(self, receiver, sessions_and_latency)
UserMailer.scheduled_session_daily(receiver, sessions_and_latency).deliver
end
self.sent_count = self.opt_in_count
self.save
self.did_batch_run!
end
def self.send_daily_session_batch
oo = self.create
oo.deliver_batch
oo
end
end
end