Files
files/internal/logic/files/complete.go

62 lines
1.7 KiB
Go

package files
import (
"time"
"git.apinb.com/bsm-sdk/core/infra"
fileerrors "git.apinb.com/ops/files/internal/errors"
"git.apinb.com/ops/files/internal/impl"
"git.apinb.com/ops/files/internal/models"
"github.com/gin-gonic/gin"
)
func CompleteUpload(ctx *gin.Context) {
fileObject, ok := loadOwnedFile(ctx)
if !ok {
return
}
if fileObject.Status != models.FileStatusPending {
infra.Response.Error(ctx, fileerrors.ErrUploadStatusConflict)
return
}
if fileObject.ExpiresAt == nil || !fileObject.ExpiresAt.After(time.Now()) {
infra.Response.Error(ctx, fileerrors.ErrUploadExpired)
return
}
objectInfo, err := impl.StorageService.Stat(ctx.Request.Context(), fileObject.ObjectKey)
if err != nil {
infra.Response.Error(ctx, fileerrors.ErrObjectStorageOperation)
return
}
if objectInfo.Size != fileObject.ExpectedSize {
infra.Response.Error(ctx, fileerrors.ErrObjectInfoMismatch)
return
}
completedAt := time.Now()
result := impl.DBService.Model(&models.FileObject{}).
Where("id = ? AND status = ? AND expires_at > ?", fileObject.ID, models.FileStatusPending, completedAt).
Updates(map[string]any{
"status": models.FileStatusReady,
"actual_size": objectInfo.Size,
"e_tag": objectInfo.ETag,
"completed_at": completedAt,
})
if result.Error != nil {
infra.Response.Error(ctx, fileerrors.ErrDatabaseOperation)
return
}
if result.RowsAffected != 1 {
infra.Response.Error(ctx, fileerrors.ErrUploadStatusConflict)
return
}
fileObject.Status = models.FileStatusReady
fileObject.ActualSize = objectInfo.Size
fileObject.ETag = objectInfo.ETag
fileObject.CompletedAt = &completedAt
infra.Response.Success(ctx, newFileResponse(fileObject))
}