From 73ed8628671c1ad21733f70dafd7f175f3b25c94 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Tue, 20 Aug 2024 21:08:00 +0800 Subject: [PATCH 1/4] feat: add main sender and sms base sender --- .gitignore | 2 +- client/senderservice/sender_service.go | 12 +++--- generate/protobuf/service.proto | 8 ++-- go.mod | 10 +++++ internal/config/config.go | 12 ++++++ internal/domain/usecase/mail.go | 18 ++++++++ internal/domain/usecase/sms.go | 18 ++++++++ .../logic/senderservice/send_mail_logic.go | 37 ++++++++++++++++- .../logic/senderservice/send_sms_logic.go | 35 +++++++++++++++- .../senderservice/sender_service_server.go | 7 ++-- internal/svc/service_context.go | 16 +++++++- internal/usecase/mitake.go | 35 ++++++++++++++++ internal/usecase/smtp.go | 41 +++++++++++++++++++ 13 files changed, 232 insertions(+), 19 deletions(-) create mode 100644 internal/domain/usecase/mail.go create mode 100644 internal/domain/usecase/sms.go create mode 100644 internal/usecase/mitake.go create mode 100644 internal/usecase/smtp.go diff --git a/.gitignore b/.gitignore index 61a2d61..0a56a16 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ go.sum account/ gen_result/ etc/service.yaml -./client \ No newline at end of file +client/ \ No newline at end of file diff --git a/client/senderservice/sender_service.go b/client/senderservice/sender_service.go index a647688..33bcb18 100644 --- a/client/senderservice/sender_service.go +++ b/client/senderservice/sender_service.go @@ -22,11 +22,11 @@ type ( SenderService interface { // SendMail 寄信 SendMail(ctx context.Context, in *SendMailReq, opts ...grpc.CallOption) (*OKResp, error) - // SendSMS 寄簡訊 + // SendSms 寄簡訊 SendSms(ctx context.Context, in *SendSMSReq, opts ...grpc.CallOption) (*OKResp, error) - // SendMailByTemplateID 寄送模板信件 + // SendMailByTemplateId 寄送模板信件 SendMailByTemplateId(ctx context.Context, in *SendByTemplateIDReq, opts ...grpc.CallOption) (*OKResp, error) - // SendSMSByTemplateID 寄送模板簡訊 + // SendSmsByTemplateId 寄送模板簡訊 SendSmsByTemplateId(ctx context.Context, in *SendByTemplateIDReq, opts ...grpc.CallOption) (*OKResp, error) } @@ -47,19 +47,19 @@ func (m *defaultSenderService) SendMail(ctx context.Context, in *SendMailReq, op return client.SendMail(ctx, in, opts...) } -// SendSMS 寄簡訊 +// SendSms 寄簡訊 func (m *defaultSenderService) SendSms(ctx context.Context, in *SendSMSReq, opts ...grpc.CallOption) (*OKResp, error) { client := notification.NewSenderServiceClient(m.cli.Conn()) return client.SendSms(ctx, in, opts...) } -// SendMailByTemplateID 寄送模板信件 +// SendMailByTemplateId 寄送模板信件 func (m *defaultSenderService) SendMailByTemplateId(ctx context.Context, in *SendByTemplateIDReq, opts ...grpc.CallOption) (*OKResp, error) { client := notification.NewSenderServiceClient(m.cli.Conn()) return client.SendMailByTemplateId(ctx, in, opts...) } -// SendSMSByTemplateID 寄送模板簡訊 +// SendSmsByTemplateId 寄送模板簡訊 func (m *defaultSenderService) SendSmsByTemplateId(ctx context.Context, in *SendByTemplateIDReq, opts ...grpc.CallOption) (*OKResp, error) { client := notification.NewSenderServiceClient(m.cli.Conn()) return client.SendSmsByTemplateId(ctx, in, opts...) diff --git a/generate/protobuf/service.proto b/generate/protobuf/service.proto index 2d84dce..e3d5304 100644 --- a/generate/protobuf/service.proto +++ b/generate/protobuf/service.proto @@ -13,11 +13,13 @@ message SendMailReq { string to = 1; string subject = 2; string body = 3; + string from =4; } message SendSMSReq { string to = 1; string body = 2; + string recipient_name=3; } message SendByTemplateIDReq { @@ -31,11 +33,11 @@ message SendByTemplateIDReq { service SenderService { // SendMail 寄信 rpc SendMail(SendMailReq) returns(OKResp); - // SendSMS 寄簡訊 + // SendSms 寄簡訊 rpc SendSms(SendSMSReq) returns(OKResp); - // SendMailByTemplateID 寄送模板信件 + // SendMailByTemplateId 寄送模板信件 rpc SendMailByTemplateId(SendByTemplateIDReq) returns(OKResp); - // SendSMSByTemplateID 寄送模板簡訊 + // SendSmsByTemplateId 寄送模板簡訊 rpc SendSmsByTemplateId(SendByTemplateIDReq) returns(OKResp); } diff --git a/go.mod b/go.mod index a339282..eee482d 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,12 @@ go 1.22.3 require ( code.30cm.net/digimon/library-go/errors v1.0.0 + code.30cm.net/digimon/library-go/validator v1.0.0 + github.com/minchao/go-mitake v1.0.0 github.com/zeromicro/go-zero v1.7.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 + gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df ) require ( @@ -19,11 +22,15 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/fatih/color v1.17.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -34,6 +41,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -66,6 +74,7 @@ require ( go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/sys v0.22.0 // indirect @@ -74,6 +83,7 @@ require ( golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/internal/config/config.go b/internal/config/config.go index c1f85b9..3521805 100755 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,4 +4,16 @@ import "github.com/zeromicro/go-zero/zrpc" type Config struct { zrpc.RpcServerConf + + SMTP struct { + Host string + Port int + User string + Password string + } + + SMSSender struct { + User string + Password string + } } diff --git a/internal/domain/usecase/mail.go b/internal/domain/usecase/mail.go new file mode 100644 index 0000000..95fb400 --- /dev/null +++ b/internal/domain/usecase/mail.go @@ -0,0 +1,18 @@ +package usecase + +import "context" + +type MailClientUseCase interface { + SendMail(ctx context.Context, req MailReq) error +} + +type MailReq struct { + To string + From string + Subject string + Body string +} + +type MailUseCase interface { + GetMailTemplateByID(ctx context.Context, tid int64) ([]rune, error) +} diff --git a/internal/domain/usecase/sms.go b/internal/domain/usecase/sms.go new file mode 100644 index 0000000..c4e6d66 --- /dev/null +++ b/internal/domain/usecase/sms.go @@ -0,0 +1,18 @@ +package usecase + +import ( + "context" +) + +type SMSClientUseCase interface { + SendSMS(ctx context.Context, req SMSReq) error +} + +type SMSReq struct { + // RecipientAddress 接收者號碼 + RecipientAddress string + // RecipientName 接收者姓名 + RecipientName string + // Body 要傳送的訊息 + Body string +} diff --git a/internal/logic/senderservice/send_mail_logic.go b/internal/logic/senderservice/send_mail_logic.go index 6af7fc1..39ad124 100644 --- a/internal/logic/senderservice/send_mail_logic.go +++ b/internal/logic/senderservice/send_mail_logic.go @@ -1,6 +1,8 @@ package senderservicelogic import ( + "app-cloudep-notification-service/internal/domain/usecase" + ers "code.30cm.net/digimon/library-go/errors" "context" "app-cloudep-notification-service/gen_result/pb/notification" @@ -23,9 +25,42 @@ func NewSendMailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendMail } } +type sendMailReq struct { + // TO 收件者 + To string `validate:"required,email"` + // Subject 信件主旨 + Subject string `validate:"required,max=128"` + // Body 內容 + Body string `validate:"required"` + // From 寄件者 + From string `validate:"required"` +} + // SendMail 寄信 func (l *SendMailLogic) SendMail(in *notification.SendMailReq) (*notification.OKResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&sendMailReq{ + To: in.GetTo(), + Subject: in.GetSubject(), + Body: in.GetBody(), + From: in.GetFrom(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } + + err := l.svcCtx.MailSender.SendMail(l.ctx, usecase.MailReq{ + To: in.GetTo(), + Subject: in.GetSubject(), + From: in.GetFrom(), + Body: in.GetBody(), + }) + if err != nil { + logx.WithCallerSkip(1).WithFields( + logx.Field("func", "MailSender.SendMail"), + logx.Field("in", in), + logx.Field("err", err), + ).Error(err.Error()) + return nil, ers.ArkInternal("MailSender.SendMail failed to send mail") + } return ¬ification.OKResp{}, nil } diff --git a/internal/logic/senderservice/send_sms_logic.go b/internal/logic/senderservice/send_sms_logic.go index 7e5e4f9..152d890 100644 --- a/internal/logic/senderservice/send_sms_logic.go +++ b/internal/logic/senderservice/send_sms_logic.go @@ -1,6 +1,8 @@ package senderservicelogic import ( + "app-cloudep-notification-service/internal/domain/usecase" + ers "code.30cm.net/digimon/library-go/errors" "context" "app-cloudep-notification-service/gen_result/pb/notification" @@ -23,9 +25,38 @@ func NewSendSmsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SendSmsLo } } -// SendSMS 寄簡訊 +type sendSMSReq struct { + // RecipientAddress 收件者 + RecipientAddress string `validate:"required,phone"` + // Body 內容 + Body string `validate:"required"` + // RecipientName 收件者信名 + RecipientName string `validate:"required"` +} + +// SendSms 寄簡訊 func (l *SendSmsLogic) SendSms(in *notification.SendSMSReq) (*notification.OKResp, error) { - // todo: add your logic here and delete this line + if err := l.svcCtx.Validate.ValidateAll(&sendSMSReq{ + RecipientName: in.GetTo(), + Body: in.GetBody(), + RecipientAddress: in.GetTo(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } + + err := l.svcCtx.SMSSender.SendSMS(l.ctx, usecase.SMSReq{ + RecipientAddress: in.GetTo(), + RecipientName: in.GetRecipientName(), + Body: in.GetBody(), + }) + if err != nil { + logx.WithCallerSkip(1).WithFields( + logx.Field("func", "SMSSender.SendSMS"), + logx.Field("in", in), + logx.Field("err", err), + ).Error(err.Error()) + return nil, ers.ArkInternal("SMSSender.SendSMS failed to send sms") + } return ¬ification.OKResp{}, nil } diff --git a/internal/server/senderservice/sender_service_server.go b/internal/server/senderservice/sender_service_server.go index 14d51b9..7300421 100644 --- a/internal/server/senderservice/sender_service_server.go +++ b/internal/server/senderservice/sender_service_server.go @@ -7,7 +7,6 @@ import ( "context" "app-cloudep-notification-service/gen_result/pb/notification" - senderservicelogic "app-cloudep-notification-service/internal/logic/senderservice" "app-cloudep-notification-service/internal/logic/senderservice" "app-cloudep-notification-service/internal/svc" ) @@ -29,19 +28,19 @@ func (s *SenderServiceServer) SendMail(ctx context.Context, in *notification.Sen return l.SendMail(in) } -// SendSMS 寄簡訊 +// SendSms 寄簡訊 func (s *SenderServiceServer) SendSms(ctx context.Context, in *notification.SendSMSReq) (*notification.OKResp, error) { l := senderservicelogic.NewSendSmsLogic(ctx, s.svcCtx) return l.SendSms(in) } -// SendMailByTemplateID 寄送模板信件 +// SendMailByTemplateId 寄送模板信件 func (s *SenderServiceServer) SendMailByTemplateId(ctx context.Context, in *notification.SendByTemplateIDReq) (*notification.OKResp, error) { l := senderservicelogic.NewSendMailByTemplateIdLogic(ctx, s.svcCtx) return l.SendMailByTemplateId(in) } -// SendSMSByTemplateID 寄送模板簡訊 +// SendSmsByTemplateId 寄送模板簡訊 func (s *SenderServiceServer) SendSmsByTemplateId(ctx context.Context, in *notification.SendByTemplateIDReq) (*notification.OKResp, error) { l := senderservicelogic.NewSendSmsByTemplateIdLogic(ctx, s.svcCtx) return l.SendSmsByTemplateId(in) diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index d0f930f..09a29c1 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -1,13 +1,25 @@ package svc -import "app-cloudep-notification-service/internal/config" +import ( + "app-cloudep-notification-service/internal/config" + domainUC "app-cloudep-notification-service/internal/domain/usecase" + "app-cloudep-notification-service/internal/usecase" + v "code.30cm.net/digimon/library-go/validator" +) type ServiceContext struct { Config config.Config + + Validate v.Validate + MailSender domainUC.MailClientUseCase + SMSSender domainUC.SMSClientUseCase } func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ - Config: c, + Config: c, + MailSender: usecase.MustMailgunUseCase(usecase.MailUseCaseParam{Conf: c}), + SMSSender: usecase.MustMitakeUseCase(usecase.SMSUseCaseParam{Conf: c}), + Validate: v.MustValidator(), } } diff --git a/internal/usecase/mitake.go b/internal/usecase/mitake.go new file mode 100644 index 0000000..cd8e622 --- /dev/null +++ b/internal/usecase/mitake.go @@ -0,0 +1,35 @@ +package usecase + +import ( + "app-cloudep-notification-service/internal/config" + "app-cloudep-notification-service/internal/domain/usecase" + "context" + "github.com/minchao/go-mitake" +) + +type SMSUseCaseParam struct { + Conf config.Config +} + +type SMSUseCase struct { + Client *mitake.Client +} + +func (s *SMSUseCase) SendSMS(_ context.Context, req usecase.SMSReq) error { + message := mitake.Message{ + Dstaddr: req.RecipientAddress, + Destname: req.RecipientName, + Smbody: req.Body, + } + _, err := s.Client.Send(message) + if err != nil { + return err + } + return nil +} + +func MustMitakeUseCase(param SMSUseCaseParam) usecase.SMSClientUseCase { + return &SMSUseCase{ + Client: mitake.NewClient(param.Conf.SMSSender.User, param.Conf.SMSSender.Password, nil), + } +} diff --git a/internal/usecase/smtp.go b/internal/usecase/smtp.go new file mode 100644 index 0000000..9a10771 --- /dev/null +++ b/internal/usecase/smtp.go @@ -0,0 +1,41 @@ +package usecase + +import ( + "app-cloudep-notification-service/internal/config" + "app-cloudep-notification-service/internal/domain/usecase" + "context" + "gopkg.in/gomail.v2" +) + +type MailUseCaseParam struct { + Conf config.Config +} + +type MailUseCase struct { + Host string + Port int + User string + Password string +} + +func (mu *MailUseCase) SendMail(_ context.Context, req usecase.MailReq) error { + m := gomail.NewMessage() + m.SetHeader("From", req.From) + m.SetHeader("To", req.To) + m.SetHeader("Subject", req.Subject) + m.SetBody("text/html", req.Body) + d := gomail.NewDialer(mu.Host, mu.Port, mu.User, mu.Password) + if err := d.DialAndSend(m); err != nil { + return err + } + return nil +} + +func MustMailgunUseCase(param MailUseCaseParam) usecase.MailClientUseCase { + return &MailUseCase{ + Host: param.Conf.SMTP.Host, + Port: param.Conf.SMTP.Port, + User: param.Conf.SMTP.User, + Password: param.Conf.SMTP.Password, + } +} From cef8a172e609ca2b6f98842ecd7190372bcfa104 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Tue, 20 Aug 2024 23:53:20 +0800 Subject: [PATCH 2/4] feat: add worker_pool --- .golangci.yaml | 140 ++++++++++++++++++ etc/service.yaml | 10 ++ go.mod | 3 + .../send_mail_by_template_id_logic.go | 3 +- .../logic/senderservice/send_mail_logic.go | 4 +- .../logic/senderservice/send_sms_logic.go | 4 +- .../senderservice/sender_service_server.go | 2 +- internal/svc/service_context.go | 1 + internal/usecase/mitake.go | 1 + internal/usecase/smtp.go | 35 +++-- 10 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 .golangci.yaml diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..5518484 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,140 @@ +run: + timeout: 3m + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + # Include test files or not. + # Default: true + tests: false + +# Reference URL: https://golangci-lint.run/usage/linters/ +linters: + # Disable everything by default so upgrades to not include new - default + # enabled- linters. + disable-all: true + # Specifically enable linters we want to use. + enable: + # - depguard + - errcheck + # - godot + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - misspell + - revive + # - staticcheck + - typecheck + - unused + # - wsl + - asasalint + - asciicheck + - bidichk + - bodyclose + # - containedctx + - contextcheck + # - cyclop + # - varnamelen + # - gci + - wastedassign + - whitespace + # - wrapcheck + - thelper + - tparallel + - unconvert + - unparam + - usestdlibvars + - tenv + - testableexamples + - stylecheck + - sqlclosecheck + - nosprintfhostport + - paralleltest + - prealloc + - predeclared + - promlinter + - reassign + - rowserrcheck + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - decorder + - dogsled + # - dupl + - dupword + - durationcheck + - errchkjson + - errname + - errorlint + # - execinquery + - exhaustive + - exportloopref + - forbidigo + - forcetypeassert + # - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + # - godox + # - goerr113 + # - gofumpt + - goheader + - gomoddirectives + # - gomodguard always failed + - goprintffuncname + - gosec + - grouper + - importas + - interfacebloat + # - ireturn + - lll + - loggercheck + - maintidx + - makezero + +issues: + exclude-rules: + - path: _test\.go + linters: + - funlen + - goconst + - interfacer + - dupl + - lll + - goerr113 + - errcheck + - gocritic + - cyclop + - wrapcheck + - gocognit + - contextcheck + +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 40 + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 10 + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 200 + # Tab width in spaces. + # Default: 1 + tab-width: 1 diff --git a/etc/service.yaml b/etc/service.yaml index f9a189a..319ba6f 100644 --- a/etc/service.yaml +++ b/etc/service.yaml @@ -4,3 +4,13 @@ Etcd: Hosts: - 127.0.0.1:2379 Key: service.rpc +SMTP: + Host: smtp.mailgun.org + Port: 25 + User: postmaster@code.30cm.net + Password: 9015592e10f385e4f16705e00a5e0d3d-2b91eb47-31205b4e + +SMSSender: + User: daniel@30cm.net + Password : test123 + diff --git a/go.mod b/go.mod index eee482d..f983540 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.3 require ( code.30cm.net/digimon/library-go/errors v1.0.0 code.30cm.net/digimon/library-go/validator v1.0.0 + code.30cm.net/digimon/library-go/worker_pool v0.0.0-20240820153352-f9c90a90f5e2 github.com/minchao/go-mitake v1.0.0 github.com/zeromicro/go-zero v1.7.0 google.golang.org/grpc v1.65.0 @@ -49,6 +50,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/panjf2000/ants/v2 v2.10.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.5.0 // indirect @@ -77,6 +79,7 @@ require ( golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect diff --git a/internal/logic/senderservice/send_mail_by_template_id_logic.go b/internal/logic/senderservice/send_mail_by_template_id_logic.go index abf4b49..b9decc9 100644 --- a/internal/logic/senderservice/send_mail_by_template_id_logic.go +++ b/internal/logic/senderservice/send_mail_by_template_id_logic.go @@ -3,9 +3,10 @@ package senderservicelogic import ( "app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/internal/svc" - ers "code.30cm.net/digimon/library-go/errors" "context" "fmt" + + ers "code.30cm.net/digimon/library-go/errors" "github.com/zeromicro/go-zero/core/logx" ) diff --git a/internal/logic/senderservice/send_mail_logic.go b/internal/logic/senderservice/send_mail_logic.go index 39ad124..c7aa930 100644 --- a/internal/logic/senderservice/send_mail_logic.go +++ b/internal/logic/senderservice/send_mail_logic.go @@ -2,9 +2,10 @@ package senderservicelogic import ( "app-cloudep-notification-service/internal/domain/usecase" - ers "code.30cm.net/digimon/library-go/errors" "context" + ers "code.30cm.net/digimon/library-go/errors" + "app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/internal/svc" @@ -47,6 +48,7 @@ func (l *SendMailLogic) SendMail(in *notification.SendMailReq) (*notification.OK return nil, ers.InvalidFormat(err.Error()) } + // TODO 以後可以做換線 err := l.svcCtx.MailSender.SendMail(l.ctx, usecase.MailReq{ To: in.GetTo(), Subject: in.GetSubject(), diff --git a/internal/logic/senderservice/send_sms_logic.go b/internal/logic/senderservice/send_sms_logic.go index 152d890..83d79fa 100644 --- a/internal/logic/senderservice/send_sms_logic.go +++ b/internal/logic/senderservice/send_sms_logic.go @@ -2,9 +2,10 @@ package senderservicelogic import ( "app-cloudep-notification-service/internal/domain/usecase" - ers "code.30cm.net/digimon/library-go/errors" "context" + ers "code.30cm.net/digimon/library-go/errors" + "app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/internal/svc" @@ -44,6 +45,7 @@ func (l *SendSmsLogic) SendSms(in *notification.SendSMSReq) (*notification.OKRes return nil, ers.InvalidFormat(err.Error()) } + // TODO 以後可以做換線 err := l.svcCtx.SMSSender.SendSMS(l.ctx, usecase.SMSReq{ RecipientAddress: in.GetTo(), RecipientName: in.GetRecipientName(), diff --git a/internal/server/senderservice/sender_service_server.go b/internal/server/senderservice/sender_service_server.go index 7300421..99f6d32 100644 --- a/internal/server/senderservice/sender_service_server.go +++ b/internal/server/senderservice/sender_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-notification-service/gen_result/pb/notification" - "app-cloudep-notification-service/internal/logic/senderservice" + senderservicelogic "app-cloudep-notification-service/internal/logic/senderservice" "app-cloudep-notification-service/internal/svc" ) diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 09a29c1..7ce53b9 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -4,6 +4,7 @@ import ( "app-cloudep-notification-service/internal/config" domainUC "app-cloudep-notification-service/internal/domain/usecase" "app-cloudep-notification-service/internal/usecase" + v "code.30cm.net/digimon/library-go/validator" ) diff --git a/internal/usecase/mitake.go b/internal/usecase/mitake.go index cd8e622..ac332bc 100644 --- a/internal/usecase/mitake.go +++ b/internal/usecase/mitake.go @@ -4,6 +4,7 @@ import ( "app-cloudep-notification-service/internal/config" "app-cloudep-notification-service/internal/domain/usecase" "context" + "github.com/minchao/go-mitake" ) diff --git a/internal/usecase/smtp.go b/internal/usecase/smtp.go index 9a10771..f4d97e7 100644 --- a/internal/usecase/smtp.go +++ b/internal/usecase/smtp.go @@ -3,7 +3,12 @@ package usecase import ( "app-cloudep-notification-service/internal/config" "app-cloudep-notification-service/internal/domain/usecase" + + pool "code.30cm.net/digimon/library-go/worker_pool" + "github.com/zeromicro/go-zero/core/logx" + "context" + "gopkg.in/gomail.v2" ) @@ -16,19 +21,28 @@ type MailUseCase struct { Port int User string Password string + Pool pool.WorkerPool } func (mu *MailUseCase) SendMail(_ context.Context, req usecase.MailReq) error { - m := gomail.NewMessage() - m.SetHeader("From", req.From) - m.SetHeader("To", req.To) - m.SetHeader("Subject", req.Subject) - m.SetBody("text/html", req.Body) - d := gomail.NewDialer(mu.Host, mu.Port, mu.User, mu.Password) - if err := d.DialAndSend(m); err != nil { - return err - } - return nil + // 用 goroutine pool 送,否則會超時 + err := mu.Pool.Submit(func() { + m := gomail.NewMessage() + m.SetHeader("From", req.From) + m.SetHeader("To", req.To) + m.SetHeader("Subject", req.Subject) + m.SetBody("text/html", req.Body) + d := gomail.NewDialer(mu.Host, mu.Port, mu.User, mu.Password) + if err := d.DialAndSend(m); err != nil { + logx.WithCallerSkip(1).WithFields( + logx.Field("func", "MailUseCase.SendMail"), + logx.Field("req", req), + logx.Field("err", err), + ).Error("failed to send mail by mailgun") + } + }) + + return err } func MustMailgunUseCase(param MailUseCaseParam) usecase.MailClientUseCase { @@ -37,5 +51,6 @@ func MustMailgunUseCase(param MailUseCaseParam) usecase.MailClientUseCase { Port: param.Conf.SMTP.Port, User: param.Conf.SMTP.User, Password: param.Conf.SMTP.Password, + Pool: pool.NewWorkerPool(2000), } } From 44e736daabe6d19ed3769fb3c791e9f47ebb4bc7 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Tue, 20 Aug 2024 23:55:09 +0800 Subject: [PATCH 3/4] feat: add worker_pool --- etc/{service.yaml => service.example.yaml} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename etc/{service.yaml => service.example.yaml} (66%) diff --git a/etc/service.yaml b/etc/service.example.yaml similarity index 66% rename from etc/service.yaml rename to etc/service.example.yaml index 319ba6f..9474363 100644 --- a/etc/service.yaml +++ b/etc/service.example.yaml @@ -7,8 +7,8 @@ Etcd: SMTP: Host: smtp.mailgun.org Port: 25 - User: postmaster@code.30cm.net - Password: 9015592e10f385e4f16705e00a5e0d3d-2b91eb47-31205b4e + User: xxx + Password: 000 SMSSender: User: daniel@30cm.net From 5b9355c4e9154f085dbafcd7ffe493a4b14f432b Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Mon, 26 Aug 2024 16:34:16 +0800 Subject: [PATCH 4/4] add checkout verify code --- .gitignore | 5 +++-- Makefile | 2 +- client/senderservice/sender_service.go | 2 +- etc/service.yaml | 16 ++++++++++++++++ .../{service.proto => notification.proto} | 0 .../senderservice/sender_service_server.go | 4 ++-- service.go => notification.go | 2 +- 7 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 etc/service.yaml rename generate/protobuf/{service.proto => notification.proto} (100%) rename service.go => notification.go (92%) diff --git a/.gitignore b/.gitignore index 0a56a16..ca060ca 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ go.sum account/ gen_result/ -etc/service.yaml -client/ \ No newline at end of file +etc/notification.yaml +client/ +.DS_Store \ No newline at end of file diff --git a/Makefile b/Makefile index 1d51c21..785dc15 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ fmt: # 格式優化 .PHONY: gen-rpc gen-rpc: # 建立 rpc code - $(GO_CTL_NAME) rpc protoc ./generate/protobuf/service.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. + $(GO_CTL_NAME) rpc protoc ./generate/protobuf/notification.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=. copy ./etc/service.yaml ./etc/service.example.yaml go mod tidy @echo "Generate core-api files successfully" diff --git a/client/senderservice/sender_service.go b/client/senderservice/sender_service.go index 33bcb18..bbc3d18 100644 --- a/client/senderservice/sender_service.go +++ b/client/senderservice/sender_service.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// Source: service.proto +// Source: notification.proto package senderservice diff --git a/etc/service.yaml b/etc/service.yaml new file mode 100644 index 0000000..319ba6f --- /dev/null +++ b/etc/service.yaml @@ -0,0 +1,16 @@ +Name: service.rpc +ListenOn: 0.0.0.0:8080 +Etcd: + Hosts: + - 127.0.0.1:2379 + Key: service.rpc +SMTP: + Host: smtp.mailgun.org + Port: 25 + User: postmaster@code.30cm.net + Password: 9015592e10f385e4f16705e00a5e0d3d-2b91eb47-31205b4e + +SMSSender: + User: daniel@30cm.net + Password : test123 + diff --git a/generate/protobuf/service.proto b/generate/protobuf/notification.proto similarity index 100% rename from generate/protobuf/service.proto rename to generate/protobuf/notification.proto diff --git a/internal/server/senderservice/sender_service_server.go b/internal/server/senderservice/sender_service_server.go index 99f6d32..6e9e1a1 100644 --- a/internal/server/senderservice/sender_service_server.go +++ b/internal/server/senderservice/sender_service_server.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// Source: service.proto +// Source: notification.proto package server @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-notification-service/gen_result/pb/notification" - senderservicelogic "app-cloudep-notification-service/internal/logic/senderservice" + "app-cloudep-notification-service/internal/logic/senderservice" "app-cloudep-notification-service/internal/svc" ) diff --git a/service.go b/notification.go similarity index 92% rename from service.go rename to notification.go index e202e4e..b35a92c 100644 --- a/service.go +++ b/notification.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/reflection" ) -var configFile = flag.String("f", "etc/service.yaml", "the config file") +var configFile = flag.String("f", "etc/notification.yaml", "the config file") func main() { flag.Parse()