github.com/oinume/lekcije@v0.0.0-20231017100347-5b4c5eb6ab24/backend/cmd/teacher_error_resetter/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "flag" 6 "io" 7 "net/http" 8 "os" 9 "time" 10 11 "github.com/jinzhu/gorm" 12 "go.uber.org/zap" 13 14 "github.com/oinume/lekcije/backend/cli" 15 "github.com/oinume/lekcije/backend/domain/config" 16 "github.com/oinume/lekcije/backend/infrastructure/dmm_eikaiwa" 17 "github.com/oinume/lekcije/backend/logger" 18 "github.com/oinume/lekcije/backend/model" 19 "github.com/oinume/lekcije/backend/registry" 20 ) 21 22 func main() { 23 m := &teacherErrorResetterMain{ 24 outStream: os.Stdout, 25 errStream: os.Stderr, 26 db: nil, 27 httpClient: nil, 28 } 29 if err := m.run(os.Args); err != nil { 30 cli.WriteError(m.errStream, err) 31 os.Exit(cli.ExitError) 32 } 33 os.Exit(cli.ExitOK) 34 } 35 36 type teacherErrorResetterMain struct { 37 outStream io.Writer 38 errStream io.Writer 39 db *gorm.DB 40 httpClient *http.Client 41 } 42 43 const fetchErrorCount = 5 44 45 func (m *teacherErrorResetterMain) run(args []string) error { 46 flagSet := flag.NewFlagSet("teacher_error_resetter", flag.ContinueOnError) 47 flagSet.SetOutput(m.errStream) 48 var ( 49 concurrency = flagSet.Int("concurrency", 1, "Concurrency of lessonFetcher") 50 dryRun = flagSet.Bool("dry-run", false, "Don't update database with fetched lessons") 51 logLevel = flag.String("log-level", "info", "Log level") 52 ) 53 if err := flagSet.Parse(args[1:]); err != nil { 54 return err 55 } 56 57 config.MustProcessDefault() 58 if m.db == nil { 59 db, err := model.OpenDB(config.DefaultVars.DBURL(), 1, config.DefaultVars.DebugSQL) 60 if err != nil { 61 cli.WriteError(os.Stderr, err) 62 os.Exit(1) 63 } 64 defer func() { _ = db.Close() }() 65 m.db = db 66 } 67 68 startedAt := time.Now().UTC() 69 appLogger := logger.NewAppLogger(os.Stderr, logger.NewLevel(*logLevel)) 70 appLogger.Info("teacher_error_resetter started") 71 defer func() { 72 elapsed := time.Now().UTC().Sub(startedAt) / time.Millisecond 73 appLogger.Info("teacher_error_resetter finished", zap.Int("elapsed", int(elapsed))) 74 }() 75 76 ctx := context.Background() 77 teacherService := model.NewTeacherService(m.db) 78 teachers, err := teacherService.FindByFetchErrorCountGt(fetchErrorCount) 79 if err != nil { 80 return err 81 } 82 83 mCountryList := registry.MustNewMCountryList(ctx, m.db.DB()) 84 lessonFetcher := dmm_eikaiwa.NewLessonFetcher(m.httpClient, *concurrency, false, mCountryList, appLogger) 85 defer lessonFetcher.Close() 86 for _, t := range teachers { 87 if _, _, err := lessonFetcher.Fetch(ctx, uint(t.ID)); err != nil { 88 appLogger.Error("lessonFetcher.Fetch failed", zap.Uint32("id", t.ID), zap.Error(err)) 89 continue 90 } 91 if *dryRun { 92 appLogger.Info("Skip teacher because of dry-run", zap.Uint32("id", t.ID)) 93 continue 94 } 95 if err := teacherService.ResetFetchErrorCount(t.ID); err != nil { 96 appLogger.Error("teacherService.ResetFetchErrorCount failed", zap.Uint32("id", t.ID), zap.Error(err)) 97 continue 98 } 99 } 100 101 return nil 102 }