add bulk users

This commit is contained in:
Aditya Siregar
2025-08-15 22:42:58 +07:00
parent e1a5e9efd3
commit 5966301165
8 changed files with 313 additions and 25 deletions
+52 -5
View File
@@ -66,16 +66,13 @@ func (h *UserHandler) BulkCreateUsers(c *gin.Context) {
return
}
// Increased limit to handle 1000+ users
if len(req.Users) > 5000 {
h.sendValidationErrorResponse(c, "Cannot create more than 5000 users at once", constants.MissingFieldErrorCode)
return
}
// Set a longer timeout for large bulk operations
ctx := c.Request.Context()
if len(req.Users) > 500 {
// Create a context with extended timeout for large operations
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
@@ -97,11 +94,61 @@ func (h *UserHandler) BulkCreateUsers(c *gin.Context) {
statusCode = http.StatusMultiStatus
}
logger.FromContext(c).Infof("UserHandler::BulkCreateUsers -> Successfully processed bulk creation: %d succeeded, %d failed",
logger.FromContext(c).Infof("UserHandler::BulkCreateUsers -> Successfully processed bulk creation: %d succeeded, %d failed",
response.Summary.Succeeded, response.Summary.Failed)
c.JSON(statusCode, contract.BuildSuccessResponse(response))
}
func (h *UserHandler) BulkCreateUsersAsync(c *gin.Context) {
var req contract.BulkCreateUsersRequest
if err := c.ShouldBindJSON(&req); err != nil {
logger.FromContext(c).WithError(err).Error("UserHandler::BulkCreateUsersAsync -> request binding failed")
h.sendValidationErrorResponse(c, "Invalid request body", constants.MissingFieldErrorCode)
return
}
if len(req.Users) == 0 {
h.sendValidationErrorResponse(c, "Users list cannot be empty", constants.MissingFieldErrorCode)
return
}
if len(req.Users) > 5000 {
h.sendValidationErrorResponse(c, "Cannot create more than 5000 users at once", constants.MissingFieldErrorCode)
return
}
logger.FromContext(c).Infof("UserHandler::BulkCreateUsersAsync -> Starting async bulk creation of %d users", len(req.Users))
response, err := h.userService.BulkCreateUsersAsync(c.Request.Context(), &req)
if err != nil {
logger.FromContext(c).WithError(err).Error("UserHandler::BulkCreateUsersAsync -> Failed to start async bulk creation")
h.sendErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
}
logger.FromContext(c).Infof("UserHandler::BulkCreateUsersAsync -> Job created with ID: %s", response.JobID)
c.JSON(http.StatusAccepted, contract.BuildSuccessResponse(response))
}
func (h *UserHandler) GetBulkJobStatus(c *gin.Context) {
jobIDStr := c.Param("jobId")
jobID, err := uuid.Parse(jobIDStr)
if err != nil {
logger.FromContext(c).WithError(err).Error("UserHandler::GetBulkJobStatus -> invalid job ID")
h.sendValidationErrorResponse(c, "Invalid job ID", constants.ValidationErrorCode)
return
}
job, err := h.userService.GetBulkJobStatus(c.Request.Context(), jobID)
if err != nil {
logger.FromContext(c).WithError(err).Error("UserHandler::GetBulkJobStatus -> Failed to get job status")
h.sendErrorResponse(c, err.Error(), http.StatusNotFound)
return
}
c.JSON(http.StatusOK, contract.BuildSuccessResponse(job))
}
func (h *UserHandler) UpdateUser(c *gin.Context) {
userIDStr := c.Param("id")
userID, err := uuid.Parse(userIDStr)
@@ -358,7 +405,7 @@ func (h *UserHandler) GetActiveUsersForMention(c *gin.Context) {
if limit > 100 {
limit = 100
}
var searchPtr *string
if search != "" {
searchPtr = &search
+3
View File
@@ -3,6 +3,7 @@ package handler
import (
"context"
"eslogad-be/internal/contract"
"eslogad-be/internal/manager"
"github.com/google/uuid"
)
@@ -10,6 +11,8 @@ import (
type UserService interface {
CreateUser(ctx context.Context, req *contract.CreateUserRequest) (*contract.UserResponse, error)
BulkCreateUsers(ctx context.Context, req *contract.BulkCreateUsersRequest) (*contract.BulkCreateUsersResponse, error)
BulkCreateUsersAsync(ctx context.Context, req *contract.BulkCreateUsersRequest) (*contract.BulkCreateAsyncResponse, error)
GetBulkJobStatus(ctx context.Context, jobID uuid.UUID) (*manager.BulkJobResult, error)
UpdateUser(ctx context.Context, id uuid.UUID, req *contract.UpdateUserRequest) (*contract.UserResponse, error)
DeleteUser(ctx context.Context, id uuid.UUID) error
GetUserByID(ctx context.Context, id uuid.UUID) (*contract.UserResponse, error)