/
updateloop.go
132 lines (119 loc) · 3.25 KB
/
updateloop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Package updateloop provide functionalities to keep the local assets
// up-to-date.
//
// The operation "update" contains 3 sub-operations, and the subject of update
// can be either PictureArt module or Story module.
//
// Pull. It pulls the assets from the remote API, either the HyperGryph API or
// the ArknightsGameData GitHub repository API. It also unpacks or decompresses
// the assets from the downloaded files, therefore, whether the assets are
// pulled from either API, the result directory structure will turn out the
// same.
//
// Preprocess. It converts the pulled assets to the form which the submitter of
// the "submit" sub-operation can recognize. Moreover, it does some image
// preprocessing such as merge the alpha channel and merge the different faces
// onto the body for characters (合并差分).
//
// Submit. It parses the preprocessed assets and submits them to the art service
// and the story service.
//
// After the above sub-operations, all intermediate files shall be deleted to
// preserve the disk space.
package updateloop
import (
"context"
"fmt"
"github.com/flandiayingman/arkwaifu/internal/app/art"
"github.com/flandiayingman/arkwaifu/internal/app/gallery"
"github.com/flandiayingman/arkwaifu/internal/app/story"
"github.com/flandiayingman/arkwaifu/internal/pkg/ark"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.uber.org/fx"
"os"
"time"
)
func init() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
}
func FxModule() fx.Option {
return fx.Module("updateloop",
fx.Provide(
newRepo,
newService,
),
fx.Invoke(
registerService,
),
)
}
// Service provides all functionalities of update.
type Service struct {
repo *repo
artService *art.Service
storyService *story.Service
galleryService *gallery.Service
}
func newService(
artService *art.Service,
storyService *story.Service,
galleryService *gallery.Service,
repo *repo,
) *Service {
return &Service{
artService: artService,
storyService: storyService,
galleryService: galleryService,
repo: repo,
}
}
func registerService(service *Service, lc fx.Lifecycle) {
loopCtx, cancelLoop := context.WithCancel(context.Background())
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
go service.Loop(loopCtx)
return nil
},
OnStop: func(ctx context.Context) error {
cancelLoop()
return nil
},
})
}
func (s *Service) Loop(ctx context.Context) {
for {
select {
case <-ctx.Done():
break
default:
s.AttemptUpdate(ctx)
}
time.Sleep(5 * time.Minute)
}
}
// AttemptUpdate attempts to update the resources.
func (s *Service) AttemptUpdate(ctx context.Context) {
log := log.With().
Logger()
log.Info().Msg("Update loop is attempting to update the assets... ")
defer func() {
v := recover()
if v != nil {
log.Error().
Str("err", fmt.Sprintf("%+v", v)).
Msg("Update loop has recovered from panic.")
}
}()
s.attemptUpdateArt(ctx)
s.attemptUpdateArtThumbnails(ctx)
for _, server := range ark.Servers {
// Skip TW server, since we haven't implemented it yet.
if server == ark.TwServer {
continue
}
s.attemptUpdateStory(ctx, server)
s.attemptUpdateGalleries(ctx, server)
}
log.Info().Msg("Update loop has completed this attempt to update the assets..")
}