Skip to content

Commit

Permalink
.net 9.0 / photo page (part 1) / handle exception review / storage fu…
Browse files Browse the repository at this point in the history
…nction review / nuget updates
  • Loading branch information
Dhiogo Acioli committed Nov 24, 2024
1 parent 6d61191 commit 132e1d7
Show file tree
Hide file tree
Showing 42 changed files with 684 additions and 412 deletions.
38 changes: 38 additions & 0 deletions MM.API/Core/ComputerVisionHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using Microsoft.Extensions.Configuration;

namespace MM.API.Core
{
public class ComputerVisionHelper(IConfiguration configuration)
{
public IConfiguration Configuration { get; } = configuration;

/// <summary>
/// still using version 3.2 (old version)
///
/// https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/quickstarts-sdk/image-analysis-client-library?pivots=programming-language-csharp&tabs=windows%2Cvisual-studio
///
/// update when adult content is available
///
/// https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/overview-image-analysis?tabs=4-0
/// </summary>
/// <param name="url"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<ImageAnalysis> AnalyzeImage(Stream stream, CancellationToken cancellationToken)
{
var endpoint = Configuration.GetValue<string>("CognitiveEndpoint");
var key = Configuration.GetValue<string>("CognitiveKey");

var client = new ComputerVisionClient(new ApiKeyServiceClientCredentials(key)) { Endpoint = endpoint };

var features = new List<VisualFeatureTypes?>()
{
VisualFeatureTypes.Adult, VisualFeatureTypes.Faces
};

return await client.AnalyzeImageInStreamAsync(stream, visualFeatures: features, cancellationToken: cancellationToken);
}
}
}
3 changes: 2 additions & 1 deletion MM.API/Core/CosmosLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
Name = _name,
State = formatter(state, exception),
Message = exception?.Message,
StackTrace = exception?.StackTrace
StackTrace = exception?.StackTrace,
Ttl = (int)ttlCache.three_months
});
}
}
Expand Down
294 changes: 227 additions & 67 deletions MM.API/Core/FaceHelper.cs

Large diffs are not rendered by default.

21 changes: 1 addition & 20 deletions MM.API/Core/IsolatedFunctionHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Collections.Specialized;
Expand Down Expand Up @@ -87,24 +86,6 @@ private static string BuildState(this HttpRequestData req)

return string.Join("", valueCollection.AllKeys.Select((key) => $"{key?.ToLowerInvariant()}={{{key?.ToLowerInvariant()}}}|"));
}

public static string? BuildException(this Exception ex)
{
if (ex is CosmosException cex)
{
//TODO: review this

//var result = JsonSerializer.Deserialize<CosmosExceptionStructure>("{" + cex.ResponseBody.Replace("Errors", "\"Errors\"") + "}", options: null);

//return result?.Message?.Errors.FirstOrDefault();

return cex.Message;
}
else
{
return ex.Message;
}
}
}

public class CosmosExceptionStructure
Expand Down
10 changes: 10 additions & 0 deletions MM.API/Core/Middleware/ExceptionHandlingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next
{
await context.SetHttpResponseStatusCode(HttpStatusCode.RequestTimeout, "Request Timeout!");
}
catch (CosmosException)
{
//var result = JsonSerializer.Deserialize<CosmosExceptionStructure>("{" + cex.ResponseBody.Replace("Errors", "\"Errors\"") + "}", options: null);
//return result?.Message?.Errors.FirstOrDefault();
await context.SetHttpResponseStatusCode(HttpStatusCode.InternalServerError, "Invocation failed!");
}
catch (NotificationException ex)
{
await context.SetHttpResponseStatusCode(HttpStatusCode.BadRequest, ex.Message);
}
catch (Exception ex)
{
_logger.LogError(ex, "ExceptionHandlingMiddleware");
Expand Down
15 changes: 6 additions & 9 deletions MM.API/Core/Middleware/FunctionContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,31 @@ namespace MM.API.Core.Middleware
{
public static class FunctionContextExtensions
{
public static async Task SetHttpResponseStatusCode(this FunctionContext context, HttpStatusCode statusCode, string? status)
public static async Task SetHttpResponseStatusCode(this FunctionContext context, HttpStatusCode statusCode, string message)
{
var req = await context.GetHttpRequestDataAsync();

var newHttpResponse = req!.CreateResponse(statusCode);
var response = req!.CreateResponse(statusCode);

// You need to explicitly pass the status code in WriteAsJsonAsync method.
// https://github.com/Azure/azure-functions-dotnet-worker/issues/776
await newHttpResponse.WriteAsJsonAsync(new { Status = status }, newHttpResponse.StatusCode);
await response.WriteStringAsync(message);

var invocationResult = context.GetInvocationResult();

var httpOutputBindingFromMultipleOutputBindings = GetHttpOutputBindingFromMultipleOutputBinding(context);
if (httpOutputBindingFromMultipleOutputBindings is not null)
{
httpOutputBindingFromMultipleOutputBindings.Value = newHttpResponse;
httpOutputBindingFromMultipleOutputBindings.Value = response;
}
else
{
invocationResult.Value = newHttpResponse;
invocationResult.Value = response;
}
}

private static OutputBindingData<HttpResponseData>? GetHttpOutputBindingFromMultipleOutputBinding(FunctionContext context)
{
// The output binding entry name will be "$return" only when the function return type is HttpResponseData
var httpOutputBinding = context.GetOutputBindings<HttpResponseData>()
.FirstOrDefault(b => b.BindingType == "http" && b.Name != "$return");
var httpOutputBinding = context.GetOutputBindings<HttpResponseData>().FirstOrDefault(b => b.BindingType == "http" && b.Name != "$return");

return httpOutputBinding;
}
Expand Down
29 changes: 10 additions & 19 deletions MM.API/Core/StorageHelper.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.Extensions.Configuration;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using static VerusDate.Shared.Helper.ImageHelper;
using MM.Shared.Models.Profile;
using static MM.Shared.Core.Helper.ImageHelper;

namespace MM.API.Core
{
public class StorageHelper
public class StorageHelper(IConfiguration configuration)
{
public IConfiguration Configuration { get; }
public IConfiguration Configuration { get; } = configuration;

public StorageHelper(IConfiguration configuration)
{
Configuration = configuration;
}

public async Task UploadPhoto(PhotoType type, Stream stream, string fileName, CancellationToken cancellationToken)
public async Task UploadPhoto(PhotoType type, Stream stream, string fileName, string userId, CancellationToken cancellationToken)
{
var container = new BlobContainerClient(Configuration.GetValue<string>("AzureStorage"), GetPhotoContainer(type));
var client = container.GetBlobClient(fileName);

var headers = new BlobHttpHeaders { ContentType = "image/jpeg" };

await client.UploadAsync(stream, headers, cancellationToken: cancellationToken);
await client.UploadAsync(stream, headers, new Dictionary<string, string>() { { "id", userId } }, cancellationToken: cancellationToken);
}

public async Task DeletePhoto(PhotoType type, string fileName, CancellationToken cancellationToken)
public async Task DeletePhoto(PhotoType type, string pictureId, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(fileName)) return;

var container = new BlobContainerClient(Configuration.GetValue<string>("AzureStorage"), GetPhotoContainer(type));
var blob = container.GetBlobClient(fileName);
var blob = container.GetBlobClient(pictureId);

if (await blob.ExistsAsync())
if (await blob.ExistsAsync(cancellationToken))
{
await blob.DeleteAsync(DeleteSnapshotsOption.IncludeSnapshots, cancellationToken: cancellationToken);
}
}
}
}
}
4 changes: 2 additions & 2 deletions MM.API/Functions/ExternalFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class ExternalFunction(IConfiguration config)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -39,7 +39,7 @@ public class ExternalFunction(IConfiguration config)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion MM.API/Functions/LoginFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public async Task LoginAdd(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions MM.API/Functions/PaddleFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class PaddleFunction(CosmosRepository repo, IConfiguration configuration)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -62,7 +62,7 @@ public class PaddleFunction(CosmosRepository repo, IConfiguration configuration)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -91,7 +91,7 @@ public async Task PostSubscription(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -116,7 +116,7 @@ public Configurations Configurations([HttpTrigger(AuthorizationLevel.Anonymous,
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions MM.API/Functions/PrincipalFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class PrincipalFunction(CosmosRepository repo)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -39,7 +39,7 @@ public class PrincipalFunction(CosmosRepository repo)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -58,7 +58,7 @@ public class PrincipalFunction(CosmosRepository repo)
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -80,7 +80,7 @@ public async Task<ClientePrincipal> PrincipalPaddle(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -116,7 +116,7 @@ public async Task PrincipalRemove(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions MM.API/Functions/ProfileFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class ProfileFunction(CosmosProfileRepository repo, CosmosRepository repo
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -39,7 +39,7 @@ public class ProfileFunction(CosmosProfileRepository repo, CosmosRepository repo
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -56,7 +56,7 @@ public class ProfileFunction(CosmosProfileRepository repo, CosmosRepository repo
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -119,7 +119,7 @@ public async Task<ProfileModel> ProfileUpdateData(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -136,7 +136,7 @@ public async Task<FilterModel> ProfileUpdateFilter(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -153,7 +153,7 @@ public async Task<SettingModel> ProfileUpdateSetting(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions MM.API/Functions/SendgridFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SendgridFunction(CosmosEmailRepository repo, IConfiguration configu
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand All @@ -38,7 +38,7 @@ public async Task EmailUpdate(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -70,7 +70,7 @@ public async Task SendgridInbound(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}

Expand Down Expand Up @@ -102,7 +102,7 @@ public async Task SendgridSendEmail(
catch (Exception ex)
{
req.ProcessException(ex);
throw new UnhandledException(ex.BuildException());
throw;
}
}
}
Expand Down
Loading

0 comments on commit 132e1d7

Please sign in to comment.