129 lines
3.7 KiB
Go
129 lines
3.7 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
"errors"
|
||
"log"
|
||
"net"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"syscall"
|
||
"time"
|
||
|
||
_ "github.com/go-sql-driver/mysql"
|
||
"google.golang.org/grpc"
|
||
"google.golang.org/grpc/reflection"
|
||
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/api/pb"
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/internal/grpcapi"
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/internal/httpapi"
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/internal/sms"
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/internal/sms/aliyun"
|
||
"git.5iot.com/iotlcm-public/iotlcm-sms/internal/sms/tencent"
|
||
)
|
||
|
||
// 构建时通过 -ldflags 注入。
|
||
var (
|
||
BuildVersion = "0.0"
|
||
BuildTime = ""
|
||
CommitID = ""
|
||
)
|
||
|
||
func main() {
|
||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||
defer stop()
|
||
|
||
log.Printf("iotlcm-sms starting, version=%s buildTime=%s commit=%s", BuildVersion, BuildTime, CommitID)
|
||
|
||
// 默认全局配置:config.yaml 提供默认值,SMS_* 环境变量可覆盖。
|
||
defaultConfig, source, err := sms.LoadDefaultConfig()
|
||
if err != nil {
|
||
log.Fatalf("load sms default config: %v", err)
|
||
}
|
||
log.Printf("sms default config loaded: %s", source.Describe())
|
||
|
||
// 场景模板配置来自数据库(表 t_sms_template_config):改库即生效,无需改代码或重启。
|
||
// 连接参数与凭证同源于 config.yaml(SMS_DB_DSN 等环境变量可覆盖);DSN 为空时能力关闭。
|
||
var scenes sms.SceneProvider
|
||
var sceneStore *sms.SceneStore
|
||
sceneDb, sceneDbSrc, err := sms.LoadSceneDbConfig()
|
||
if err != nil {
|
||
log.Printf("load scene db config: %v(场景模板能力关闭)", err)
|
||
} else if sceneDb.DSN == "" {
|
||
log.Printf("scene db DSN not set, scene-based template config disabled")
|
||
} else {
|
||
db, err := sql.Open("mysql", sceneDb.DSN)
|
||
if err != nil {
|
||
log.Fatalf("open sms config database: %v", err)
|
||
}
|
||
db.SetMaxOpenConns(4)
|
||
db.SetMaxIdleConns(2)
|
||
db.SetConnMaxLifetime(time.Hour)
|
||
ttl := sceneDb.TTL()
|
||
sceneStore = sms.NewSceneStore(db, ttl)
|
||
defer func() { _ = sceneStore.Close() }()
|
||
scenes = sceneStore
|
||
log.Printf("sms scene config store enabled (source: %s), cache ttl=%s", sceneDbSrc.Describe(), ttl)
|
||
}
|
||
|
||
providers := sms.NewRegistryWithDefault(defaultConfig, scenes)
|
||
providers.Register(sms.ServiceAliyun, aliyun.New())
|
||
providers.Register(sms.ServiceTencent, tencent.New())
|
||
|
||
httpAddr := envOrDefault("HTTP_ADDR", ":8080")
|
||
httpServer := &http.Server{
|
||
Addr: httpAddr,
|
||
Handler: httpapi.NewHandler(providers),
|
||
ReadHeaderTimeout: 5 * time.Second,
|
||
ReadTimeout: 10 * time.Second,
|
||
WriteTimeout: 30 * time.Second,
|
||
IdleTimeout: 60 * time.Second,
|
||
}
|
||
|
||
grpcAddr := envOrDefault("GRPC_ADDR", ":11200")
|
||
grpcListener, err := net.Listen("tcp", grpcAddr)
|
||
if err != nil {
|
||
log.Fatalf("listen on gRPC address %s: %v", grpcAddr, err)
|
||
}
|
||
grpcServer := grpc.NewServer()
|
||
pb.RegisterNoticeServer(grpcServer, grpcapi.NewServer(providers))
|
||
reflection.Register(grpcServer)
|
||
|
||
errCh := make(chan error, 2)
|
||
go func() {
|
||
log.Printf("sms http server listening on %s", httpAddr)
|
||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||
errCh <- err
|
||
}
|
||
}()
|
||
go func() {
|
||
log.Printf("sms gRPC server listening on %s", grpcAddr)
|
||
if err := grpcServer.Serve(grpcListener); err != nil {
|
||
errCh <- err
|
||
}
|
||
}()
|
||
|
||
select {
|
||
case err := <-errCh:
|
||
log.Printf("server stopped unexpectedly: %v", err)
|
||
stop()
|
||
case <-ctx.Done():
|
||
}
|
||
|
||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||
defer cancel()
|
||
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
||
log.Printf("shutdown HTTP server: %v", err)
|
||
}
|
||
grpcServer.GracefulStop()
|
||
}
|
||
|
||
func envOrDefault(name, fallback string) string {
|
||
if value := os.Getenv(name); value != "" {
|
||
return value
|
||
}
|
||
return fallback
|
||
}
|