RowsAffected == 0 now returns gorm.ErrRecordNotFound so the handler can respond with 404 instead of silently returning 200. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"gcy_hpc_server/internal/model"
|
|
)
|
|
|
|
// TemplateStore provides CRUD operations for job templates via GORM.
|
|
type TemplateStore struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewTemplateStore creates a new TemplateStore.
|
|
func NewTemplateStore(db *gorm.DB) *TemplateStore {
|
|
return &TemplateStore{db: db}
|
|
}
|
|
|
|
// List returns a paginated list of job templates and the total count.
|
|
func (s *TemplateStore) List(ctx context.Context, page, pageSize int) ([]model.JobTemplate, int, error) {
|
|
var templates []model.JobTemplate
|
|
var total int64
|
|
|
|
if err := s.db.WithContext(ctx).Model(&model.JobTemplate{}).Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
if err := s.db.WithContext(ctx).Order("id DESC").Limit(pageSize).Offset(offset).Find(&templates).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return templates, int(total), nil
|
|
}
|
|
|
|
// GetByID returns a single job template by ID. Returns nil, nil when not found.
|
|
func (s *TemplateStore) GetByID(ctx context.Context, id int64) (*model.JobTemplate, error) {
|
|
var t model.JobTemplate
|
|
err := s.db.WithContext(ctx).First(&t, id).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &t, nil
|
|
}
|
|
|
|
// Create inserts a new job template and returns the generated ID.
|
|
func (s *TemplateStore) Create(ctx context.Context, req *model.CreateTemplateRequest) (int64, error) {
|
|
t := &model.JobTemplate{
|
|
Name: req.Name,
|
|
Description: req.Description,
|
|
Script: req.Script,
|
|
Partition: req.Partition,
|
|
QOS: req.QOS,
|
|
CPUs: req.CPUs,
|
|
Memory: req.Memory,
|
|
TimeLimit: req.TimeLimit,
|
|
}
|
|
if err := s.db.WithContext(ctx).Create(t).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return t.ID, nil
|
|
}
|
|
|
|
// Update modifies an existing job template. Only non-empty/non-zero fields are updated.
|
|
func (s *TemplateStore) Update(ctx context.Context, id int64, req *model.UpdateTemplateRequest) error {
|
|
updates := map[string]interface{}{}
|
|
if req.Name != "" {
|
|
updates["name"] = req.Name
|
|
}
|
|
if req.Description != "" {
|
|
updates["description"] = req.Description
|
|
}
|
|
if req.Script != "" {
|
|
updates["script"] = req.Script
|
|
}
|
|
if req.Partition != "" {
|
|
updates["partition"] = req.Partition
|
|
}
|
|
if req.QOS != "" {
|
|
updates["qos"] = req.QOS
|
|
}
|
|
if req.CPUs > 0 {
|
|
updates["cpus"] = req.CPUs
|
|
}
|
|
if req.Memory != "" {
|
|
updates["memory"] = req.Memory
|
|
}
|
|
if req.TimeLimit != "" {
|
|
updates["time_limit"] = req.TimeLimit
|
|
}
|
|
|
|
if len(updates) == 0 {
|
|
return nil // nothing to update
|
|
}
|
|
|
|
result := s.db.WithContext(ctx).Model(&model.JobTemplate{}).Where("id = ?", id).Updates(updates)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected == 0 {
|
|
return gorm.ErrRecordNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete removes a job template by ID. Idempotent — returns nil even if the row doesn't exist.
|
|
func (s *TemplateStore) Delete(ctx context.Context, id int64) error {
|
|
result := s.db.WithContext(ctx).Delete(&model.JobTemplate{}, id)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
return nil
|
|
}
|