Skip to content
Snippets Groups Projects
Commit 0712cec1 authored by Martin Mareš's avatar Martin Mareš
Browse files

Jobs: Job si může objednat odeslání mailu o úspěšném dokončení

parent eabe44d4
No related branches found
No related tags found
1 merge request!136Joby naplánované na konkrétní čas
...@@ -29,6 +29,10 @@ MAIL_CONTACT = "osmo@mo.mff.cuni.cz" ...@@ -29,6 +29,10 @@ MAIL_CONTACT = "osmo@mo.mff.cuni.cz"
# Pozor, v debugovacím módu je ještě potřeba nastavit PROPAGATE_EXCEPTIONS = False. # Pozor, v debugovacím módu je ještě potřeba nastavit PROPAGATE_EXCEPTIONS = False.
# MAIL_ERRORS_TO = "osmo@mo.mff.cuni.cz" # MAIL_ERRORS_TO = "osmo@mo.mff.cuni.cz"
# Kam posíláme mailové notitifikace pro systémového uživatele, třeba dokončení jobu na správu kola
# (není-li definováno, neposílají se).
# MAIL_SYSTEM_TO = "osmo@mo.mff.cuni.cz"
# Pro testování je možné všechny odesílané maily přesměrovat na jinou adresu # Pro testování je možné všechny odesílané maily přesměrovat na jinou adresu
# MAIL_INSTEAD = "mares@kam.mff.cuni.cz" # MAIL_INSTEAD = "mares@kam.mff.cuni.cz"
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import datetime import datetime
import email.message import email.message
import email.headerregistry import email.headerregistry
from sqlalchemy.orm import joinedload
import subprocess import subprocess
import textwrap import textwrap
import token_bucket import token_bucket
...@@ -70,7 +71,15 @@ def send_email(send_to: str, full_name: str, subject: str, body: str) -> bool: ...@@ -70,7 +71,15 @@ def send_email(send_to: str, full_name: str, subject: str, body: str) -> bool:
def send_user_email(user: db.User, subject: str, body: str, add_footer: bool = False, override_email: Optional[str] = None) -> bool: def send_user_email(user: db.User, subject: str, body: str, add_footer: bool = False, override_email: Optional[str] = None) -> bool:
email = override_email or user.email if override_email:
email = override_email
elif user.user_id == 0:
email = getattr(config, 'MAIL_SYSTEM_TO', None)
if email is None:
return True
else:
email = user.email
logger.info(f'Mail: "{subject}" -> {email} (#{user.user_id})') logger.info(f'Mail: "{subject}" -> {email} (#{user.user_id})')
if add_footer: if add_footer:
...@@ -225,3 +234,33 @@ def send_internal_error_email(place: str, attrs: Mapping[str, Optional[str]], ex ...@@ -225,3 +234,33 @@ def send_internal_error_email(place: str, attrs: Mapping[str, Optional[str]], ex
logger.info('Mail: Zpráva o interní chybě') logger.info('Mail: Zpráva o interní chybě')
send_email(errors_to, "", f'Interní chyba ({place})', "".join(lines)) send_email(errors_to, "", f'Interní chyba ({place})', "".join(lines))
def send_job_done_email(job: db.Job) -> None:
to_users = {job.user}
state = db.job_state_names[job.state]
sess = db.get_session()
attrs = {
'Dávka': f'#{job.job_id}',
'Popis': job.description,
'Stav': state,
'Výsledek': job.result,
}
rnd = job.for_round
if rnd:
# Chceme informovat garanty kola
for ur in (sess.query(db.UserRole)
.filter_by(role=db.RoleType.garant)
.options(joinedload(db.UserRole.user))
.all()):
if ur.applies_to(year=rnd.year, cat=rnd.category, seq=rnd.seq):
to_users.add(ur.user)
subject = f'Dávka #{job.job_id}: {state}'
lines = [f'{key+":":10s} {val if val is not None else "-"}\n' for key, val in attrs.items()]
body = "".join(lines)
for u in to_users:
send_user_email(u, subject, body)
...@@ -171,10 +171,6 @@ class TheJob: ...@@ -171,10 +171,6 @@ class TheJob:
_handler_table[job.type](self) _handler_table[job.type](self)
if self.errors: if self.errors:
logger.info(f'{self.log_prefix} Neúspěšně dokončen ({job.result})') logger.info(f'{self.log_prefix} Neúspěšně dokončen ({job.result})')
if job.user_id == 0:
# Joby běžící na systémového uživatele produkují interní chyby
job.state = db.JobState.internal_error
else:
job.state = db.JobState.failed job.state = db.JobState.failed
job.out_json = {'errors': self.errors} job.out_json = {'errors': self.errors}
if job.result == "": if job.result == "":
...@@ -211,7 +207,7 @@ class TheJob: ...@@ -211,7 +207,7 @@ class TheJob:
+ (f', pokus {job.num_tries}' if job.num_tries > 1 else "") + (f', pokus {job.num_tries}' if job.num_tries > 1 else "")
+ (f', retry za {retry_in_min*60:.0f} s' if retry_in_min is not None else "")) + (f', retry za {retry_in_min*60:.0f} s' if retry_in_min is not None else ""))
# Maily o interních chybách posíláme mimo transakci # Maily posíláme mimo transakci
if job.state == db.JobState.internal_error: if job.state == db.JobState.internal_error:
err_attrs = { err_attrs = {
'Job': f'#{job.job_id}', 'Job': f'#{job.job_id}',
...@@ -220,6 +216,9 @@ class TheJob: ...@@ -220,6 +216,9 @@ class TheJob:
'Desc': job.description, 'Desc': job.description,
} }
mo.email.send_internal_error_email(f'Job #{job.job_id}', err_attrs, exc_info) mo.email.send_internal_error_email(f'Job #{job.job_id}', err_attrs, exc_info)
elif job.state != db.JobState.soft_error:
if job.email_when_done or (job.state != db.JobState.done and job.user_id == 0):
mo.email.send_job_done_email(job)
def process_jobs(min_priority: int = 0): def process_jobs(min_priority: int = 0):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment