diff --git a/cmd/new.go b/cmd/new.go index 8911b1a..c30f61e 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -16,6 +16,7 @@ func CommandInit(root *cobra.Command) { CommandNewProject, CommandNewModule, CommandNewProvider, + CommandNewEvent, } for _, c := range cmds { diff --git a/cmd/new_event.go b/cmd/new_event.go new file mode 100644 index 0000000..45caa74 --- /dev/null +++ b/cmd/new_event.go @@ -0,0 +1,107 @@ +package cmd + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "text/template" + + "git.ipao.vip/rogeecn/atomctl/pkg/utils/gomod" + "git.ipao.vip/rogeecn/atomctl/templates" + "github.com/samber/lo" + "github.com/spf13/cobra" +) + +// CommandNewProvider 注册 new_provider 命令 +func CommandNewEvent(root *cobra.Command) { + cmd := &cobra.Command{ + Use: "event", + Aliases: []string{"e"}, + Short: "创建新的 event publish & subscriber", + Args: cobra.ExactArgs(1), + RunE: commandNewEventE, + } + + root.AddCommand(cmd) +} + +func commandNewEventE(cmd *cobra.Command, args []string) error { + snakeName := lo.SnakeCase(args[0]) + camelName := lo.PascalCase(args[0]) + + publisherPath := "app/events/publishers" + subscriberPath := "app/events/subscribers" + + path, err := os.Getwd() + if err != nil { + return err + } + + path, _ = filepath.Abs(path) + err = gomod.Parse(filepath.Join(path, "go.mod")) + if err != nil { + return err + } + + if err := os.MkdirAll(publisherPath, os.ModePerm); err != nil { + return err + } + + if err := os.MkdirAll(subscriberPath, os.ModePerm); err != nil { + return err + } + + err = fs.WalkDir(templates.Events, "events", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + + relPath, err := filepath.Rel("events", path) + if err != nil { + return err + } + + var destPath string + if relPath == "publisher.go.tpl" { + destPath = filepath.Join(publisherPath, snakeName+".go") + } else if relPath == "subscriber.go.tpl" { + destPath = filepath.Join(subscriberPath, snakeName+".go") + } + + tmpl, err := template.ParseFS(templates.Events, path) + if err != nil { + return err + } + + destFile, err := os.Create(destPath) + if err != nil { + return err + } + defer destFile.Close() + + return tmpl.Execute(destFile, map[string]string{ + "Name": camelName, + "ModuleName": gomod.GetModuleName(), + }) + }) + + topicStr := fmt.Sprintf("const Topic%s = %q\n", camelName, snakeName) + // 写入到 app/events/topic.go + topicFile, err := os.OpenFile("app/events/topics.go", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + return err + } + defer topicFile.Close() + + _, err = topicFile.WriteString(topicStr) + if err != nil { + return err + } + + fmt.Printf("event 已创建: %s\n", snakeName) + return nil +} diff --git a/templates/events/publisher.go.tpl b/templates/events/publisher.go.tpl new file mode 100644 index 0000000..12f8a1f --- /dev/null +++ b/templates/events/publisher.go.tpl @@ -0,0 +1,23 @@ +package publishers + +import ( + "encoding/json" + + "{{.ModuleName}}/app/events" + + "git.ipao.vip/rogeecn/atom/contracts" +) + +var _ contracts.EventPublisher = (*{{.Name}}Event)(nil) + +type {{.Name}}Event struct { + ID int64 `json:"id"` +} + +func (e *{{.Name}}Event) Marshal() ([]byte, error) { + return json.Marshal(e) +} + +func (e *{{.Name}}Event) Topic() string { + return events.Topic{{.Name}} +} diff --git a/templates/events/subscriber.go.tpl b/templates/events/subscriber.go.tpl new file mode 100644 index 0000000..2323b47 --- /dev/null +++ b/templates/events/subscriber.go.tpl @@ -0,0 +1,48 @@ +package subscribers + +import ( + "encoding/json" + + "{{.ModuleName}}/app/events" + "{{.ModuleName}}/app/events/publishers" + + "git.ipao.vip/rogeecn/atom/contracts" + "github.com/ThreeDotsLabs/watermill/message" + "github.com/sirupsen/logrus" +) + +var _ contracts.EventHandler = (*{{.Name}}Subscriber)(nil) + +// @provider(event) +type {{.Name}}Subscriber struct { + log *logrus.Entry `inject:"false"` +} + +func (e *{{.Name}}Subscriber) Prepare() error { + e.log = logrus.WithField("module", "events.subscribers.{{.Name}}Subscriber") + return nil +} + +// PublishToTopic implements contracts.EventHandler. +func (e *{{.Name}}Subscriber) PublishToTopic() string { + return events.TopicProcessed +} + +// Topic implements contracts.EventHandler. +func (e *{{.Name}}Subscriber) Topic() string { + return events.Topic{{.Name}} +} + +// Handler implements contracts.EventHandler. +func (e *{{.Name}}Subscriber) Handler(msg *message.Message) ([]*message.Message, error) { + var payload publishers.{{.Name}}Event + err := json.Unmarshal(msg.Payload, &payload) + if err != nil { + return nil, err + } + e.log.Infof("received event %s", msg.Payload) + + // TODO: handle post deletion + + return nil, nil +} diff --git a/templates/project/app/events/event_demo.go.tpl b/templates/project/app/events/event_demo.go.tpl deleted file mode 100644 index 35a9f75..0000000 --- a/templates/project/app/events/event_demo.go.tpl +++ /dev/null @@ -1,52 +0,0 @@ -package events - -import ( - "encoding/json" - - "git.ipao.vip/rogeecn/atom/contracts" - "github.com/ThreeDotsLabs/watermill/message" - "github.com/sirupsen/logrus" -) - -var ( - _ contracts.EventHandler = (*UserRegister)(nil) - _ contracts.EventPublisher = (*UserRegister)(nil) -) - -// @provider(event) -type UserRegister struct { - log *logrus.Entry `inject:"false" json:"-"` - ID int64 `json:"id"` -} - -func (e *UserRegister) Prepare() error { - return nil -} - -// Marshal implements contracts.EventPublisher. -func (e *UserRegister) Marshal() ([]byte, error) { - return json.Marshal(e) -} - -// PublishToTopic implements contracts.EventHandler. -func (e *UserRegister) PublishToTopic() string { - return TopicProcessed.String() -} - -// Topic implements contracts.EventHandler. -func (e *UserRegister) Topic() string { - return TopicUserRegister.String() -} - -// Handler implements contracts.EventHandler. -func (e *UserRegister) Handler(msg *message.Message) ([]*message.Message, error) { - var payload UserRegister - err := json.Unmarshal(msg.Payload, &payload) - if err != nil { - return nil, err - } - - e.log.Infof("received event %+v\n", payload) - - return nil, nil -} diff --git a/templates/project/app/events/topics.go.tpl b/templates/project/app/events/topics.go.tpl index bf9c96a..059cd0f 100644 --- a/templates/project/app/events/topics.go.tpl +++ b/templates/project/app/events/topics.go.tpl @@ -1,10 +1,5 @@ package events -// swagger:enum Topic -// ENUM( -// -// Processed = "event:processed" -// UserRegister = "user:register" -// -// ) -type Topic string +const ( + TopicProcessed = "event:processed" +) diff --git a/templates/templates.go b/templates/templates.go index 79413b0..c388b18 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -10,3 +10,6 @@ var Module embed.FS //go:embed provider var Provider embed.FS + +//go:embed events +var Events embed.FS