optimize features process logic to abstract in cfg pkg

pull/193/head
Michael Li 2 years ago
parent ebcf2be179
commit bace5bf750

@ -4,6 +4,8 @@ import (
"log"
"sync"
"time"
"github.com/rocboss/paopao-ce/pkg/cfg"
)
var (
@ -12,7 +14,6 @@ var (
loggerZincSetting *LoggerZincSettingS
loggerMeiliSetting *LoggerMeiliSettingS
redisSetting *RedisSettingS
features *FeaturesSettingS
DatabaseSetting *DatabaseSetingS
MysqlSetting *MySQLSettingS
@ -45,9 +46,11 @@ func setupSetting(suite []string, noDefault bool) error {
return err
}
features = setting.FeaturesFrom("Features")
// initialize features configure
ss, kv := setting.featuresInfoFrom("Features")
cfg.Initialize(ss, kv)
if len(suite) > 0 {
if err = features.Use(suite, noDefault); err != nil {
if err = cfg.Use(suite, noDefault); err != nil {
return err
}
}
@ -106,59 +109,26 @@ func Initialize(suite []string, noDefault bool) {
setupDBEngine()
}
// Cfg get value by key if exist
func Cfg(key string) (string, bool) {
return features.Cfg(key)
}
// CfgIf check expression is true. if expression just have a string like
// `Sms` is mean `Sms` whether defined in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func CfgIf(expression string) bool {
return features.CfgIf(expression)
}
// CfgBe check expression is true then do the handle. if expression just have a string like
// `Sms` is mean `Sms` whether defined in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func CfgBe(expression string, handle func()) {
if features.CfgIf(expression) {
handle()
}
}
// CfgNot check expression is not true then do the handle. if expression just have a string like
// `Sms` is mean `Sms` whether defined in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func CfgNot(expression string, handle func()) {
if !features.CfgIf(expression) {
handle()
}
}
func GetOssDomain() string {
uri := "https://"
if CfgIf("AliOSS") {
if cfg.If("AliOSS") {
return uri + AliOSSSetting.Domain + "/"
} else if CfgIf("COS") {
} else if cfg.If("COS") {
return uri + COSSetting.Domain + "/"
} else if CfgIf("HuaweiOBS") {
} else if cfg.If("HuaweiOBS") {
return uri + HuaweiOBSSetting.Domain + "/"
} else if CfgIf("MinIO") {
} else if cfg.If("MinIO") {
if !MinIOSetting.Secure {
uri = "http://"
}
return uri + MinIOSetting.Domain + "/" + MinIOSetting.Bucket + "/"
} else if CfgIf("S3") {
} else if cfg.If("S3") {
if !S3Setting.Secure {
uri = "http://"
}
// TODO: will not work well need test in real world
return uri + S3Setting.Domain + "/" + S3Setting.Bucket + "/"
} else if CfgIf("LocalOSS") {
} else if cfg.If("LocalOSS") {
if !LocalOSSSetting.Secure {
uri = "http://"
}

@ -5,6 +5,7 @@ import (
"time"
"github.com/go-redis/redis/v8"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
@ -59,15 +60,15 @@ func newDBEngine() (*gorm.DB, error) {
db *gorm.DB
err error
)
if CfgIf("MySQL") {
if cfg.If("MySQL") {
logrus.Debugln("use MySQL as db")
if db, err = gorm.Open(mysql.Open(MysqlSetting.Dsn()), config); err == nil {
db.Use(plugin)
}
} else if CfgIf("Postgres") {
} else if cfg.If("Postgres") {
logrus.Debugln("use PostgreSQL as db")
db, err = gorm.Open(postgres.Open(PostgresSetting.Dsn()), config)
} else if CfgIf("Sqlite3") {
} else if cfg.If("Sqlite3") {
logrus.Debugf("use Sqlite3 as db path:%s sqlite3InCgoEnabled:%t", Sqlite3Setting.Path, sqlite3InCgoEnabled)
db, err = gormOpenSqlite3(config)
} else {

@ -3,6 +3,7 @@ package conf
import (
"io"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)
@ -20,16 +21,20 @@ func setupLogger() {
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetLevel(loggerSetting.logLevel())
if CfgIf("LoggerFile") {
out := newFileLogger()
logrus.SetOutput(out)
} else if CfgIf("LoggerZinc") {
hook := newZincLogHook()
logrus.SetOutput(io.Discard)
logrus.AddHook(hook)
} else if CfgIf("LoggerMeili") {
hook := newMeiliLogHook()
logrus.SetOutput(io.Discard)
logrus.AddHook(hook)
}
cfg.In(cfg.Actions{
"LoggerFile": func() {
out := newFileLogger()
logrus.SetOutput(out)
},
"LoggerZinc": func() {
hook := newZincLogHook()
logrus.SetOutput(io.Discard)
logrus.AddHook(hook)
},
"LoggerMeili": func() {
hook := newMeiliLogHook()
logrus.SetOutput(io.Discard)
logrus.AddHook(hook)
},
})
}

@ -90,12 +90,6 @@ type SmsJuheSettings struct {
TplVal string
}
type FeaturesSettingS struct {
kv map[string]string
suites map[string][]string
features map[string]string
}
type TweetSearchS struct {
MaxUpdateQPS int
MinWorker int
@ -237,7 +231,7 @@ func (s *Setting) Unmarshal(objects map[string]any) error {
return nil
}
func (s *Setting) FeaturesFrom(k string) *FeaturesSettingS {
func (s *Setting) featuresInfoFrom(k string) (map[string][]string, map[string]string) {
sub := s.vp.Sub(k)
keys := sub.AllKeys()
@ -252,73 +246,7 @@ func (s *Setting) FeaturesFrom(k string) *FeaturesSettingS {
suites[key] = sub.GetStringSlice(key)
}
}
return newFeatures(suites, kv)
}
func newFeatures(suites map[string][]string, kv map[string]string) *FeaturesSettingS {
features := &FeaturesSettingS{
suites: suites,
kv: kv,
features: make(map[string]string),
}
features.UseDefault()
return features
}
func (f *FeaturesSettingS) UseDefault() {
f.Use([]string{"default"}, true)
}
func (f *FeaturesSettingS) Use(suite []string, noDefault bool) error {
if noDefault && len(f.features) != 0 {
f.features = make(map[string]string)
}
features := f.flatFeatures(suite)
for _, feature := range features {
if len(feature) == 0 {
continue
}
f.features[feature] = f.kv[feature]
}
return nil
}
func (f *FeaturesSettingS) flatFeatures(suite []string) []string {
features := make([]string, 0, len(suite)+10)
for s := suite[:]; len(s) > 0; s = s[:len(s)-1] {
item := strings.TrimSpace(strings.ToLower(s[0]))
if len(item) > 0 {
if items, exist := f.suites[item]; exist {
s = append(s, items...)
}
features = append(features, item)
}
s[0] = s[len(s)-1]
}
return features
}
// Cfg get value by key if exist
func (f *FeaturesSettingS) Cfg(key string) (string, bool) {
key = strings.ToLower(key)
value, exist := f.features[key]
return value, exist
}
// CfgIf check expression is true. if expression just have a string like
// `Sms` is mean `Sms` whether define in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func (f *FeaturesSettingS) CfgIf(expression string) bool {
kv := strings.Split(expression, "=")
key := strings.Trim(strings.ToLower(kv[0]), " ")
v, ok := f.features[key]
if len(kv) == 2 && ok && strings.Trim(kv[1], " ") == v {
return true
} else if len(kv) == 1 && ok {
return true
}
return false
return suites, kv
}
func (s *MySQLSettingS) Dsn() string {

@ -3,13 +3,13 @@ package dao
import (
"sync"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu"
"github.com/rocboss/paopao-ce/internal/dao/sakila"
"github.com/rocboss/paopao-ce/internal/dao/search"
"github.com/rocboss/paopao-ce/internal/dao/slonik"
"github.com/rocboss/paopao-ce/internal/dao/storage"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
)
@ -24,11 +24,11 @@ var (
func DataService() core.DataService {
onceDs.Do(func() {
var v core.VersionInfo
if conf.CfgIf("Gorm") {
if cfg.If("Gorm") {
ds, v = jinzhu.NewDataService()
} else if conf.CfgIf("Sqlx") && conf.CfgIf("MySQL") {
} else if cfg.If("Sqlx") && cfg.If("MySQL") {
ds, v = sakila.NewDataService()
} else if conf.CfgIf("Sqlx") && (conf.CfgIf("Postgres") || conf.CfgIf("PostgreSQL")) {
} else if cfg.If("Sqlx") && (cfg.If("Postgres") || cfg.If("PostgreSQL")) {
ds, v = slonik.NewDataService()
} else {
// default use gorm as orm for sql database
@ -42,19 +42,19 @@ func DataService() core.DataService {
func ObjectStorageService() core.ObjectStorageService {
onceOss.Do(func() {
var v core.VersionInfo
if conf.CfgIf("AliOSS") {
if cfg.If("AliOSS") {
oss, v = storage.MustAliossService()
} else if conf.CfgIf("COS") {
} else if cfg.If("COS") {
oss, v = storage.NewCosService()
} else if conf.CfgIf("HuaweiOBS") {
} else if cfg.If("HuaweiOBS") {
oss, v = storage.MustHuaweiobsService()
} else if conf.CfgIf("MinIO") {
} else if cfg.If("MinIO") {
oss, v = storage.MustMinioService()
} else if conf.CfgIf("S3") {
} else if cfg.If("S3") {
oss, v = storage.MustS3Service()
logrus.Infof("use S3 as object storage by version %s", v.Version())
return
} else if conf.CfgIf("LocalOSS") {
} else if cfg.If("LocalOSS") {
oss, v = storage.MustLocalossService()
} else {
// default use AliOSS as object storage service
@ -71,9 +71,9 @@ func TweetSearchService() core.TweetSearchService {
onceTs.Do(func() {
var v core.VersionInfo
ams := newAuthorizationManageService()
if conf.CfgIf("Zinc") {
if cfg.If("Zinc") {
ts, v = search.NewZincTweetSearchService(ams)
} else if conf.CfgIf("Meili") {
} else if cfg.If("Meili") {
ts, v = search.NewMeiliTweetSearchService(ams)
} else {
// default use Zinc as tweet search service
@ -87,11 +87,11 @@ func TweetSearchService() core.TweetSearchService {
}
func newAuthorizationManageService() (s core.AuthorizationManageService) {
if conf.CfgIf("Gorm") {
if cfg.If("Gorm") {
s = jinzhu.NewAuthorizationManageService()
} else if conf.CfgIf("Sqlx") && conf.CfgIf("MySQL") {
} else if cfg.If("Sqlx") && cfg.If("MySQL") {
s = sakila.NewAuthorizationManageService()
} else if conf.CfgIf("Sqlx") && (conf.CfgIf("Postgres") || conf.CfgIf("PostgreSQL")) {
} else if cfg.If("Sqlx") && (cfg.If("Postgres") || cfg.If("PostgreSQL")) {
s = slonik.NewAuthorizationManageService()
} else {
s = jinzhu.NewAuthorizationManageService()

@ -10,6 +10,7 @@ import (
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/rocboss/paopao-ce/internal/dao/security"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
)
@ -43,10 +44,10 @@ func NewDataService() (core.DataService, core.VersionInfo) {
db := conf.MustGormDB()
i := newIndexPostsService(db)
if conf.CfgIf("SimpleCacheIndex") {
if cfg.If("SimpleCacheIndex") {
i = newSimpleIndexPostsService(db)
c, v = cache.NewSimpleCacheIndexService(i)
} else if conf.CfgIf("BigCacheIndex") {
} else if cfg.If("BigCacheIndex") {
a := newAuthorizationManageService(db)
c, v = cache.NewBigCacheIndexService(i, a)
} else {

@ -14,6 +14,7 @@ import (
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
"github.com/tencentyun/cos-go-sdk-v5"
)
@ -31,14 +32,14 @@ func MustAliossService() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &aliossCreateTempDirServant{
bucket: bucket,
domain: domain,
tempDir: conf.ObjectStorage.TempDirSlash(),
}
logrus.Debugln("use OSS:TempDir feature")
} else if conf.CfgIf("OSS:Retention") {
} else if cfg.If("OSS:Retention") {
cs = &aliossCreateRetentionServant{
bucket: bucket,
domain: domain,
@ -75,7 +76,7 @@ func NewCosService() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &cosCreateTempDirServant{
client: client,
domain: domain,
@ -108,7 +109,7 @@ func MustHuaweiobsService() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &hwobsCreateTempDirServant{
client: client,
bucket: s.Bucket,
@ -116,7 +117,7 @@ func MustHuaweiobsService() (core.ObjectStorageService, core.VersionInfo) {
tempDir: conf.ObjectStorage.TempDirSlash(),
}
logrus.Debugln("use OSS:TempDir feature")
} else if conf.CfgIf("OSS:Retention") {
} else if cfg.If("OSS:Retention") {
retainUntilDays := time.Until(time.Date(2049, time.December, 1, 12, 0, 0, 0, time.UTC)) / (24 * time.Hour)
cs = &hwobsCreateRetentionServant{
client: client,
@ -153,7 +154,7 @@ func MustLocalossService() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
savePath = savePath + "/" + conf.LocalOSSSetting.Bucket + "/"
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &localossCreateTempDirServant{
savePath: savePath,
domain: domain,
@ -188,7 +189,7 @@ func MustMinioService() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &minioCreateTempDirServant{
client: client,
bucket: conf.MinIOSetting.Bucket,
@ -196,7 +197,7 @@ func MustMinioService() (core.ObjectStorageService, core.VersionInfo) {
tempDir: conf.ObjectStorage.TempDirSlash(),
}
logrus.Debugln("use OSS:TempDir feature")
} else if conf.CfgIf("OSS:Retention") {
} else if cfg.If("OSS:Retention") {
cs = &minioCreateRetentionServant{
client: client,
bucket: conf.MinIOSetting.Bucket,
@ -235,7 +236,7 @@ func MustS3Service() (core.ObjectStorageService, core.VersionInfo) {
domain := conf.GetOssDomain()
var cs core.OssCreateService
if conf.CfgIf("OSS:TempDir") {
if cfg.If("OSS:TempDir") {
cs = &minioCreateTempDirServant{
client: client,
bucket: conf.S3Setting.Bucket,
@ -243,7 +244,7 @@ func MustS3Service() (core.ObjectStorageService, core.VersionInfo) {
tempDir: conf.ObjectStorage.TempDirSlash(),
}
logrus.Debugln("use OSS:TempDir feature")
} else if conf.CfgIf("OSS:Retention") {
} else if cfg.If("OSS:Retention") {
cs = &minioCreateRetentionServant{
client: client,
bucket: conf.S3Setting.Bucket,

@ -2,14 +2,14 @@ package middleware
import (
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/app"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/rocboss/paopao-ce/pkg/errcode"
)
func Priv() gin.HandlerFunc {
if conf.CfgIf("PhoneBind") {
if cfg.If("PhoneBind") {
return func(c *gin.Context) {
if u, exist := c.Get("USER"); exist {
if user, ok := u.(*model.User); ok {

@ -4,12 +4,12 @@
package migration
import (
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
)
func Run() {
if conf.CfgIf("Migration") {
if cfg.If("Migration") {
logrus.Infoln("want migrate feature but not support in this compile version")
}
}

@ -14,12 +14,13 @@ import (
"github.com/golang-migrate/migrate/v4/source"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/rocboss/paopao-ce/scripts/migration"
"github.com/sirupsen/logrus"
)
func Run() {
if !conf.CfgIf("Migration") {
if !cfg.If("Migration") {
logrus.Infoln("skip migrate because not add Migration feature in config.yaml")
return
}
@ -32,13 +33,13 @@ func Run() {
err, err2 error
)
if conf.CfgIf("MySQL") {
if cfg.If("MySQL") {
dbName = conf.MysqlSetting.DBName
db, err = sql.Open("mysql", conf.MysqlSetting.Dsn()+"&multiStatements=true")
} else if conf.CfgIf("PostgreSQL") || conf.CfgIf("Postgres") {
} else if cfg.If("PostgreSQL") || cfg.If("Postgres") {
dbName = (*conf.PostgresSetting)["DBName"]
db, err = sql.Open("postgres", conf.PostgresSetting.Dsn())
} else if conf.CfgIf("Sqlite3") {
} else if cfg.If("Sqlite3") {
db, err = conf.OpenSqlite3()
} else {
dbName = conf.MysqlSetting.DBName
@ -50,13 +51,13 @@ func Run() {
}
migrationsTable := conf.DatabaseSetting.TablePrefix + "schema_migrations"
if conf.CfgIf("MySQL") {
if cfg.If("MySQL") {
srcDriver, err = iofs.New(migration.Files, "mysql")
dbDriver, err2 = mysql.WithInstance(db, &mysql.Config{MigrationsTable: migrationsTable})
} else if conf.CfgIf("PostgreSQL") || conf.CfgIf("Postgres") {
} else if cfg.If("PostgreSQL") || cfg.If("Postgres") {
srcDriver, err = iofs.New(migration.Files, "postgres")
dbDriver, err2 = postgres.WithInstance(db, &postgres.Config{MigrationsTable: migrationsTable})
} else if conf.CfgIf("Sqlite3") {
} else if cfg.If("Sqlite3") {
srcDriver, err = iofs.New(migration.Files, "sqlite3")
dbDriver, err2 = sqlite3.WithInstance(db, &sqlite3.Config{MigrationsTable: migrationsTable})
} else {

@ -4,6 +4,7 @@ import (
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3"
)
@ -16,7 +17,7 @@ var (
func Initialize() {
objectStorage = dao.ObjectStorageService()
if conf.CfgIf("Alipay") {
if cfg.If("Alipay") {
initAlipay()
}
}

@ -6,12 +6,12 @@ package routers
import (
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/docs/openapi"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/cfg"
)
// registerDocs register docs asset route
func registerDocs(e *gin.Engine) {
if conf.CfgIf("Docs:OpenAPI") {
cfg.Be("Docs:OpenAPI", func() {
e.StaticFS("/docs/openapi", openapi.NewFileSystem())
}
})
}

@ -9,6 +9,7 @@ import (
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/middleware"
"github.com/rocboss/paopao-ce/internal/routers/api"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
)
@ -28,7 +29,10 @@ func NewRouter() *gin.Engine {
{
registerDocs(e)
registerStatick(e)
routeLocalOSS(e)
cfg.Be("LocalOSS", func() {
routeLocalOSS(e)
})
}
// v1 group api
@ -84,7 +88,9 @@ func NewRouter() *gin.Engine {
routeCore(authApi, privApi, adminApi)
// 支付宝路由注册
routeAlipay(r, authApi)
cfg.Be("Alipay", func() {
routeAlipay(r, authApi)
})
// Relationship相关路由注册
routeRelationship(authApi)
@ -205,10 +211,6 @@ func routeCore(authApi gin.IRoutes, privApi gin.IRoutes, adminApi gin.IRoutes) {
// routeLocalOSS register LocalOSS route if needed
func routeLocalOSS(e *gin.Engine) {
if !conf.CfgIf("LocalOSS") {
return
}
savePath, err := filepath.Abs(conf.LocalOSSSetting.SavePath)
if err != nil {
logrus.Fatalf("get localOSS save path err: %v", err)
@ -220,10 +222,6 @@ func routeLocalOSS(e *gin.Engine) {
// routeAlipay register Alipay feature releated route if needed
func routeAlipay(public gin.IRoutes, authApi gin.IRoutes) {
if !conf.CfgIf("Alipay") {
return
}
// 支付宝回调
public.POST("/alipay/notify", api.AlipayNotify)
@ -239,15 +237,18 @@ func routeAlipay(public gin.IRoutes, authApi gin.IRoutes) {
// routeRelationship register Relationship releated routes
func routeRelationship(authApi gin.IRoutes) {
if conf.CfgIf("Friendship") {
routeFriendship(authApi)
} else if conf.CfgIf("Followship") {
routeFollowship(authApi)
} else {
cfg.In(cfg.Actions{
"Friendship": func() {
routeFriendship(authApi)
},
"Followship": func() {
routeFollowship(authApi)
},
}, func() {
// 暂时默认使用好友模式
// TODO: 后期提供一种无关系模式(既不是好友模式也不是关注者模式)作为默认的关系模式
routeFriendship(authApi)
}
})
}
// routeFriendship register Friendship feature releated routes

@ -1,10 +1,10 @@
package service
import (
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus"
)
@ -19,7 +19,7 @@ func Initialize() {
ds = dao.DataService()
ts = dao.TweetSearchService()
oss = dao.ObjectStorageService()
DisablePhoneVerify = !conf.CfgIf("Sms")
DisablePhoneVerify = !cfg.If("Sms")
}
// persistMediaContents 获取媒体内容并持久化

@ -0,0 +1,40 @@
package cfg
var (
_features = emptyFeatures()
// Use alias of Features.Use func
Use = _features.Use
// UseDeafult alias of Features.UseDefault func
UseDefault = _features.UseDefault
// As alias of Features.Cfg func
As = _features.Cfg
// If alias of Features.CfgIf func
If = _features.CfgIf
// In alias of Features.CfgIn func
In = _features.CfgIn
// Be alias of Feaures.CfgBe func
Be = _features.CfgBe
// Not alias of Features.CfgNot func
Not = _features.CfgNot
)
func Initialize(suites map[string][]string, kv map[string]string) {
_features = NewFeatures(suites, kv)
{
// must re-assign variable below
Use = _features.Use
UseDefault = _features.UseDefault
As = _features.Cfg
If = _features.CfgIf
In = _features.CfgIn
Be = _features.CfgBe
Not = _features.CfgNot
}
}

@ -0,0 +1,78 @@
package cfg
import (
"testing"
)
func TestCfg(t *testing.T) {
suites := map[string][]string{
"default": {"Sms", "Alipay", "Zinc", "MySQL", "Redis", "AliOSS", "LogZinc"},
"develop": {"Zinc", "MySQL", "AliOSS", "LogFile"},
"slim": {"Zinc", "MySQL", "Redis", "AliOSS", "LogFile"},
}
kv := map[string]string{
"sms": "SmsJuhe",
}
Initialize(suites, kv)
UseDefault()
if !If("Sms") {
t.Error(`want If("Sms") == true but not`)
}
if v, exist := As("Sms"); exist && v != "SmsJuhe" {
t.Errorf(`want As("Sms") == "SmsJuhe", true but got: "%s", "%t"`, v, exist)
}
matched := false
Be("Alipay", func() {
matched = true
})
if !matched {
t.Error(`want Be("Alipay", ...) matched but not`)
}
matched = false
Not("LogFile", func() {
matched = true
})
if !matched {
t.Error(`want Not("LogFile", ...) matched but not`)
}
var m1, m2, m3, m4 bool
In(Actions{
"Sms": func() {
m1 = true
},
"Alipay": func() {
m2 = true
},
"Meili": func() {
m4 = true
},
}, func() {
m3 = true
})
if !m1 || !m2 || m3 || m4 {
t.Errorf(`In("Sms", "Alipay", "Meili", ...) not correct -> m1: %t m2:%t m3:%t m4:%t`, m1, m2, m3, m4)
}
m1 = false
m2 = false
m3 = false
In(Actions{
"LogFile": func() {
m1 = true
},
"Meili": func() {
m2 = true
},
}, func() {
m3 = true
})
if m1 || m2 || !m3 {
t.Errorf(`In("Zinc", "MySQL", ...) not correct -> m1: %t m2:%t m3:%t`, m1, m2, m3)
}
}

@ -0,0 +1,127 @@
package cfg
import (
"strings"
"github.com/rocboss/paopao-ce/pkg/types"
)
type Features struct {
kv map[string]string
suites map[string][]string
features map[string]string
}
// Actions feature-func map alias type
type Actions map[string]types.Fn
func NewFeatures(suites map[string][]string, kv map[string]string) *Features {
f := &Features{
suites: suites,
kv: kv,
features: make(map[string]string),
}
f.UseDefault()
return f
}
func emptyFeatures() *Features {
return &Features{
features: make(map[string]string),
}
}
func (f *Features) UseDefault() {
f.Use([]string{"default"}, true)
}
func (f *Features) Use(suite []string, noDefault bool) error {
if noDefault && len(f.features) != 0 {
f.features = make(map[string]string)
}
features := f.flatFeatures(suite)
for _, feature := range features {
if len(feature) == 0 {
continue
}
f.features[feature] = f.kv[feature]
}
return nil
}
func (f *Features) flatFeatures(suite []string) []string {
features := make([]string, 0, len(suite)+10)
for s := suite[:]; len(s) > 0; s = s[:len(s)-1] {
item := strings.TrimSpace(strings.ToLower(s[0]))
if len(item) > 0 {
if items, exist := f.suites[item]; exist {
s = append(s, items...)
}
features = append(features, item)
}
s[0] = s[len(s)-1]
}
return features
}
// Cfg get value by key if exist
func (f *Features) Cfg(key string) (string, bool) {
key = strings.ToLower(key)
value, exist := f.features[key]
return value, exist
}
// CfgIf check expression is true. if expression just have a string like
// `Sms` is mean `Sms` whether define in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func (f *Features) CfgIf(expression string) bool {
kv := strings.Split(expression, "=")
key := strings.Trim(strings.ToLower(kv[0]), " ")
v, ok := f.features[key]
if len(kv) == 2 && ok && strings.Trim(kv[1], " ") == v {
return true
} else if len(kv) == 1 && ok {
return true
}
return false
}
// CfgIn range actions to check item's expression is true then do the handle, defFn will handle
// if all items are not matched,
func (f *Features) CfgIn(actions Actions, defAct ...types.Fn) {
itemMatched := false
for expression, handle := range actions {
if f.CfgIf(expression) && handle != nil {
handle()
itemMatched = true
}
}
if !itemMatched && len(defAct) > 0 {
for _, handle := range defAct {
if handle != nil {
handle()
}
}
}
}
// CfgBe check expression is true then do the handle. if expression just have a string like
// `Sms` is mean `Sms` whether defined in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func (f *Features) CfgBe(expression string, handle types.Fn) {
if f.CfgIf(expression) && handle != nil {
handle()
}
}
// CfgNot check expression is not true then do the handle. if expression just have a string like
// `Sms` is mean `Sms` whether defined in suite feature settings. expression like
// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value
// is `SmsJuhe`
func (f *Features) CfgNot(expression string, handle func()) {
if !f.CfgIf(expression) {
handle()
}
}

@ -1,4 +1,4 @@
package conf
package cfg
import (
"testing"
@ -13,7 +13,7 @@ func TestUseDefault(t *testing.T) {
kv := map[string]string{
"sms": "SmsJuhe",
}
features := newFeatures(suites, kv)
f := NewFeatures(suites, kv)
for _, data := range []struct {
key string
expect string
@ -25,7 +25,7 @@ func TestUseDefault(t *testing.T) {
{"Redis", "", true},
{"Database", "", false},
} {
if v, ok := features.Cfg(data.key); ok != data.exist || v != data.expect {
if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect {
t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok)
}
}
@ -35,7 +35,7 @@ func TestUseDefault(t *testing.T) {
"SmsJuhe": false,
"default": true,
} {
if ok := features.CfgIf(exp); res != ok {
if ok := f.CfgIf(exp); res != ok {
t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok)
}
}
@ -50,9 +50,9 @@ func TestUse(t *testing.T) {
kv := map[string]string{
"sms": "SmsJuhe",
}
features := newFeatures(suites, kv)
f := NewFeatures(suites, kv)
features.Use([]string{"develop"}, true)
f.Use([]string{"develop"}, true)
for _, data := range []struct {
key string
expect string
@ -64,7 +64,7 @@ func TestUse(t *testing.T) {
{"Redis", "", false},
{"Database", "", false},
} {
if v, ok := features.Cfg(data.key); ok != data.exist || v != data.expect {
if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect {
t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok)
}
}
@ -75,13 +75,13 @@ func TestUse(t *testing.T) {
"default": false,
"develop": true,
} {
if ok := features.CfgIf(exp); res != ok {
if ok := f.CfgIf(exp); res != ok {
t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok)
}
}
features.UseDefault()
features.Use([]string{"slim", "", "demo"}, false)
f.UseDefault()
f.Use([]string{"slim", "", "demo"}, false)
for _, data := range []struct {
key string
expect string
@ -94,7 +94,7 @@ func TestUse(t *testing.T) {
{"Database", "", false},
{"demo", "", true},
} {
if v, ok := features.Cfg(data.key); ok != data.exist || v != data.expect {
if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect {
t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok)
}
}
@ -107,7 +107,7 @@ func TestUse(t *testing.T) {
"slim": true,
"demo": true,
} {
if ok := features.CfgIf(exp); res != ok {
if ok := f.CfgIf(exp); res != ok {
t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok)
}
}

@ -1,3 +1,7 @@
package types
// Empty empty alias type
type Empty = struct{}
// Fn empty argument func alias type
type Fn = func()

Loading…
Cancel
Save