Skip to content

Commit

Permalink
geral revision
Browse files Browse the repository at this point in the history
  • Loading branch information
Dhiogo Acioli committed Sep 9, 2024
1 parent 5eb99a6 commit e3a4b4f
Show file tree
Hide file tree
Showing 43 changed files with 773 additions and 220 deletions.
6 changes: 5 additions & 1 deletion MM.API/Core/IsolatedFunctionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace MM.API.Core
{
public static class IsolatedFunctionHelper
{
public static async Task<T> GetBody<T>(this HttpRequestData req, CancellationToken cancellationToken) where T : MainDocument, new()
public static async Task<T> GetBody<T>(this HttpRequestData req, CancellationToken cancellationToken) where T : CosmosDocument, new()
{
var model = await JsonSerializer.DeserializeAsync<T>(req.Body, cancellationToken: cancellationToken);

Expand All @@ -35,6 +35,10 @@ public static class IsolatedFunctionHelper
{
priv.Initialize(userId);
}
else if (model is CosmosDocument doc) //generic document
{
doc.SetIds(userId);
}

return model;
}
Expand Down
7 changes: 6 additions & 1 deletion MM.API/Core/Middleware/ExceptionHandlingMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Middleware;
using Microsoft.Extensions.Logging;
using System.Net;
Expand All @@ -15,6 +16,10 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next
{
await next(context);
}
catch (CosmosOperationCanceledException)
{
await context.SetHttpResponseStatusCode(HttpStatusCode.RequestTimeout, "Request Timeout!");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing invocation");
Expand Down
2 changes: 1 addition & 1 deletion MM.API/Core/Middleware/FunctionContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static async Task SetHttpResponseStatusCode(this FunctionContext context,
{
var req = await context.GetHttpRequestDataAsync();

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

// You need to explicitly pass the status code in WriteAsJsonAsync method.
// https://github.com/Azure/azure-functions-dotnet-worker/issues/776
Expand Down
162 changes: 137 additions & 25 deletions MM.API/Functions/CacheFunction.cs

Large diffs are not rendered by default.

27 changes: 10 additions & 17 deletions MM.API/Functions/LoginFunction.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using MM.Shared.Models.Auth;
Expand All @@ -15,34 +14,28 @@ public async Task Add(
{
try
{
var platform = req.GetQueryParameters()["platform"];
if (platform.Empty()) platform = "webapp";
var platform = req.GetQueryParameters()["platform"] ?? "webapp";
var ip = req.GetQueryParameters()["ip"] ?? "null ip";
var userId = req.GetUserId();
if (string.IsNullOrEmpty(userId)) throw new InvalidOperationException("unauthenticated user");
var login = await repo.Get<ClienteLogin>(DocumentType.Login, userId, cancellationToken);

if (login == null)
{
var newLogin = new ClienteLogin { UserId = userId, Logins = [DateTimeOffset.Now], Platforms = [platform!] };
var newLogin = new ClienteLogin
{
UserId = userId,
Accesses = [new Access { Date = DateTimeOffset.Now, Platform = platform, Ip = ip }]
};
newLogin.Initialize(userId);

await repo.Upsert(newLogin, cancellationToken);
}
else
{
if (Array.Exists(login.Platforms, a => a == platform))
{
await repo.PatchItem<ClienteLogin>(DocumentType.Login, userId,
[
PatchOperation.Add("/logins/-", DateTimeOffset.Now),
], cancellationToken);
}
else
{
login.Logins = login.Logins.Union([DateTimeOffset.Now]).ToArray();
login.Platforms = login.Platforms.Union([platform]).ToArray();
await repo.Upsert(login, cancellationToken);
}
login.Accesses = login.Accesses.Union([new Access { Date = DateTimeOffset.Now, Platform = platform, Ip = ip }]).ToArray();

await repo.Upsert(login, cancellationToken);
}
}
catch (Exception ex)
Expand Down
10 changes: 5 additions & 5 deletions MM.API/Functions/ProfileFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

namespace VerusDate.Api.Function
{
public class ProfileFunction(CosmosRepository repo)
public class ProfileFunction(CosmosProfileRepository repo)
{
private readonly CosmosRepository _repo = repo;
private readonly CosmosProfileRepository _repo = repo;

[Function("ProfileGet")]
public async Task<ProfileModel?> Get(
Expand All @@ -17,7 +17,7 @@ public class ProfileFunction(CosmosRepository repo)
{
var userId = req.GetUserId();

return await _repo.Get<ProfileModel>(DocumentType.Profile, userId, cancellationToken);
return await _repo.Get<ProfileModel>(userId, cancellationToken);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -103,7 +103,7 @@ public async Task<ProfileModel> UpdateLooking(
PatchOperation.Add("/dtUpdate", DateTime.UtcNow)
};

return await _repo.PatchItem<ProfileModel>(DocumentType.Profile, userId, operations, cancellationToken);
return await _repo.PatchItem<ProfileModel>(userId, operations, cancellationToken);
}
catch (Exception ex)
{
Expand All @@ -129,7 +129,7 @@ public async Task<ProfileModel> UpdateLooking(
var email = req.GetQueryParameters()["email"];
var userId = req.GetUserId();

var obj = await _repo.Get<ProfileModel>(DocumentType.Profile, userId, cancellationToken);
var obj = await _repo.Get<ProfileModel>(userId, cancellationToken);

obj?.UpdatePartner(id, email);

Expand Down
2 changes: 1 addition & 1 deletion MM.API/Functions/SendgridFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async Task SendgridInbound(
SenderIp = inboundMail.SenderIp
};

await repo.CreateItemAsync(model, cancellationToken);
await repo.UpsertItemAsync(model, cancellationToken);
}
catch (Exception ex)
{
Expand Down
8 changes: 4 additions & 4 deletions MM.API/MM.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
<Compile Remove="Functions\StorageFunction.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.65" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.41.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.43.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.4.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
Expand Down
1 change: 1 addition & 0 deletions MM.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static void ConfigureServices(HostBuilderContext context, IServiceCollection ser
services.AddSingleton<CosmosRepository>();
services.AddSingleton<CosmosCacheRepository>();
services.AddSingleton<CosmosEmailRepository>();
services.AddSingleton<CosmosProfileRepository>();
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
}
Expand Down
25 changes: 18 additions & 7 deletions MM.API/Repository/CosmosCacheRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,40 @@ public CosmosCacheRepository(IConfiguration config, ILogger<CosmosCacheRepositor
{
var response = await Container.ReadItemAsync<CacheDocument<TData>?>(id, new PartitionKey(id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 1.5)
if (response.RequestCharge > 1.7)
{
_logger.LogWarning("Get - Id {0}, RequestCharge {1}", id, response.RequestCharge);
}

return response.Resource;
}
catch (CosmosOperationCanceledException)
{
return null;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
}

public async Task<CacheDocument<TData>?> CreateItemAsync<TData>(CacheDocument<TData> cache, CancellationToken cancellationToken) where TData : class
public async Task<CacheDocument<TData>?> UpsertItemAsync<TData>(CacheDocument<TData> cache, CancellationToken cancellationToken) where TData : class
{
var response = await Container.CreateItemAsync(cache, new PartitionKey(cache.Id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);
try
{
var response = await Container.UpsertItemAsync(cache, new PartitionKey(cache.Id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 12)
{
_logger.LogWarning("Add - Id {0}, RequestCharge {1}", cache.Id, response.RequestCharge);
}

if (response.RequestCharge > 12)
return response.Resource;
}
catch (CosmosOperationCanceledException)
{
_logger.LogWarning("Add - Id {0}, RequestCharge {1}", cache.Id, response.RequestCharge);
return null;
}

return response.Resource;
}
}
}
11 changes: 4 additions & 7 deletions MM.API/Repository/CosmosEmailRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public CosmosEmailRepository(IConfiguration config)

return response.Resource;
}
catch (CosmosOperationCanceledException)
{
return null;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
Expand Down Expand Up @@ -68,12 +72,5 @@ public async Task<List<EmailDocument>> Query(Expression<Func<EmailDocument, bool

return response.Resource;
}

public async Task<EmailDocument?> CreateItemAsync(EmailDocument email, CancellationToken cancellationToken)
{
var response = await Container.CreateItemAsync(email, new PartitionKey(email.Id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

return response.Resource;
}
}
}
112 changes: 112 additions & 0 deletions MM.API/Repository/CosmosProfileRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MM.API.Repository.Core;
using System.Linq.Expressions;

namespace MM.API.Repository
{
public class CosmosProfileRepository
{
public Container Container { get; private set; }
private readonly ILogger<CosmosProfileRepository> _logger;

public CosmosProfileRepository(IConfiguration config, ILogger<CosmosProfileRepository> logger)
{
_logger = logger;

var databaseId = config.GetValue<string>("RepositoryOptions_DatabaseId");
var containerId = config.GetValue<string>("RepositoryOptions_ContainerProfileId");

Container = ApiStartup.CosmosClient.GetContainer(databaseId, containerId);
}

public async Task<T?> Get<T>(string? id, CancellationToken cancellationToken) where T : CosmosDocument
{
if (string.IsNullOrEmpty(id)) throw new ArgumentNullException(nameof(id));

try
{
var response = await Container.ReadItemAsync<T>(id, new PartitionKey(id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 1.5)
{
_logger.LogWarning("Get - ID {0}, RequestCharge {1}", id, response.RequestCharge);
}

return response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
}

public async Task<List<T>> Query<T>(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken) where T : MainDocument
{
var query = Container
.GetItemLinqQueryable<T>(requestOptions: CosmosRepositoryExtensions.GetQueryRequestOptions())
.Where(predicate);

using var iterator = query.ToFeedIterator();
var results = new List<T>();

double charges = 0;
while (iterator.HasMoreResults)
{
var response = await iterator.ReadNextAsync(cancellationToken);
charges += response.RequestCharge;
results.AddRange(response.Resource);
}

if (charges > 5)
{
_logger.LogWarning("Query, RequestCharge {Charges}", charges);
}

return results;
}

public async Task<T> Upsert<T>(T item, CancellationToken cancellationToken) where T : CosmosDocument
{
var response = await Container.UpsertItemAsync(item, new PartitionKey(item.Id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 12)
{
_logger.LogWarning("Upsert - ID {Id}, RequestCharge {Charges}", item.Id, response.RequestCharge);
}

return response.Resource;
}

public async Task<T> PatchItem<T>(string? id, List<PatchOperation> operations, CancellationToken cancellationToken) where T : CosmosDocument
{
//https://learn.microsoft.com/en-us/azure/cosmos-db/partial-document-update-getting-started?tabs=dotnet

var response = await Container.PatchItemAsync<T>(id, new PartitionKey(id), operations, CosmosRepositoryExtensions.GetPatchItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 12)
{
_logger.LogWarning("PatchItem - ID {Id}, RequestCharge {Charges}", id, response.RequestCharge);
}

return response.Resource;
}

public async Task<bool> Delete<T>(T item, CancellationToken cancellationToken) where T : CosmosDocument
{
var response = await Container.DeleteItemAsync<T>(item.Id, new PartitionKey(item.Id), CosmosRepositoryExtensions.GetItemRequestOptions(), cancellationToken);

if (response.RequestCharge > 12)
{
_logger.LogWarning("Delete - ID {Id}, RequestCharge {Charges}", item.Id, response.RequestCharge);
}

return response.StatusCode == System.Net.HttpStatusCode.OK;
}

//Overview of indexing in Azure Cosmos DB
//https://learn.microsoft.com/en-us/azure/cosmos-db/index-overview
}
}
Loading

0 comments on commit e3a4b4f

Please sign in to comment.