Removing the project stored in cache for employee who have the project manage permission
This commit is contained in:
parent
3c8a044d66
commit
8e3eedbfa7
@ -137,6 +137,20 @@ namespace Marco.Pms.CacheHelper
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> ClearAllProjectIdsByPermissionIdFromCache(Guid permissionId)
|
||||
{
|
||||
var filter = Builders<EmployeePermissionMongoDB>.Filter.AnyEq(e => e.PermissionIds, permissionId.ToString());
|
||||
|
||||
var update = Builders<EmployeePermissionMongoDB>.Update
|
||||
.Set(e => e.ProjectIds, new List<string>());
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update);
|
||||
|
||||
if (result.MatchedCount == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> RemoveRoleIdFromCache(Guid employeeId, Guid roleId)
|
||||
{
|
||||
var filter = Builders<EmployeePermissionMongoDB>.Filter
|
||||
|
@ -36,6 +36,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
private readonly IHubContext<MarcoHub> _signalR;
|
||||
private readonly PermissionServices _permission;
|
||||
private readonly CacheUpdateHelper _cache;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly Guid ViewProjects;
|
||||
private readonly Guid ManageProject;
|
||||
private readonly Guid ViewInfra;
|
||||
@ -44,7 +45,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
|
||||
|
||||
public ProjectController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger, RolesHelper rolesHelper, ProjectsHelper projectHelper,
|
||||
IHubContext<MarcoHub> signalR, PermissionServices permission, CacheUpdateHelper cache)
|
||||
IHubContext<MarcoHub> signalR, PermissionServices permission, CacheUpdateHelper cache, IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
_context = context;
|
||||
_userHelper = userHelper;
|
||||
@ -59,6 +60,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
ViewInfra = Guid.Parse("8d7cc6e3-9147-41f7-aaa7-fa507e450bd4");
|
||||
ManageInfra = Guid.Parse("f2aee20a-b754-4537-8166-f9507b44585b");
|
||||
tenantId = _userHelper.GetTenantId();
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
[HttpGet("list/basic")]
|
||||
@ -436,31 +438,56 @@ namespace MarcoBMS.Services.Controllers
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] CreateProjectDto projectDto)
|
||||
{
|
||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
// 1. Validate input first (early exit)
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Values
|
||||
.SelectMany(v => v.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToList();
|
||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||
|
||||
}
|
||||
|
||||
Guid TenantId = GetTenantId();
|
||||
var project = projectDto.ToProjectFromCreateProjectDto(TenantId);
|
||||
// 2. Prepare data without I/O
|
||||
Guid tenantId = _userHelper.GetTenantId(); // Assuming this is fast and from claims
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var loggedInUserId = loggedInEmployee.Id;
|
||||
var project = projectDto.ToProjectFromCreateProjectDto(tenantId);
|
||||
|
||||
_context.Projects.Add(project);
|
||||
// 3. Store it to database
|
||||
try
|
||||
{
|
||||
_context.Projects.Add(project);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the detailed exception
|
||||
_logger.LogError("Failed to create project in database. Rolling back transaction. : {Error}", ex.Message);
|
||||
// Return a server error as the primary operation failed
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An error occurred while saving the project.", ex.Message, 500));
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
// 4. Perform non-critical side-effects (caching, notifications) concurrently
|
||||
try
|
||||
{
|
||||
// These operations do not depend on each other, so they can run in parallel.
|
||||
Task cacheAddDetailsTask = _cache.AddProjectDetails(project);
|
||||
Task cacheClearListTask = _cache.ClearAllProjectIdsByPermissionId(ManageProject);
|
||||
|
||||
await _cache.AddProjectDetails(project);
|
||||
var notification = new { LoggedInUserId = loggedInUserId, Keyword = "Create_Project", Response = project.ToProjectDto() };
|
||||
// Send notification only to the relevant group (e.g., users in the same tenant)
|
||||
Task notificationTask = _signalR.Clients.Group(tenantId.ToString()).SendAsync("NotificationEventHandler", notification);
|
||||
|
||||
var notification = new { LoggedInUserId = LoggedInEmployee.Id, Keyword = "Create_Project", Response = project.ToProjectDto() };
|
||||
// Await all side-effect tasks to complete in parallel
|
||||
await Task.WhenAll(cacheAddDetailsTask, cacheClearListTask, notificationTask);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// The project was created successfully, but a side-effect failed.
|
||||
// Log this as a warning, as the primary operation succeeded. Don't return an error to the user.
|
||||
_logger.LogWarning("Project {ProjectId} was created, but a post-creation side-effect (caching/notification) failed. : {Error}", project.Id, ex.Message);
|
||||
}
|
||||
|
||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(project.ToProjectDto(), "Success.", 200));
|
||||
// 5. Return a success response to the user as soon as the critical data is saved.
|
||||
return Ok(ApiResponse<object>.SuccessResponse(project.ToProjectDto(), "Project created successfully.", 200));
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
|
@ -298,6 +298,17 @@ namespace Marco.Pms.Services.Helpers
|
||||
_logger.LogWarning("Error occured while deleting projectIds from Cache for Application Role {RoleId}: {Error}", roleId, ex.Message);
|
||||
}
|
||||
}
|
||||
public async Task ClearAllProjectIdsByPermissionId(Guid permissionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _employeeCache.ClearAllProjectIdsByPermissionIdFromCache(permissionId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Error occured while deleting projectIds from Cache for Permission {PermissionId}: {Error}", permissionId, ex.Message);
|
||||
}
|
||||
}
|
||||
public async Task ClearAllPermissionIdsByEmployeeID(Guid employeeId)
|
||||
{
|
||||
try
|
||||
|
Loading…
x
Reference in New Issue
Block a user