package app import ( "context" "errors" "fmt" "time" "gitea.dwysokinski.me/twhelp/core/internal/domain" ) type SnapshotService struct { versionSvc *VersionService serverSvc *ServerService serverSnapshotPub SnapshotPublisher tribeSnapshotPub SnapshotPublisher playerSnapshotPub SnapshotPublisher } func NewSnapshotService( versionSvc *VersionService, serverSvc *ServerService, serverSnapshotPub SnapshotPublisher, tribeSnapshotPub SnapshotPublisher, playerSnapshotPub SnapshotPublisher, ) *SnapshotService { return &SnapshotService{ versionSvc: versionSvc, serverSvc: serverSvc, serverSnapshotPub: serverSnapshotPub, tribeSnapshotPub: tribeSnapshotPub, playerSnapshotPub: playerSnapshotPub, } } func (svc *SnapshotService) Create(ctx context.Context) error { listVersionsRes, err := svc.versionSvc.List(ctx, domain.NewListVersionsParams()) if err != nil { return err } versions := listVersionsRes.Versions() for _, v := range versions { loc, loopErr := time.LoadLocation(v.Timezone()) if loopErr != nil { return fmt.Errorf("%s: %w", v.Code(), err) } year, month, day := time.Now().In(loc).Date() snapshotsCreatedAtLT := time.Date(year, month, day, 0, 0, 0, 0, loc) date := time.Date(year, month, day, 0, 0, 0, 0, time.UTC) if loopErr = errors.Join( svc.publishServer(ctx, v, snapshotsCreatedAtLT, date), svc.publishTribe(ctx, v, snapshotsCreatedAtLT, date), svc.publishPlayer(ctx, v, snapshotsCreatedAtLT, date), ); loopErr != nil { return loopErr } } return nil } func (svc *SnapshotService) publishServer( ctx context.Context, v domain.Version, snapshotCreatedAtLT time.Time, date time.Time, ) error { params, err := svc.baseParams(v) if err != nil { return err } if err = params.SetSnapshotCreatedAtLT(domain.NullTime{ V: snapshotCreatedAtLT, Valid: true, }); err != nil { return err } servers, err := svc.serverSvc.ListAll(ctx, params) if err != nil { return err } payloads, err := svc.toPayload(v, servers, date) if err != nil { return err } return svc.serverSnapshotPub.CmdCreate(ctx, payloads...) } func (svc *SnapshotService) publishTribe( ctx context.Context, v domain.Version, snapshotsCreatedAtLT time.Time, date time.Time, ) error { params, err := svc.baseParams(v) if err != nil { return err } if err = params.SetTribeSnapshotsCreatedAtLT(domain.NullTime{ V: snapshotsCreatedAtLT, Valid: true, }); err != nil { return err } servers, err := svc.serverSvc.ListAll(ctx, params) if err != nil { return err } payloads, err := svc.toPayload(v, servers, date) if err != nil { return err } return svc.tribeSnapshotPub.CmdCreate(ctx, payloads...) } func (svc *SnapshotService) publishPlayer( ctx context.Context, v domain.Version, snapshotsCreatedAtLT time.Time, date time.Time, ) error { params, err := svc.baseParams(v) if err != nil { return err } if err = params.SetPlayerSnapshotsCreatedAtLT(domain.NullTime{ V: snapshotsCreatedAtLT, Valid: true, }); err != nil { return err } servers, err := svc.serverSvc.ListAll(ctx, params) if err != nil { return err } payloads, err := svc.toPayload(v, servers, date) if err != nil { return err } return svc.playerSnapshotPub.CmdCreate(ctx, payloads...) } func (svc *SnapshotService) baseParams(v domain.Version) (domain.ListServersParams, error) { params := domain.NewListServersParams() if err := params.SetVersionCodes([]string{v.Code()}); err != nil { return domain.ListServersParams{}, err } if err := params.SetOpen(domain.NullBool{ V: true, Valid: true, }); err != nil { return domain.ListServersParams{}, nil } return params, nil } func (svc *SnapshotService) toPayload( v domain.Version, servers domain.Servers, date time.Time, ) ([]domain.CreateSnapshotsCmdPayload, error) { payloads := make([]domain.CreateSnapshotsCmdPayload, 0, len(servers)) for _, s := range servers { p, err := domain.NewCreateSnapshotsCmdPayload(s.Key(), v.Code(), v.Timezone(), date) if err != nil { return nil, fmt.Errorf("%s: couldn't construct domain.CreateSnapshotsCmdPayload: %w", s.Key(), err) } payloads = append(payloads, p) } return payloads, nil }