Files
hpc/internal/server/server.go
dailz 2298e92516 feat(handler): add upload, file, and folder handlers with routes
Add UploadHandler (5 endpoints), FileHandler (4 endpoints), FolderHandler (4 endpoints) with Gin route registration in server.go.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-15 09:23:17 +08:00

183 lines
4.7 KiB
Go

package server
import (
"net/http"
"gcy_hpc_server/internal/middleware"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type JobHandler interface {
SubmitJob(c *gin.Context)
GetJobs(c *gin.Context)
GetJobHistory(c *gin.Context)
GetJob(c *gin.Context)
CancelJob(c *gin.Context)
}
type ClusterHandler interface {
GetNodes(c *gin.Context)
GetNode(c *gin.Context)
GetPartitions(c *gin.Context)
GetPartition(c *gin.Context)
GetDiag(c *gin.Context)
}
type ApplicationHandler interface {
ListApplications(c *gin.Context)
CreateApplication(c *gin.Context)
GetApplication(c *gin.Context)
UpdateApplication(c *gin.Context)
DeleteApplication(c *gin.Context)
SubmitApplication(c *gin.Context)
}
type UploadHandler interface {
InitUpload(c *gin.Context)
GetUploadStatus(c *gin.Context)
UploadChunk(c *gin.Context)
CompleteUpload(c *gin.Context)
CancelUpload(c *gin.Context)
}
type FileHandler interface {
ListFiles(c *gin.Context)
GetFile(c *gin.Context)
DownloadFile(c *gin.Context)
DeleteFile(c *gin.Context)
}
type FolderHandler interface {
CreateFolder(c *gin.Context)
GetFolder(c *gin.Context)
ListFolders(c *gin.Context)
DeleteFolder(c *gin.Context)
}
// NewRouter creates a Gin engine with all API v1 routes registered with real handlers.
func NewRouter(jobH JobHandler, clusterH ClusterHandler, appH ApplicationHandler, uploadH UploadHandler, fileH FileHandler, folderH FolderHandler, logger *zap.Logger) *gin.Engine {
gin.SetMode(gin.ReleaseMode)
r := gin.New()
r.Use(gin.Recovery())
if logger != nil {
r.Use(middleware.RequestLogger(logger))
}
v1 := r.Group("/api/v1")
jobs := v1.Group("/jobs")
jobs.POST("/submit", jobH.SubmitJob)
jobs.GET("", jobH.GetJobs)
jobs.GET("/history", jobH.GetJobHistory)
jobs.GET("/:id", jobH.GetJob)
jobs.DELETE("/:id", jobH.CancelJob)
v1.GET("/nodes", clusterH.GetNodes)
v1.GET("/nodes/:name", clusterH.GetNode)
v1.GET("/partitions", clusterH.GetPartitions)
v1.GET("/partitions/:name", clusterH.GetPartition)
v1.GET("/diag", clusterH.GetDiag)
apps := v1.Group("/applications")
apps.GET("", appH.ListApplications)
apps.POST("", appH.CreateApplication)
apps.GET("/:id", appH.GetApplication)
apps.PUT("/:id", appH.UpdateApplication)
apps.DELETE("/:id", appH.DeleteApplication)
apps.POST("/:id/submit", appH.SubmitApplication)
files := v1.Group("/files")
if uploadH != nil {
uploads := files.Group("/uploads")
uploads.POST("", uploadH.InitUpload)
uploads.GET("/:id", uploadH.GetUploadStatus)
uploads.PUT("/:id/chunks/:index", uploadH.UploadChunk)
uploads.POST("/:id/complete", uploadH.CompleteUpload)
uploads.DELETE("/:id", uploadH.CancelUpload)
}
if fileH != nil {
files.GET("", fileH.ListFiles)
files.GET("/:id", fileH.GetFile)
files.GET("/:id/download", fileH.DownloadFile)
files.DELETE("/:id", fileH.DeleteFile)
}
if folderH != nil {
folders := files.Group("/folders")
folders.POST("", folderH.CreateFolder)
folders.GET("", folderH.ListFolders)
folders.GET("/:id", folderH.GetFolder)
folders.DELETE("/:id", folderH.DeleteFolder)
}
return r
}
// NewTestRouter creates a router for testing without real handlers.
func NewTestRouter() *gin.Engine {
gin.SetMode(gin.TestMode)
r := gin.New()
r.Use(gin.Recovery())
v1 := r.Group("/api/v1")
registerPlaceholderRoutes(v1)
return r
}
func registerPlaceholderRoutes(v1 *gin.RouterGroup) {
jobs := v1.Group("/jobs")
jobs.POST("/submit", notImplemented)
jobs.GET("", notImplemented)
jobs.GET("/history", notImplemented)
jobs.GET("/:id", notImplemented)
jobs.DELETE("/:id", notImplemented)
v1.GET("/nodes", notImplemented)
v1.GET("/nodes/:name", notImplemented)
v1.GET("/partitions", notImplemented)
v1.GET("/partitions/:name", notImplemented)
v1.GET("/diag", notImplemented)
apps := v1.Group("/applications")
apps.GET("", notImplemented)
apps.POST("", notImplemented)
apps.GET("/:id", notImplemented)
apps.PUT("/:id", notImplemented)
apps.DELETE("/:id", notImplemented)
apps.POST("/:id/submit", notImplemented)
files := v1.Group("/files")
uploads := files.Group("/uploads")
uploads.POST("", notImplemented)
uploads.GET("/:id", notImplemented)
uploads.PUT("/:id/chunks/:index", notImplemented)
uploads.POST("/:id/complete", notImplemented)
uploads.DELETE("/:id", notImplemented)
files.GET("", notImplemented)
files.GET("/:id", notImplemented)
files.GET("/:id/download", notImplemented)
files.DELETE("/:id", notImplemented)
folders := files.Group("/folders")
folders.POST("", notImplemented)
folders.GET("", notImplemented)
folders.GET("/:id", notImplemented)
folders.DELETE("/:id", notImplemented)
}
func notImplemented(c *gin.Context) {
c.JSON(http.StatusNotImplemented, APIResponse{
Success: false,
Error: "not implemented",
})
}