同步前后端联调与文档更新
This commit is contained in:
178
backend/internal/service/admin_pipeline_service.go
Normal file
178
backend/internal/service/admin_pipeline_service.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"cmr-backend/internal/apperr"
|
||||
"cmr-backend/internal/store/postgres"
|
||||
)
|
||||
|
||||
type AdminPipelineService struct {
|
||||
store *postgres.Store
|
||||
configService *ConfigService
|
||||
}
|
||||
|
||||
type AdminReleaseView struct {
|
||||
ID string `json:"id"`
|
||||
ReleaseNo int `json:"releaseNo"`
|
||||
ConfigLabel string `json:"configLabel"`
|
||||
ManifestURL string `json:"manifestUrl"`
|
||||
ManifestChecksumSha256 *string `json:"manifestChecksumSha256,omitempty"`
|
||||
RouteCode *string `json:"routeCode,omitempty"`
|
||||
BuildID *string `json:"buildId,omitempty"`
|
||||
Status string `json:"status"`
|
||||
PublishedAt string `json:"publishedAt"`
|
||||
}
|
||||
|
||||
type AdminEventPipelineView struct {
|
||||
EventID string `json:"eventId"`
|
||||
CurrentRelease *AdminReleaseView `json:"currentRelease,omitempty"`
|
||||
Sources []EventConfigSourceView `json:"sources"`
|
||||
Builds []EventConfigBuildView `json:"builds"`
|
||||
Releases []AdminReleaseView `json:"releases"`
|
||||
}
|
||||
|
||||
type AdminRollbackReleaseInput struct {
|
||||
ReleaseID string `json:"releaseId"`
|
||||
}
|
||||
|
||||
func NewAdminPipelineService(store *postgres.Store, configService *ConfigService) *AdminPipelineService {
|
||||
return &AdminPipelineService{
|
||||
store: store,
|
||||
configService: configService,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AdminPipelineService) GetEventPipeline(ctx context.Context, eventPublicID string, limit int) (*AdminEventPipelineView, error) {
|
||||
event, err := s.store.GetEventByPublicID(ctx, strings.TrimSpace(eventPublicID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "event_not_found", "event not found")
|
||||
}
|
||||
|
||||
sources, err := s.configService.ListEventConfigSources(ctx, event.PublicID, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buildRecords, err := s.store.ListEventConfigBuildsByEventID(ctx, event.ID, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
releaseRecords, err := s.store.ListEventReleasesByEventID(ctx, event.ID, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builds := make([]EventConfigBuildView, 0, len(buildRecords))
|
||||
for i := range buildRecords {
|
||||
item, err := buildEventConfigBuildView(&buildRecords[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builds = append(builds, *item)
|
||||
}
|
||||
releases := make([]AdminReleaseView, 0, len(releaseRecords))
|
||||
for _, item := range releaseRecords {
|
||||
releases = append(releases, buildAdminReleaseView(item))
|
||||
}
|
||||
|
||||
result := &AdminEventPipelineView{
|
||||
EventID: event.PublicID,
|
||||
Sources: sources,
|
||||
Builds: builds,
|
||||
Releases: releases,
|
||||
}
|
||||
if event.CurrentReleasePubID != nil {
|
||||
result.CurrentRelease = &AdminReleaseView{
|
||||
ID: *event.CurrentReleasePubID,
|
||||
ConfigLabel: derefStringOrEmpty(event.ConfigLabel),
|
||||
ManifestURL: derefStringOrEmpty(event.ManifestURL),
|
||||
ManifestChecksumSha256: event.ManifestChecksum,
|
||||
RouteCode: event.RouteCode,
|
||||
Status: "published",
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *AdminPipelineService) BuildSource(ctx context.Context, sourceID string) (*EventConfigBuildView, error) {
|
||||
return s.configService.BuildPreview(ctx, BuildPreviewInput{SourceID: sourceID})
|
||||
}
|
||||
|
||||
func (s *AdminPipelineService) GetBuild(ctx context.Context, buildID string) (*EventConfigBuildView, error) {
|
||||
return s.configService.GetEventConfigBuild(ctx, buildID)
|
||||
}
|
||||
|
||||
func (s *AdminPipelineService) PublishBuild(ctx context.Context, buildID string) (*PublishedReleaseView, error) {
|
||||
return s.configService.PublishBuild(ctx, PublishBuildInput{BuildID: buildID})
|
||||
}
|
||||
|
||||
func (s *AdminPipelineService) RollbackRelease(ctx context.Context, eventPublicID string, input AdminRollbackReleaseInput) (*AdminReleaseView, error) {
|
||||
event, err := s.store.GetEventByPublicID(ctx, strings.TrimSpace(eventPublicID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if event == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "event_not_found", "event not found")
|
||||
}
|
||||
|
||||
input.ReleaseID = strings.TrimSpace(input.ReleaseID)
|
||||
if input.ReleaseID == "" {
|
||||
return nil, apperr.New(http.StatusBadRequest, "invalid_params", "releaseId is required")
|
||||
}
|
||||
|
||||
release, err := s.store.GetEventReleaseByPublicID(ctx, input.ReleaseID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if release == nil {
|
||||
return nil, apperr.New(http.StatusNotFound, "release_not_found", "release not found")
|
||||
}
|
||||
if release.EventID != event.ID {
|
||||
return nil, apperr.New(http.StatusConflict, "release_not_belong_to_event", "release does not belong to event")
|
||||
}
|
||||
if release.Status != "published" {
|
||||
return nil, apperr.New(http.StatusConflict, "release_not_publishable", "release is not published")
|
||||
}
|
||||
|
||||
tx, err := s.store.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
if err := s.store.SetCurrentEventRelease(ctx, tx, event.ID, release.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
view := buildAdminReleaseView(*release)
|
||||
return &view, nil
|
||||
}
|
||||
|
||||
func buildAdminReleaseView(item postgres.EventRelease) AdminReleaseView {
|
||||
return AdminReleaseView{
|
||||
ID: item.PublicID,
|
||||
ReleaseNo: item.ReleaseNo,
|
||||
ConfigLabel: item.ConfigLabel,
|
||||
ManifestURL: item.ManifestURL,
|
||||
ManifestChecksumSha256: item.ManifestChecksum,
|
||||
RouteCode: item.RouteCode,
|
||||
BuildID: item.BuildID,
|
||||
Status: item.Status,
|
||||
PublishedAt: item.PublishedAt.Format(timeRFC3339),
|
||||
}
|
||||
}
|
||||
|
||||
func derefStringOrEmpty(value *string) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
return *value
|
||||
}
|
||||
Reference in New Issue
Block a user