-
Notifications
You must be signed in to change notification settings - Fork 463
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1.0.8: EdgeAgent: Get status of logs upload request (#1392)
* Cherry pick 4e8e005 * Update TwinConfigSourceModule.cs
- Loading branch information
1 parent
49d8655
commit e7876eb
Showing
12 changed files
with
560 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/requests/TaskStatusRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Requests | ||
{ | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
|
||
public class TaskStatusRequest | ||
{ | ||
public TaskStatusRequest(string schemaVersion, string correlationId) | ||
{ | ||
this.SchemaVersion = Preconditions.CheckNonWhiteSpace(schemaVersion, nameof(schemaVersion)); | ||
this.CorrelationId = Preconditions.CheckNonWhiteSpace(correlationId, nameof(correlationId)); | ||
} | ||
|
||
public string SchemaVersion { get; } | ||
|
||
public string CorrelationId { get; } | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/requests/TaskStatusRequestHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Requests | ||
{ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Edge.Storage; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Extensions.Logging; | ||
|
||
public class TaskStatusRequestHandler : RequestHandlerBase<TaskStatusRequest, TaskStatusResponse> | ||
{ | ||
static readonly Version ExpectedSchemaVersion = new Version("1.0"); | ||
|
||
public override string RequestName => "GetTaskStatus"; | ||
|
||
protected override Task<Option<TaskStatusResponse>> HandleRequestInternal(Option<TaskStatusRequest> payloadOption, CancellationToken cancellationToken) | ||
{ | ||
TaskStatusRequest payload = payloadOption.Expect(() => new ArgumentException("Request payload not found")); | ||
if (ExpectedSchemaVersion.CompareMajorVersion(payload.SchemaVersion, "logs upload request schema") != 0) | ||
{ | ||
Events.MismatchedMinorVersions(payload.SchemaVersion, ExpectedSchemaVersion); | ||
} | ||
|
||
BackgroundTaskStatus backgroundTaskStatus = BackgroundTask.GetStatus(payload.CorrelationId); | ||
Events.ProcessingRequest(payload, backgroundTaskStatus); | ||
return Task.FromResult(Option.Some(TaskStatusResponse.Create(payload.CorrelationId, backgroundTaskStatus))); | ||
} | ||
|
||
static class Events | ||
{ | ||
const int IdStart = AgentEventIds.TaskStatusRequestHandler; | ||
static readonly ILogger Log = Logger.Factory.CreateLogger<TaskStatusRequestHandler>(); | ||
|
||
enum EventIds | ||
{ | ||
MismatchedMinorVersions = IdStart, | ||
ProcessingRequest | ||
} | ||
|
||
public static void MismatchedMinorVersions(string payloadSchemaVersion, Version expectedSchemaVersion) | ||
{ | ||
Log.LogWarning((int)EventIds.MismatchedMinorVersions, $"Logs upload request schema version {payloadSchemaVersion} does not match expected schema version {expectedSchemaVersion}. Some settings may not be supported."); | ||
} | ||
|
||
public static void ProcessingRequest(TaskStatusRequest payload, BackgroundTaskStatus backgroundTaskStatus) | ||
{ | ||
Log.LogInformation((int)EventIds.ProcessingRequest, $"Handling status request for task {payload.CorrelationId} - {backgroundTaskStatus.ToJson()}"); | ||
} | ||
} | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/requests/TaskStatusResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Requests | ||
{ | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Converters; | ||
|
||
public class TaskStatusResponse | ||
{ | ||
public static TaskStatusResponse Create(string correlationId, BackgroundTaskStatus backgroundTaskStatus) | ||
{ | ||
Preconditions.CheckNotNull(backgroundTaskStatus, nameof(backgroundTaskStatus)); | ||
string message = string.Empty; | ||
if (backgroundTaskStatus.Status == BackgroundTaskRunStatus.Failed) | ||
{ | ||
message = backgroundTaskStatus.Exception.Match( | ||
e => $"Task {backgroundTaskStatus.Operation} failed because of error {e.Message}", | ||
() => $"Task {backgroundTaskStatus.Operation} failed with no error"); | ||
} | ||
|
||
return new TaskStatusResponse(correlationId, backgroundTaskStatus.Status, message); | ||
} | ||
|
||
public TaskStatusResponse(string correlationId, BackgroundTaskRunStatus status, string message) | ||
{ | ||
this.CorrelationId = Preconditions.CheckNonWhiteSpace(correlationId, nameof(correlationId)); | ||
this.Status = status; | ||
this.Message = Preconditions.CheckNotNull(message, nameof(message)); | ||
} | ||
|
||
[JsonProperty("status")] | ||
[JsonConverter(typeof(StringEnumConverter))] | ||
public BackgroundTaskRunStatus Status { get; } | ||
|
||
[JsonProperty("message")] | ||
public string Message { get; } | ||
|
||
[JsonProperty("correlationId")] | ||
public string CorrelationId { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
...est/Microsoft.Azure.Devices.Edge.Agent.Core.Test/requests/TaskStatusRequestHandlerTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Agent.Core.Test.Requests | ||
{ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Devices.Edge.Agent.Core.Logs; | ||
using Microsoft.Azure.Devices.Edge.Agent.Core.Requests; | ||
using Microsoft.Azure.Devices.Edge.Storage; | ||
using Microsoft.Azure.Devices.Edge.Util; | ||
using Microsoft.Azure.Devices.Edge.Util.Test.Common; | ||
using Moq; | ||
using Xunit; | ||
|
||
[Unit] | ||
public class TaskStatusRequestHandlerTest | ||
{ | ||
[Fact] | ||
public async Task SmokeTest() | ||
{ | ||
async Task TestTask() | ||
{ | ||
await Task.Delay(TimeSpan.FromSeconds(3)); | ||
} | ||
|
||
(string correlationId, BackgroundTaskStatus backgroundTaskStatus) = BackgroundTask.Run(TestTask, "test", CancellationToken.None); | ||
|
||
string payload = @"{ | ||
""schemaVersion"": ""1.0"", | ||
""correlationId"": ""<correlationId>"" | ||
}".Replace("<correlationId>", correlationId); | ||
var taskStatusRequestHandler = new TaskStatusRequestHandler(); | ||
Option<string> response = await taskStatusRequestHandler.HandleRequest(Option.Some(payload), CancellationToken.None); | ||
|
||
Assert.True(response.HasValue); | ||
TaskStatusResponse taskStatusResponse = response.OrDefault().FromJson<TaskStatusResponse>(); | ||
Assert.NotNull(taskStatusResponse); | ||
Assert.Equal(taskStatusResponse.CorrelationId, correlationId); | ||
} | ||
|
||
[Fact] | ||
public async Task InvalidInputsTest() | ||
{ | ||
var taskStatusRequestHandler = new TaskStatusRequestHandler(); | ||
await Assert.ThrowsAsync<ArgumentException>(() => taskStatusRequestHandler.HandleRequest(Option.None<string>(), CancellationToken.None)); | ||
|
||
string payload1 = @"{ | ||
""schemaVersion"": ""2.0"", | ||
""correlationId"": ""1234"" | ||
}"; | ||
await Assert.ThrowsAsync<InvalidSchemaVersionException>(() => taskStatusRequestHandler.HandleRequest(Option.Some(payload1), CancellationToken.None)); | ||
|
||
string payload2 = @"{ | ||
""schemaVersion"": ""1.0"", | ||
""correlationId"": """" | ||
}"; | ||
await Assert.ThrowsAsync<ArgumentException>(() => taskStatusRequestHandler.HandleRequest(Option.Some(payload2), CancellationToken.None)); | ||
} | ||
} | ||
} |
71 changes: 71 additions & 0 deletions
71
edge-util/src/Microsoft.Azure.Devices.Edge.Util/BackgroundTask.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
namespace Microsoft.Azure.Devices.Edge.Util | ||
{ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
public static class BackgroundTask | ||
{ | ||
static readonly ConcurrentDictionary<string, BackgroundTaskStatus> TaskStatuses = new ConcurrentDictionary<string, BackgroundTaskStatus>(); | ||
|
||
public static (string correlationId, BackgroundTaskStatus backgroundTaskStatus) Run(Func<Task> task, string operation, CancellationToken cancellationToken) | ||
{ | ||
BackgroundTaskStatus backgroundTaskStatus = new BackgroundTaskStatus(BackgroundTaskRunStatus.Running, operation); | ||
string correlationId = AddNewTask(backgroundTaskStatus); | ||
Task.Run( | ||
() => task().ContinueWith( | ||
t => | ||
{ | ||
BackgroundTaskStatus GetNewStatus() | ||
{ | ||
switch (t.Status) | ||
{ | ||
case TaskStatus.Faulted: | ||
Exception exception = t.Exception is AggregateException aggregateException | ||
? aggregateException.InnerException | ||
: t.Exception; | ||
return new BackgroundTaskStatus(BackgroundTaskRunStatus.Failed, operation, Option.Some(exception)); | ||
|
||
case TaskStatus.Canceled: | ||
return new BackgroundTaskStatus(BackgroundTaskRunStatus.Cancelled, operation); | ||
|
||
case TaskStatus.RanToCompletion: | ||
return new BackgroundTaskStatus(BackgroundTaskRunStatus.Completed, operation); | ||
|
||
default: | ||
return new BackgroundTaskStatus(BackgroundTaskRunStatus.Unknown, operation); | ||
} | ||
} | ||
|
||
BackgroundTaskStatus newStatus = GetNewStatus(); | ||
if (!TaskStatuses.TryUpdate(correlationId, newStatus, backgroundTaskStatus)) | ||
{ | ||
// This should never happen. | ||
BackgroundTaskStatus currentTask = GetStatus(correlationId); | ||
throw new InvalidOperationException($"Failed to update background task status to - {newStatus}. Current task = {currentTask}"); | ||
} | ||
}, cancellationToken), | ||
cancellationToken); | ||
return (correlationId, backgroundTaskStatus); | ||
} | ||
|
||
static string AddNewTask(BackgroundTaskStatus backgroundTaskStatus) | ||
{ | ||
while (true) | ||
{ | ||
var correlationId = Guid.NewGuid().ToString(); | ||
if (TaskStatuses.TryAdd(correlationId, backgroundTaskStatus)) | ||
{ | ||
return correlationId; | ||
} | ||
} | ||
} | ||
|
||
public static BackgroundTaskStatus GetStatus(string correlationId) => | ||
TaskStatuses.TryGetValue(correlationId, out BackgroundTaskStatus status) | ||
? status | ||
: new BackgroundTaskStatus(BackgroundTaskRunStatus.Unknown, string.Empty); | ||
} | ||
} |
Oops, something went wrong.