Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Commit

Permalink
Return the failure from NotifyAdo as result instead of an exception (#…
Browse files Browse the repository at this point in the history
…3555)

* Return the failure from NotifyAdo as result  instead of an exception

* remove comment

* requeue when notification fails

* fix logic
  • Loading branch information
chkeita authored Oct 17, 2023
1 parent d792b3b commit 7afe06a
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/ApiService/ApiService/Functions/NotificationsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Async.Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.An
}

var result = await _context.NotificationOperations.TriggerNotification(notificationTest.Notification.Container, notificationTest.Notification,
notificationTest.Report, isLastRetryAttempt: true);
notificationTest.Report);
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(new NotificationTestResponse(result.IsOk, result.ErrorV?.ToString()));
return response;
Expand Down
16 changes: 5 additions & 11 deletions src/ApiService/ApiService/Functions/QueueFileChanges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,17 @@ public async Async.Task Run(
var storageAccount = new ResourceIdentifier(topicElement.GetString()!);

try {
// Setting isLastRetryAttempt to false will rethrow any exceptions
// With the intention that the azure functions runtime will handle requeing
// the message for us. The difference is for the poison queue, we're handling the
// requeuing ourselves because azure functions doesn't support retry policies
// for queue based functions.

var result = await FileAdded(storageAccount, fileChangeEvent, isLastRetryAttempt: false);
if (!result.IsOk && result.ErrorV.Code == ErrorCode.ADO_WORKITEM_PROCESSING_DISABLED) {
await RequeueMessage(msg, TimeSpan.FromDays(1));
var result = await FileAdded(storageAccount, fileChangeEvent);
if (!result.IsOk) {
await RequeueMessage(msg, result.ErrorV.Code == ErrorCode.ADO_WORKITEM_PROCESSING_DISABLED ? TimeSpan.FromDays(1) : null);
}
} catch (Exception e) {
_log.LogError(e, "File Added failed");
await RequeueMessage(msg);
}
}

private async Async.Task<OneFuzzResultVoid> FileAdded(ResourceIdentifier storageAccount, JsonDocument fileChangeEvent, bool isLastRetryAttempt) {
private async Async.Task<OneFuzzResultVoid> FileAdded(ResourceIdentifier storageAccount, JsonDocument fileChangeEvent) {
var data = fileChangeEvent.RootElement.GetProperty("data");
var url = data.GetProperty("url").GetString()!;
var parts = url.Split("/").Skip(3).ToList();
Expand All @@ -86,7 +80,7 @@ private async Async.Task<OneFuzzResultVoid> FileAdded(ResourceIdentifier storage

var (_, result) = await (
ApplyRetentionPolicy(storageAccount, container, path),
_notificationOperations.NewFiles(container, path, isLastRetryAttempt));
_notificationOperations.NewFiles(container, path));

return result;
}
Expand Down
1 change: 1 addition & 0 deletions src/ApiService/ApiService/OneFuzzTypes/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public enum ErrorCode {
ADO_VALIDATION_INVALID_PROJECT = 496,
INVALID_RETENTION_PERIOD = 497,
INVALID_CLI_VERSION = 498,
TRANSIENT_NOTIFICATION_FAILURE = 499,
// NB: if you update this enum, also update enums.py
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ public async Task<HttpResponseData> NewFiles([HttpTrigger(AuthorizationLevel.Ano

var container = query["container"];
var fileName = query["fileName"];
var isLastRetryAttempt = UriExtension.GetBool("isLastRetryAttempt", query, true);

_ = await _notificationOps.NewFiles(Container.Parse(container), fileName, isLastRetryAttempt);
_ = await _notificationOps.NewFiles(Container.Parse(container), fileName);
var resp = req.CreateResponse(HttpStatusCode.OK);
return resp;
}
Expand Down
12 changes: 6 additions & 6 deletions src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
namespace Microsoft.OneFuzz.Service;

public interface INotificationOperations : IOrm<Notification> {
Async.Task<OneFuzzResultVoid> NewFiles(Container container, string filename, bool isLastRetryAttempt);
Async.Task<OneFuzzResultVoid> NewFiles(Container container, string filename);
IAsyncEnumerable<Notification> GetNotifications(Container container);
IAsyncEnumerable<(Task, IEnumerable<Container>)> GetQueueTasks();
Async.Task<OneFuzzResult<Notification>> Create(Container container, NotificationTemplate config, bool replaceExisting);
Async.Task<Notification?> GetNotification(Guid notifificationId);

System.Threading.Tasks.Task<OneFuzzResultVoid> TriggerNotification(Container container,
Notification notification, IReport? reportOrRegression, bool isLastRetryAttempt = false);
Notification notification, IReport? reportOrRegression);
}

public class NotificationOperations : Orm<Notification>, INotificationOperations {
Expand All @@ -21,7 +21,7 @@ public NotificationOperations(ILogger<NotificationOperations> log, IOnefuzzConte
: base(log, context) {

}
public async Async.Task<OneFuzzResultVoid> NewFiles(Container container, string filename, bool isLastRetryAttempt) {
public async Async.Task<OneFuzzResultVoid> NewFiles(Container container, string filename) {
// We don't want to store file added events for the events container because that causes an infinite loop
if (container == WellKnownContainers.Events) {
return Result.Ok();
Expand All @@ -39,7 +39,7 @@ public async Async.Task<OneFuzzResultVoid> NewFiles(Container container, string
}

done.Add(notification.Config);
var notificationResult = await TriggerNotification(container, notification, reportOrRegression, isLastRetryAttempt);
var notificationResult = await TriggerNotification(container, notification, reportOrRegression);
if (result.IsOk && !notificationResult.IsOk) {
result = notificationResult;
}
Expand Down Expand Up @@ -86,15 +86,15 @@ public async Async.Task<OneFuzzResultVoid> NewFiles(Container container, string
}

public async System.Threading.Tasks.Task<OneFuzzResultVoid> TriggerNotification(Container container,
Notification notification, IReport? reportOrRegression, bool isLastRetryAttempt = false) {
Notification notification, IReport? reportOrRegression) {
switch (notification.Config) {
case TeamsTemplate teamsTemplate:
await _context.Teams.NotifyTeams(teamsTemplate, container, reportOrRegression!,
notification.NotificationId);
break;
case AdoTemplate adoTemplate when reportOrRegression is not null:
if (await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableWorkItemCreation)) {
return await _context.Ado.NotifyAdo(adoTemplate, container, reportOrRegression, isLastRetryAttempt,
return await _context.Ado.NotifyAdo(adoTemplate, container, reportOrRegression,
notification.NotificationId);
} else {
return OneFuzzResultVoid.Error(ErrorCode.ADO_WORKITEM_PROCESSING_DISABLED, "Work item processing is currently disabled");
Expand Down
21 changes: 14 additions & 7 deletions src/ApiService/ApiService/onefuzzlib/notifications/Ado.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Microsoft.OneFuzz.Service;

public interface IAdo {
public Async.Task<OneFuzzResultVoid> NotifyAdo(AdoTemplate config, Container container, IReport reportable, bool isLastRetryAttempt, Guid notificationId);
public Async.Task<OneFuzzResultVoid> NotifyAdo(AdoTemplate config, Container container, IReport reportable, Guid notificationId);
}

public class Ado : NotificationsBase, IAdo {
Expand All @@ -24,7 +24,7 @@ public class Ado : NotificationsBase, IAdo {
public Ado(ILogger<Ado> logTracer, IOnefuzzContext context) : base(logTracer, context) {
}

public async Async.Task<OneFuzzResultVoid> NotifyAdo(AdoTemplate config, Container container, IReport reportable, bool isLastRetryAttempt, Guid notificationId) {
public async Async.Task<OneFuzzResultVoid> NotifyAdo(AdoTemplate config, Container container, IReport reportable, Guid notificationId) {
var filename = reportable.FileName();
Report? report;
if (reportable is RegressionReport regressionReport) {
Expand Down Expand Up @@ -57,22 +57,29 @@ public async Async.Task<OneFuzzResultVoid> NotifyAdo(AdoTemplate config, Contain
_logTracer.LogEvent(adoEventType);

try {
await ProcessNotification(_context, container, filename, config, report, _logTracer, notificationInfo, isRegression: reportable is RegressionReport);
await ProcessNotification(_context, container, filename, config, report, _logTracer, notificationInfo,
isRegression: reportable is RegressionReport);
} catch (Exception e)
when (e is VssUnauthorizedException || e is VssAuthenticationException || e is VssServiceException) {
when (e is VssUnauthorizedException || e is VssAuthenticationException || e is VssServiceException) {
if (config.AdoFields.TryGetValue("System.AssignedTo", out var assignedTo)) {
_logTracer.AddTag("assigned_to", assignedTo);
}

if (!isLastRetryAttempt && IsTransient(e)) {
_logTracer.LogError("transient ADO notification failure {JobId} {TaskId} {Container} {Filename}", report.JobId, report.TaskId, container, filename);
throw;
if (IsTransient(e)) {
_logTracer.LogError("transient ADO notification failure {JobId} {TaskId} {Container} {Filename}",
report.JobId, report.TaskId, container, filename);

return OneFuzzResultVoid.Error(ErrorCode.TRANSIENT_NOTIFICATION_FAILURE,
$"Failed to process ado notification : exception: {e}");
} else {
_logTracer.LogError(e, "Failed to process ado notification");
await LogFailedNotification(report, e, notificationId);
return OneFuzzResultVoid.Error(ErrorCode.NOTIFICATION_FAILURE,
$"Failed to process ado notification : exception: {e}");
}
} catch (Exception e) {
return OneFuzzResultVoid.Error(ErrorCode.NOTIFICATION_FAILURE,
$"Failed to process ado notification : exception: {e}");
}
return OneFuzzResultVoid.Ok;
}
Expand Down
1 change: 1 addition & 0 deletions src/pytypes/onefuzztypes/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ class ErrorCode(Enum):
ADO_VALIDATION_INVALID_PROJECT = 496
INVALID_RETENTION_PERIOD = 497
INVALID_CLI_VERSION = 498
TRANSIENT_NOTIFICATION_FAILURE = 499
# NB: if you update this enum, also update Enums.cs


Expand Down

0 comments on commit 7afe06a

Please sign in to comment.