@@ -118,10 +118,20 @@ class InviteTuple(NamedTuple):
118118
119119
120120def send_gspc_invite_emails (invites : list [InviteTuple ], app_settings : Settings ) -> None :
121+ """Background task designed to do a bulk send of GSPC invite emails"""
122+ # Start timer to track how long the job takes
123+ start_time = time .time ()
121124 logging .info (f"Starting gspc invite job, number of invites:{ len (invites )} " )
125+
122126 email_messages = [create_email_message (invite , app_settings ) for invite in invites ]
123- send_emails_in_batches (email_messages = email_messages , batch_size = 10 , app_settings = app_settings )
124- logging .info ("Finished gspc invite job" )
127+ send_emails_in_batches (email_messages = email_messages , batch_size = 25 , app_settings = app_settings )
128+
129+ end_time = time .time ()
130+ execution_time = end_time - start_time
131+ # Format time as minutes and seconds for better readability
132+ minutes = int (execution_time // 60 )
133+ seconds = int (execution_time % 60 )
134+ logging .info (f"Finished gspc invite job. Total execution time: { minutes } minutes and { seconds } seconds for { len (invites )} emails" )
125135
126136
127137def create_email_message (invite : InviteTuple , app_settings : Settings ) -> EmailMessage :
@@ -149,31 +159,29 @@ def batch_iterator(items: List, batch_size: int) -> Iterator:
149159
150160
151161def send_emails_in_batches (email_messages : List [EmailMessage ], batch_size : int , app_settings : Settings ) -> None :
162+ """Chunks the list into batches and attempts to send each back of emails."""
152163 for batch in batch_iterator (email_messages , batch_size ):
153164 max_retries = 3
165+ # Attempt to trigger email batch, retries on failure
154166 for attempt in range (max_retries ):
155167 try :
156168 with SMTP (app_settings .SMTP_SERVER , port = app_settings .SMTP_PORT , timeout = 30 ) as smtp :
157169 smtp .starttls ()
158170 if app_settings .SMTP_USER and app_settings .SMTP_PASSWORD :
159171 smtp .login (user = app_settings .SMTP_USER , password = app_settings .SMTP_PASSWORD )
160172
161- logging .info (f"Sending emails with account: { str (app_settings .SMTP_PASSWORD )} " )
162-
163173 # Send messages in current batch
164174 for message in batch :
165- try :
166- smtp .send_message (message )
167- except Exception as e :
168- # Log the error but continue with remaining messages
169- logging .error (f"Failed to send email to { message ['To' ]} : { str (e )} " )
175+ smtp .send_message (message )
170176 smtp .quit ()
171-
177+ break # Exit retry loop if successful
172178 except Exception as e :
173179 if attempt < max_retries - 1 :
174- # Wait with exponential backoff: 2, 4, 8 seconds...
175- sleep_time = 2 ** attempt
180+ # Wait with backoff: 1, 2, 4 seconds...
181+ sleep_time = 1 * ( attempt + 1 )
176182 time .sleep (sleep_time )
183+ # Log the error after all retries failed
177184 else :
178- # Log the error after all retries failed
179- logging .error (f"Failed to send batch after { max_retries } attempts: { str (e )} " )
185+ # Extract all email addresses from the batch and join them with commas
186+ addresses_list = ", " .join ([message ['To' ] for message in batch ])
187+ logging .error (f"Failed to send batch after { max_retries } attempts: { str (e )} . Addresses: { addresses_list } " )
0 commit comments