package main import ( "context" stderrors "errors" "fmt" "log/slog" "git.loyso.art/frx/kurious/internal/common/errors" "git.loyso.art/frx/kurious/internal/common/xcontext" "github.com/teris-io/cli" ) func setupYDBCommand(ctx context.Context) cli.Command { migrationApply := buildCLICommand(func() cli.Command { return cli.NewCommand("apply", "Applies all known migrations"). WithAction(newYDBMigrateApplyAction(ctx)) }) migration := cli.NewCommand("migration", "Migration commands"). WithCommand(migrationApply) coursesGet := buildCLICommand(func() cli.Command { return cli.NewCommand("get", "Fetches one or more courses"). WithArg(cli.NewArg("ids", "List of course ids").AsOptional()). WithAction(newYDBCoursesGetAction(ctx)) }) courses := cli.NewCommand("courses", "Courses commands"). WithCommand(coursesGet) return cli.NewCommand("ydb", "YDB related actions"). WithCommand(migration). WithCommand(courses) } type ydbMigrateApplyAction struct { *baseAction } func newYDBMigrateApplyAction(ctx context.Context) cli.Action { action := &ydbMigrateApplyAction{ baseAction: newBaseAction(ctx), } return asCLIAction(action) } func (a *ydbMigrateApplyAction) handle() error { ydbConn, err := a.getYDBConnection() if err != nil { return err } defer func() { errClose := ydbConn.Close() if errClose != nil { xcontext.LogError(a.ctx, a.log, "unable to close repository", slog.Any("error", err)) if err == nil { err = errClose } } }() repository := ydbConn.CourseRepository() err = repository.CreateCourseTable(a.ctx) if err != nil { return fmt.Errorf("creating course table: %w", err) } return nil } type ydbCoursesGetAction struct { *baseAction courseIDs []string } func newYDBCoursesGetAction(ctx context.Context) cli.Action { action := &ydbCoursesGetAction{ baseAction: newBaseAction(ctx), } return asCLIAction(action) } func (a *ydbCoursesGetAction) parse(params []string, options map[string]string) error { err := a.baseAction.parse(params, options) if err != nil { return err } if len(params) == 0 { return errors.NewValidationError("params", "no course ids provided") } a.courseIDs = make([]string, len(params)) copy(a.courseIDs, params) return nil } func (a *ydbCoursesGetAction) handle() error { ydbConn, err := a.getYDBConnection() if err != nil { return err } defer func() { errClose := ydbConn.Close() if errClose != nil { xcontext.LogError(a.ctx, a.log, "unable to close repository", slog.Any("error", err)) if err == nil { err = errClose } } }() repository := ydbConn.CourseRepository() for _, courseID := range a.courseIDs { course, err := repository.Get(a.ctx, courseID) if err != nil && !stderrors.Is(err, errors.ErrNotFound) { return fmt.Errorf("creating course table: %w", err) } else if stderrors.Is(err, errors.ErrNotFound) { xcontext.LogWarn(a.ctx, a.log, "course not found", slog.String("id", courseID)) continue } xcontext.LogInfo(a.ctx, a.log, "fetched course", slog.Any("item", course)) } return nil }