using Marco.Pms.Model.MongoDBModels.Employees; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MongoDB.Driver; namespace Marco.Pms.Helpers.CacheHelper { public class EmployeeCache { private readonly IMongoCollection _collection; public EmployeeCache(IConfiguration configuration) { var connectionString = configuration["MongoDB:ConnectionString"]; var mongoUrl = new MongoUrl(connectionString); var client = new MongoClient(mongoUrl); // Your MongoDB connection string var mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name _collection = mongoDB.GetCollection("EmployeeProfile"); } public async Task AddApplicationRoleToCache(Guid employeeId, List newRoleIds, List newPermissionIds) { // 2. Perform database queries concurrently for better performance. var employeeIdString = employeeId.ToString(); // 5. Build a single, efficient update operation. var filter = Builders.Filter.Eq(e => e.Id, employeeIdString); var update = Builders.Update .AddToSetEach(e => e.ApplicationRoleIds, newRoleIds) .AddToSetEach(e => e.PermissionIds, newPermissionIds); var options = new UpdateOptions { IsUpsert = true }; var result = await _collection.UpdateOneAsync(filter, update, options); await InitializeCollectionAsync(); // 6. Return a more accurate result indicating success for both updates and upserts. // The operation is successful if an existing document was modified OR a new one was created. return result.IsAcknowledged && (result.ModifiedCount > 0 || result.UpsertedId != null); } public async Task AddProjectsToCache(Guid employeeId, List projectIds) { var newprojectIds = projectIds.Select(p => p.ToString()).ToList(); var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .AddToSetEach(e => e.ProjectIds, newprojectIds); var result = await _collection.UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); if (result.MatchedCount == 0) { return false; } await InitializeCollectionAsync(); return true; } public async Task> GetProjectsFromCache(Guid employeeId) { var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var result = await _collection .Find(filter) .FirstOrDefaultAsync(); var projectIds = new List(); if (result != null) { projectIds = result.ProjectIds.Select(Guid.Parse).ToList(); } return projectIds; } public async Task> GetPermissionsFromCache(Guid employeeId) { var filter = Builders.Filter.Eq(e => e.Id, employeeId.ToString()); var result = await _collection .Find(filter) .FirstOrDefaultAsync(); var permissionIds = new List(); if (result != null) { permissionIds = result.PermissionIds.Select(Guid.Parse).ToList(); } return permissionIds; } public async Task ClearAllProjectIdsFromCache(Guid employeeId) { var filter = Builders.Filter .Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .Set(e => e.ProjectIds, new List()); var result = await _collection.UpdateOneAsync(filter, update); if (result.ModifiedCount == 0) return false; return true; } public async Task ClearAllProjectIdsByRoleIdFromCache(Guid roleId) { var filter = Builders.Filter.AnyEq(e => e.ApplicationRoleIds, roleId.ToString()); var update = Builders.Update .Set(e => e.ProjectIds, new List()); var result = await _collection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) return false; return true; } public async Task ClearAllProjectIdsByPermissionIdFromCache(Guid permissionId) { var filter = Builders.Filter.AnyEq(e => e.PermissionIds, permissionId.ToString()); var update = Builders.Update.Set(e => e.ProjectIds, new List()); var result = await _collection.UpdateManyAsync(filter, update).ConfigureAwait(false); return result.IsAcknowledged && result.ModifiedCount > 0; } public async Task RemoveRoleIdFromCache(Guid employeeId, Guid roleId) { var filter = Builders.Filter .Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .Pull(e => e.ApplicationRoleIds, roleId.ToString()); var result = await _collection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) return false; if (result.ModifiedCount == 0) return false; return true; } public async Task ClearAllPermissionIdsByEmployeeIDFromCache(Guid employeeId) { var filter = Builders.Filter .Eq(e => e.Id, employeeId.ToString()); var update = Builders.Update .Set(e => e.PermissionIds, new List()); var result = await _collection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) return false; return true; } public async Task ClearAllPermissionIdsByRoleIdFromCache(Guid roleId) { var filter = Builders.Filter.AnyEq(e => e.ApplicationRoleIds, roleId.ToString()); var update = Builders.Update .Set(e => e.PermissionIds, new List()); var result = await _collection.UpdateOneAsync(filter, update); if (result.MatchedCount == 0) return false; return true; } public async Task ClearAllEmployeesFromCache() { var result = await _collection.DeleteManyAsync(FilterDefinition.Empty); if (result.DeletedCount == 0) return false; return true; } // A private method to handle the one-time setup of the collection's indexes. private async Task InitializeCollectionAsync() { // 1. Define the TTL (Time-To-Live) index on the 'ExpireAt' field. var indexKeys = Builders.IndexKeys.Ascending(x => x.ExpireAt); var indexOptions = new CreateIndexOptions { // This tells MongoDB to automatically delete documents when their 'ExpireAt' time is reached. ExpireAfter = TimeSpan.FromSeconds(0) }; var indexModel = new CreateIndexModel(indexKeys, indexOptions); // 2. Create the index. This is an idempotent operation if the index already exists. // Use CreateOneAsync since we are only creating a single index. await _collection.Indexes.CreateOneAsync(indexModel); } } }