Skip to content

[2025June]Email retry logic #3761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open

Conversation

gggdttt
Copy link
Contributor

@gggdttt gggdttt commented May 27, 2025

Summary

Work Item(s)

Fixes AB#576349

Copy link

Issue #576349 is not valid. Please make sure you link an issue that exists, is open and is approved.

@github-actions github-actions bot added this to the Version 27.0 milestone May 27, 2025
@gggdttt gggdttt requested a review from a team as a code owner June 3, 2025 22:07
@mazhelez mazhelez removed the request for review from a team June 4, 2025 21:58
UpdateOutboxStatus(EmailOutbox, EmailOutbox.Status::Failed);

// if email is not rescheduled, it means it has exceeded the retry limit, stop retrying
if ClientTypeManagement.GetCurrentClientType() = CLIENTTYPE::Background then begin
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@darjoo Can I assume all the emails sent in background belong to the CLIENTTYPE::Background ?

RetryTime: DateTime;
RandomDelay: Integer;
begin
FeatureTelemetry.LogError('', EmailFeatureNameLbl, 'Retry failed email', StrSubstNo(FailedToFindEmailMessageMsg, EmailOutbox."Message Id"), '', Dimensions);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember Invoke-Miapp helps to auto fill the Log tag... But I tried it and it doesn't work. @darjoo do you know if we change anything in Invoke-Miapp? Is it a bug? :)

FeatureTelemetry.LogError('', EmailFeatureNameLbl, 'Retry failed email', StrSubstNo(FailedToFindEmailMessageMsg, EmailOutbox."Message Id"), '', Dimensions);
EmailOutbox.Validate("Retry No.", EmailOutbox."Retry No." + 1);

if EmailOutbox."Retry No." > 10 then begin
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I set maximum retry to 10 times Not sure if it is too much

EmailOutbox.Status := EmailOutbox.Status::Queued;
EmailOutbox.Modify();

RandomDelay := Random(5000); // Jitter - Random delay between 0 and 5000 milliseconds (5 seconds)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jitter is 5 seconds. Now the concurrency is 10 at most. Do you think the jitter is too short?

EmailOutbox.Modify();

RandomDelay := Random(5000); // Jitter - Random delay between 0 and 5000 milliseconds (5 seconds)
RetryTime := CurrentDateTime() + EmailOutbox."Retry No." * 1.5 * 60000 + RandomDelay; // Base interval: 1.5 minutes, plus a random delay of up to 5 seconds
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should use 90000 directly....

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a page for this retry table? When user clicks on the retry No. , user can jump to the corresponding retry page with the filter on message Id.

trigger OnValidate()
begin
if "Concurrency Limit" > 10 then
Error('The maximum value for Concurrency Limit is 10. Please set a lower value.');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the error message to a label then it can be translated

if EmailRateLimit.Get(AccountId, Connector) then
exit(EmailRateLimit."Concurrency Limit");

EmailRateLimit."Account Id" := AccountId;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to validate

Description = 'The field is marked as internal in order to prevent modifying it from code.';
}

field(10; "Date Queued"; DateTime)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks we don't need the DateQueued

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DateSending and DateFailed should be enough

var
EmailOutbox: Record "Email Outbox";
begin
EmailOutbox.SetRange(Status, EmailOutbox.Status::Processing);
Copy link
Contributor Author

@gggdttt gggdttt Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the code, EmailOutbox.Status::Processing should represent the emails are being sent.

Just for confirmation, EmailOutbox.Status::Queued should not be included here because queued email has not been processed.

@gggdttt gggdttt changed the title [Draft] Email retry logic [2025June]Email retry logic Jun 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant