116 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using DysonNetwork.Shared.Proto;
 | |
| using Grpc.Core;
 | |
| using Microsoft.EntityFrameworkCore;
 | |
| using NodaTime;
 | |
| 
 | |
| namespace DysonNetwork.Pass.Account;
 | |
| 
 | |
| public class ActionLogServiceGrpc : Shared.Proto.ActionLogService.ActionLogServiceBase
 | |
| {
 | |
|     private readonly ActionLogService _actionLogService;
 | |
|     private readonly AppDatabase _db;
 | |
|     private readonly ILogger<ActionLogServiceGrpc> _logger;
 | |
| 
 | |
|     public ActionLogServiceGrpc(
 | |
|         ActionLogService actionLogService,
 | |
|         AppDatabase db,
 | |
|         ILogger<ActionLogServiceGrpc> logger)
 | |
|     {
 | |
|         _actionLogService = actionLogService ?? throw new ArgumentNullException(nameof(actionLogService));
 | |
|         _db = db ?? throw new ArgumentNullException(nameof(db));
 | |
|         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
 | |
|     }
 | |
| 
 | |
|     public override async Task<CreateActionLogResponse> CreateActionLog(CreateActionLogRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         if (string.IsNullOrEmpty(request.AccountId) || !Guid.TryParse(request.AccountId, out var accountId))
 | |
|         {
 | |
|             throw new RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.InvalidArgument, "Invalid account ID"));
 | |
|         }
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             var meta = request.Meta
 | |
|                 ?.Select(x => new KeyValuePair<string, object>(x.Key, GrpcTypeHelper.ConvertValueToObject(x.Value)))
 | |
|                 .ToDictionary() ?? new Dictionary<string, object>();
 | |
| 
 | |
|             _actionLogService.CreateActionLog(
 | |
|                 accountId,
 | |
|                 request.Action,
 | |
|                 meta
 | |
|             );
 | |
| 
 | |
|             await Task.CompletedTask;
 | |
|             return new CreateActionLogResponse();
 | |
|         }
 | |
|         catch (Exception ex)
 | |
|         {
 | |
|             _logger.LogError(ex, "Error creating action log");
 | |
|             throw new RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.Internal, "Failed to create action log"));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public override async Task<ListActionLogsResponse> ListActionLogs(ListActionLogsRequest request,
 | |
|         ServerCallContext context)
 | |
|     {
 | |
|         if (string.IsNullOrEmpty(request.AccountId) || !Guid.TryParse(request.AccountId, out var accountId))
 | |
|         {
 | |
|             throw new RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.InvalidArgument, "Invalid account ID"));
 | |
|         }
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             var query = _db.ActionLogs
 | |
|                 .AsNoTracking()
 | |
|                 .Where(log => log.AccountId == accountId);
 | |
| 
 | |
|             if (!string.IsNullOrEmpty(request.Action))
 | |
|             {
 | |
|                 query = query.Where(log => log.Action == request.Action);
 | |
|             }
 | |
| 
 | |
|             // Apply ordering (default to newest first)
 | |
|             query = (request.OrderBy?.ToLower() ?? "createdat desc") switch
 | |
|             {
 | |
|                 "createdat" => query.OrderBy(log => log.CreatedAt),
 | |
|                 "createdat desc" => query.OrderByDescending(log => log.CreatedAt),
 | |
|                 _ => query.OrderByDescending(log => log.CreatedAt)
 | |
|             };
 | |
| 
 | |
|             // Apply pagination
 | |
|             var pageSize = request.PageSize == 0 ? 50 : Math.Min(request.PageSize, 1000);
 | |
|             var logs = await query
 | |
|                 .Take(pageSize + 1) // Fetch one extra to determine if there are more pages
 | |
|                 .ToListAsync();
 | |
| 
 | |
|             var hasMore = logs.Count > pageSize;
 | |
|             if (hasMore)
 | |
|             {
 | |
|                 logs.RemoveAt(logs.Count - 1);
 | |
|             }
 | |
| 
 | |
|             var response = new ListActionLogsResponse
 | |
|             {
 | |
|                 TotalSize = await query.CountAsync()
 | |
|             };
 | |
| 
 | |
|             if (hasMore)
 | |
|             {
 | |
|                 // In a real implementation, you'd generate a proper page token
 | |
|                 response.NextPageToken = (logs.LastOrDefault()?.CreatedAt ?? SystemClock.Instance.GetCurrentInstant())
 | |
|                     .ToString();
 | |
|             }
 | |
| 
 | |
|             response.ActionLogs.AddRange(logs.Select(log => log.ToProtoValue()));
 | |
| 
 | |
|             return response;
 | |
|         }
 | |
|         catch (Exception ex)
 | |
|         {
 | |
|             _logger.LogError(ex, "Error listing action logs");
 | |
|             throw new RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.Internal, "Failed to list action logs"));
 | |
|         }
 | |
|     }
 | |
| }
 |