Compare commits
No commits in common. "main" and "feature/mail" have entirely different histories.
main
...
feature/ma
90
README.md
90
README.md
|
@ -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
|
|
||||||
```
|
|
|
@ -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"]
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
2
go.mod
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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 ¬ification.OKResp{}, nil
|
return ¬ification.OKResp{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ¬ification.OKResp{}, nil
|
return ¬ification.OKResp{}, nil
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 ¬ification.OKResp{}, nil
|
return ¬ification.OKResp{}, nil
|
||||||
|
|
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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}),
|
||||||
|
|
Loading…
Reference in New Issue