Compare commits

..

No commits in common. "main" and "feature/mail" have entirely different histories.

13 changed files with 50 additions and 192 deletions

View File

@ -1,90 +0,0 @@
# 專案說明
通知服務
# 專案架構
```
$tree -L 3 --gitignore
.
├── Makefile
├── build
│ └── Dockerfile
├── chart
│ └── readme.md
├── etc
│ └── service.example.yaml # 設定檔範例
├── generate # 這個資料夾會用來自動生成一些程式
│ ├── database ## 資料庫生成檔案或紀錄遷移版本
│ │ ├── mongodb
│ │ ├── mysql
│ │ ├── readme.md
│ │ └── seeder
│ └── protobuf ## gRPC 的定義,用來生成 gRPC 檔案
│ └── notification.proto
├── go.mod
├── internal
│ ├── config # 設定的結構
│ │ └── config.go
│ ├── domain # 此服務下的一些常數定義
│ │ ├── errors.go ## 錯誤定義
│ │ └── usecase ## usecase 內的常數定義
│ │ ├── mail.go
│ │ └── sms.go
│ ├── logic # 主要的程式邏輯都在這,每個功能用一個資料夾開發
│ │ └── senderservice
│ ├── server
│ │ └── senderservice # gRPC 自動產生的檔案
│ ├── svc # 此服務下會共用的功能,例如 API context, db 連線等
│ │ └── service_context.go ## API context
│ └── usecase
│ ├── mitake.go
│ └── smtp.go
└── notification.go # 服務主入口
```
# 啟動說明
此文件會介紹以下兩種啟動方式:
1. Docker 啟動 (Production 時使用)
2. 本地端 go compiler 啟動 (開發、測試時使用)
## Docker 啟動 (Production)
```bash
make build-docker
make run-docker
```
## 本地端啟動(測試用)
```bash
go mod tidy
# 進入 etc/notification.yml 設定各依賴的 config
go run notification.go
```
### 本地啟動需要依賴套件或工具
以下已 macOS 為例,若已安裝或有其他可用服務則可跳過
- go-zero goctl (https://go-zero.dev/docs/tasks/installation/goctl)
```bash
$ go install github.com/zeromicro/go-zero/tools/goctl@latest
```
- protobuf (https://protobuf.dev/)
```bash
brew install protobuf
```
- etcd (https://etcd.io/)
```bash
brew install etcd
brew services start etcd
```
- SMTP 服務(以 mailhog 為例) (https://github.com/mailhog/MailHog)
```bash
brew install mailhog
brew services start mailhog
```

View File

@ -32,7 +32,7 @@ RUN --mount=type=ssh go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags "$FLAG" \ -ldflags "$FLAG" \
-o notification -o service
########## ##########
## FINAL # ## FINAL #
@ -44,4 +44,4 @@ WORKDIR /app
COPY --from=builder /app/service /app/service COPY --from=builder /app/service /app/service
COPY --from=builder /app/etc/service.yaml /app/etc/service.yaml COPY --from=builder /app/etc/service.yaml /app/etc/service.yaml
EXPOSE 8080 EXPOSE 8080
CMD ["/app/notification"] CMD ["/app/service"]

View File

@ -1,16 +1,16 @@
Name: notification.rpc Name: service.rpc
ListenOn: 0.0.0.0:8003 ListenOn: 0.0.0.0:8080
Etcd: Etcd:
Hosts: Hosts:
- 127.0.0.1:2379 - 127.0.0.1:2379
Key: notification.rpc Key: service.rpc
SMTP: SMTP:
Host: smtp.mail.host Host: smtp.mailgun.org
Port: 25 Port: 25
User: smtp@user.net User: xxx
Password: smtp_password Password: 000
SMSSender: SMSSender:
User: sms@user.net User: daniel@30cm.net
Password : sms_password Password : test123

16
etc/service.yaml Normal file
View File

@ -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

2
go.mod
View File

@ -3,7 +3,7 @@ module app-cloudep-notification-service
go 1.22.3 go 1.22.3
require ( require (
code.30cm.net/digimon/library-go/errs v1.2.3 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/validator v1.0.0
code.30cm.net/digimon/library-go/worker_pool v0.0.0-20240820153352-f9c90a90f5e2 code.30cm.net/digimon/library-go/worker_pool v0.0.0-20240820153352-f9c90a90f5e2
github.com/minchao/go-mitake v1.0.0 github.com/minchao/go-mitake v1.0.0

View File

@ -1,58 +0,0 @@
package domain
import (
"fmt"
"strings"
"code.30cm.net/digimon/library-go/errs"
"code.30cm.net/digimon/library-go/errs/code"
"github.com/zeromicro/go-zero/core/logx"
)
type ErrorCode uint32
func (e ErrorCode) ToUint32() uint32 {
return uint32(e)
}
const (
_ = iota
SendMailErrorCode ErrorCode = iota
SendSMSErrorCode
)
// SendMailError ...
func SendMailError(s ...string) *errs.LibError {
return errs.NewError(code.CloudEPNotification, code.ThirdParty,
SendMailErrorCode.ToUint32(),
fmt.Sprintf("%s", strings.Join(s, " ")))
}
// SendMailErrorL logs error message and returns Err
func SendMailErrorL(l logx.Logger, filed []logx.LogField, s ...string) *errs.LibError {
e := SendMailError(s...)
if filed != nil || len(filed) >= 0 {
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
}
l.WithCallerSkip(1).Error(e.Error())
return e
}
// SendSMSError ...
func SendSMSError(s ...string) *errs.LibError {
return errs.NewError(code.CloudEPNotification, code.ThirdParty,
SendSMSErrorCode.ToUint32(),
fmt.Sprintf("%s", strings.Join(s, " ")))
}
// SendSMSErrorL logs error message and returns Err
func SendSMSErrorL(l logx.Logger, filed []logx.LogField, s ...string) *errs.LibError {
e := SendSMSError(s...)
if filed != nil || len(filed) >= 0 {
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
}
l.WithCallerSkip(1).Error(e.Error())
return e
}

View File

@ -4,7 +4,9 @@ import (
"app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/gen_result/pb/notification"
"app-cloudep-notification-service/internal/svc" "app-cloudep-notification-service/internal/svc"
"context" "context"
"fmt"
ers "code.30cm.net/digimon/library-go/errors"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -24,6 +26,7 @@ func NewSendMailByTemplateIdLogic(ctx context.Context, svcCtx *svc.ServiceContex
// SendMailByTemplateId 寄送模板信件 // SendMailByTemplateId 寄送模板信件
func (l *SendMailByTemplateIdLogic) SendMailByTemplateId(in *notification.SendByTemplateIDReq) (*notification.OKResp, error) { func (l *SendMailByTemplateIdLogic) SendMailByTemplateId(in *notification.SendByTemplateIDReq) (*notification.OKResp, error) {
fmt.Println(ers.ResourceNotFound("testing"))
return &notification.OKResp{}, nil return &notification.OKResp{}, nil
} }

View File

@ -1,11 +1,10 @@
package senderservicelogic package senderservicelogic
import ( import (
"app-cloudep-notification-service/internal/domain"
"app-cloudep-notification-service/internal/domain/usecase" "app-cloudep-notification-service/internal/domain/usecase"
"context" "context"
ers "code.30cm.net/digimon/library-go/errs" ers "code.30cm.net/digimon/library-go/errors"
"app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/gen_result/pb/notification"
"app-cloudep-notification-service/internal/svc" "app-cloudep-notification-service/internal/svc"
@ -46,7 +45,7 @@ func (l *SendMailLogic) SendMail(in *notification.SendMailReq) (*notification.OK
Body: in.GetBody(), Body: in.GetBody(),
From: in.GetFrom(), From: in.GetFrom(),
}); err != nil { }); err != nil {
return nil, ers.InvalidFormat("invalid format") return nil, ers.InvalidFormat(err.Error())
} }
// TODO 以後可以做換線 // TODO 以後可以做換線
@ -57,15 +56,12 @@ func (l *SendMailLogic) SendMail(in *notification.SendMailReq) (*notification.OK
Body: in.GetBody(), Body: in.GetBody(),
}) })
if err != nil { if err != nil {
return nil, domain.SendMailErrorL( logx.WithCallerSkip(1).WithFields(
logx.WithContext(l.ctx),
[]logx.LogField{
logx.Field("func", "MailSender.SendMail"), logx.Field("func", "MailSender.SendMail"),
logx.Field("in", in), logx.Field("in", in),
logx.Field("err", err), logx.Field("err", err),
}, ).Error(err.Error())
"MailSender.SendMail failed to send mail", return nil, ers.ArkInternal("MailSender.SendMail failed to send mail")
)
} }
return &notification.OKResp{}, nil return &notification.OKResp{}, nil

View File

@ -23,7 +23,7 @@ func NewSendSmsByTemplateIdLogic(ctx context.Context, svcCtx *svc.ServiceContext
} }
} }
// SendSmsByTemplateId 寄送模板簡訊 // SendSMSByTemplateID 寄送模板簡訊
func (l *SendSmsByTemplateIdLogic) SendSmsByTemplateId(in *notification.SendByTemplateIDReq) (*notification.OKResp, error) { func (l *SendSmsByTemplateIdLogic) SendSmsByTemplateId(in *notification.SendByTemplateIDReq) (*notification.OKResp, error) {
// todo: add your logic here and delete this line // todo: add your logic here and delete this line

View File

@ -1,11 +1,10 @@
package senderservicelogic package senderservicelogic
import ( import (
"app-cloudep-notification-service/internal/domain"
"app-cloudep-notification-service/internal/domain/usecase" "app-cloudep-notification-service/internal/domain/usecase"
"context" "context"
"code.30cm.net/digimon/library-go/errs" ers "code.30cm.net/digimon/library-go/errors"
"app-cloudep-notification-service/gen_result/pb/notification" "app-cloudep-notification-service/gen_result/pb/notification"
"app-cloudep-notification-service/internal/svc" "app-cloudep-notification-service/internal/svc"
@ -43,7 +42,7 @@ func (l *SendSmsLogic) SendSms(in *notification.SendSMSReq) (*notification.OKRes
Body: in.GetBody(), Body: in.GetBody(),
RecipientAddress: in.GetTo(), RecipientAddress: in.GetTo(),
}); err != nil { }); err != nil {
return nil, errs.InvalidFormat(err.Error()) return nil, ers.InvalidFormat(err.Error())
} }
// TODO 以後可以做換線 // TODO 以後可以做換線
@ -53,15 +52,12 @@ func (l *SendSmsLogic) SendSms(in *notification.SendSMSReq) (*notification.OKRes
Body: in.GetBody(), Body: in.GetBody(),
}) })
if err != nil { if err != nil {
return nil, domain.SendSMSErrorL( logx.WithCallerSkip(1).WithFields(
logx.WithContext(l.ctx),
[]logx.LogField{
logx.Field("func", "SMSSender.SendSMS"), logx.Field("func", "SMSSender.SendSMS"),
logx.Field("in", in), logx.Field("in", in),
logx.Field("err", err), logx.Field("err", err),
}, ).Error(err.Error())
"SMSSender.SendSMS failed to send sms", return nil, ers.ArkInternal("SMSSender.SendSMS failed to send sms")
)
} }
return &notification.OKResp{}, nil return &notification.OKResp{}, nil

View File

@ -7,8 +7,7 @@ import (
"context" "context"
"app-cloudep-notification-service/gen_result/pb/notification" "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" "app-cloudep-notification-service/internal/svc"
) )

View File

@ -5,9 +5,6 @@ import (
domainUC "app-cloudep-notification-service/internal/domain/usecase" domainUC "app-cloudep-notification-service/internal/domain/usecase"
"app-cloudep-notification-service/internal/usecase" "app-cloudep-notification-service/internal/usecase"
"code.30cm.net/digimon/library-go/errs"
"code.30cm.net/digimon/library-go/errs/code"
v "code.30cm.net/digimon/library-go/validator" v "code.30cm.net/digimon/library-go/validator"
) )
@ -20,7 +17,6 @@ type ServiceContext struct {
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
errs.Scope = code.CloudEPNotification
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
MailSender: usecase.MustMailgunUseCase(usecase.MailUseCaseParam{Conf: c}), MailSender: usecase.MustMailgunUseCase(usecase.MailUseCaseParam{Conf: c}),