Skip to content

Commit

Permalink
Merge pull request #389 from silinternational/feature/IDP-1266-part-4…
Browse files Browse the repository at this point in the history
…-send-ext-groups-sync-errors-email-more-often

[IDP-1266, part 4:] Send external-groups sync-errors email more often
  • Loading branch information
forevermatt authored Nov 18, 2024
2 parents 5fca038 + bb6ec9d commit 03493cf
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 5 deletions.
25 changes: 20 additions & 5 deletions application/common/components/Emailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -443,26 +443,38 @@ public function hasUserReceivedMessageRecently(int $userId, string $messageType)
}

/**
* Whether the non-user address has already been sent this type of email in the last X days
* Whether the non-user address has already been sent this type of email
* recently (where "recent" is defined by the given timeframe).
*
* @param string $emailAddress
* @param string $messageType
* @param ?string $timeframe (Optional:) What qualifies as recent. If not
* specified, this will default to `emailRepeatDelayDays` days.
* Example: '11 hours'
* @return bool
*/
public function hasNonUserReceivedMessageRecently(string $emailAddress, string $messageType): bool
{
public function hasNonUserReceivedMessageRecently(
string $emailAddress,
string $messageType,
?string $timeframe = null
): bool {
$latestEmail = EmailLog::find()->where([
'message_type' => $messageType,
'non_user_address' => $emailAddress,
'user_id' => null,
])->orderBy(
'sent_utc DESC'
)->one();

if (empty($latestEmail)) {
return false;
}

return MySqlDateTime::dateIsRecent($latestEmail->sent_utc, $this->emailRepeatDelayDays);
if (empty($timeframe)) {
$timeframe = $this->emailRepeatDelayDays . ' days';
}

return MySqlDateTime::dateTimeIsRecent($latestEmail->sent_utc, $timeframe);
}

/**
Expand Down Expand Up @@ -499,7 +511,10 @@ public function shouldSendExternalGroupsSyncErrorsEmailTo(string $emailAddress):

$haveSentEmailRecently = $this->hasNonUserReceivedMessageRecently(
$emailAddress,
EmailLog::MESSAGE_TYPE_EXT_GROUP_SYNC_ERRORS
EmailLog::MESSAGE_TYPE_EXT_GROUP_SYNC_ERRORS,
'11 hours' /* Use slightly less than the desired interval, to avoid
* inconsistent results due to being a few seconds before
* or after the cutoff. */
);

return !$haveSentEmailRecently;
Expand Down
16 changes: 16 additions & 0 deletions application/common/helpers/MySqlDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ public static function dateIsRecent(string $dbDate, int $recentDays)
return strtotime($dbDate) >= strtotime($recentDate);
}

/**
* Whether the given date-and-time qualifies as "recent" according to the
* given timeframe.
*
* @param string $dbDate formated datetime from database
* @param string $timeframe -- Example: '11 hours'
* @return bool
*/
public static function dateTimeIsRecent(string $dbDate, string $timeframe)
{
$dtInterval = '-' . $timeframe;
$recentDateTime = self::relativeTime($dtInterval);

return strtotime($dbDate) >= strtotime($recentDateTime);
}

/**
* Compare a date or datetime in MySQL format (yyyy-mm-dd or yyyy-mm-dd hh:mm::ss)
* to an epoch time as returned from time().
Expand Down
33 changes: 33 additions & 0 deletions application/features/bootstrap/EmailContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -1367,4 +1367,37 @@ public function iTryToLogAnEmailAsSentToNeitherAUserNorANonUserAddress()
]);
$this->tempEmailLog->save();
}

/**
* @Given I sent an external-groups sync-error email :numberOfHours hour(s) ago
*/
public function iSentAnExternalGroupsSyncErrorEmailHourAgo($numberOfHours)
{
$this->iSendAnExternalGroupsSyncErrorEmail();
$relativeTimeString = sprintf(
'-%u hours',
$numberOfHours
);

$emailLogs = EmailLog::findAll([
'message_type' => EmailLog::MESSAGE_TYPE_EXT_GROUP_SYNC_ERRORS,
]);

Assert::notEmpty(
$emailLogs,
'No external-group sync-error email logs found to set the sent_at value for'
);

foreach ($emailLogs as $emailLog) {
$emailLog->sent_utc = MysqlDateTime::relativeTime($relativeTimeString);
Assert::true(
$emailLog->save(true, ['sent_utc']),
sprintf(
'Failed to update email log record to be for %s: %s',
$relativeTimeString,
$emailLog->getFirstError('sent_utc')
)
);
}
}
}
12 changes: 12 additions & 0 deletions application/features/email.feature
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,18 @@ Feature: Email
When I send an external-groups sync-error email again
Then the external-groups sync-error email has been sent 1 time

Scenario Outline: Sending external-group sync-error emails up to every 12 hours
Given the database has been purged
And I sent an external-groups sync-error email <hoursAgo>
When I send an external-groups sync-error email again
Then the external-groups sync-error email has been sent <timesSent>

Examples:
| hoursAgo | timesSent |
| 1 hour ago | 1 time |
| 10 hours ago | 1 time |
| 12 hours ago | 2 times |

Scenario: Ensure no EmailLog is to both a User and a non-user address
Given a user already exists
When I try to log an email as sent to that User and to a non-user address
Expand Down

0 comments on commit 03493cf

Please sign in to comment.