Initial commit

This commit is contained in:
2026-05-20 16:13:58 +08:00
commit ceffbe382e
500 changed files with 157469 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
package main
import (
"stat/common/log"
"stat/tool/dspSync/model"
"stat/tool/dspSync/service"
"time"
)
func initMongoDB() error {
if err := model.InitMongoDB(); err != nil {
log.Error("InitMongoDB err", log.E(err))
return err
}
return nil
}
func main() {
initMongoDB()
time.Local, _ = time.LoadLocation("Asia/Shanghai")
_ = service.UserStatInfo() //用户同步完成可执行
}
+98
View File
@@ -0,0 +1,98 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"time"
"go.mongodb.org/mongo-driver/bson"
)
// DistrictInfo 渠道原始信息
type DistrictInfo struct {
Code string `bson:"code"` //商区码
Name string `bson:"name"` //账号
Mobile string `bson:"mobile"` //手机号
Parent string `bson:"parent"` //parent
Password string `bson:"password"` //密码
DiscType int `bson:"discType"` //商区类型/结算类型
DividendRatio float64 `bson:"dividendRatio"` //分红比例 参与结算
DisSettlement bool `bson:"disSettlement"` //禁止结算
UserUnitCent float64 `bson:"userUnitCent"` //用户单价 单位:分
NUDeductionRatio float64 `bson:"nuDeductionRatio"` //新增用户扣量比例
NUDedLowerOutset int64 `bson:"nuDedLowerOutset"` //新增用户扣量起点
NUDedAt time.Time `bson:"nuDedAt"` //新增用户扣量时间
RechgDeductionRatio float64 `bson:"rechgDeductionRatio"` //充值扣量比例
RechgDedLowerOutset int64 `bson:"rechgDedLowerOutset"` //充值扣量起点
RechgDedAt time.Time `bson:"rechgDedAt"` //充值扣量时间
ChildMax int `bson:"childMax"` //最大孩子数
Disable bool `bson:"disable"` //禁用
Lock bool `bson:"lock"` //禁止登陆
DisTrans bool `bson:"disTrans"` //禁止交易
DisAd bool `bson:"disAd"` //禁止广告
DisMulDivi bool `bson:"disMulDivi"` //禁止多级分成(目前针对CPS)
PayPassword string `bson:"payPassword"` //支付密码
BalanceCent float64 `bson:"balance"` //余额 单位:分
Remark string `bson:"remark"` //备注
CreatedAt time.Time `bson:"createdAt"` //文档创建时间
UpdatedAt time.Time `bson:"updatedAt"` //文档更新时间
}
// DspDistrictCodeInfo 渠道码信息
type DspDistrictCodeInfo struct {
DiscCode string `bson:"discCode"` //商圈码
PromSeq string `bson:"promSeq"` //推广序列
Remark string `bson:"remark"` //备注
CreatedAt time.Time `bson:"createdAt"`
DeletedAt time.Time `bson:"deletedAt,omitempty"` //删除时间
}
type BillLog struct {
SumDate time.Time `bson:"sumDate"` //日期
DiscType string `bson:"discType"` //商区类型
DistrictCode string `bson:"districtCode"` //商圈码
Name string `bson:"name"` //账号
Cent float64 `bson:"cent"` //人民币分
Desc string `bson:"desc"` //记录描述
CreatedAt time.Time `bson:"createdAt"` //创建时间
}
const CollDistrict = "district"
const CollDistrictCode = "prom_seqe"
var dbDistrict *mongos.MongoTool
var dbDistrictcode *mongos.MongoTool
var dbDistrictLog *mongos.MongoTool
func DistrictInit() {
dbDistrict = mongos.New(ManagerDsp, CollDistrict)
dbDistrictcode = mongos.New(ManagerDsp, CollDistrictCode)
}
// FindDspDistrictInfo 查询所有渠道
func FindDspDistrictInfo(ctx context.Context) ([]DistrictInfo, error) {
list := make([]DistrictInfo, 0)
query := bson.M{}
if err := dbDistrict.Find(ctx, &list, query); err != nil {
log.Error(fmt.Sprintf("model %s FindDspDistrictInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
// FindDspDistrictCodeInfo 查询渠道的渠道码
func FindDspDistrictCodeInfo(ctx context.Context, discCode string) ([]DspDistrictCodeInfo, error) {
list := make([]DspDistrictCodeInfo, 0)
query := bson.M{"discCode": discCode}
if err := dbDistrictcode.Find(ctx, &list, query); err != nil {
log.Error(fmt.Sprintf("model %s FindDspDistrictInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
+39
View File
@@ -0,0 +1,39 @@
package model
import (
"stat/common/log"
"stat/common/mongos"
"stat/models"
)
var (
ManagerDsp *mongos.Manager
ManagerStat *mongos.Manager
)
// InitMongoDB 初始化同步数据库
func InitMongoDB() error {
// DspDB := mongos.NewManager("mongodb://yinse:7P1pwdsMLds6QOB092Xq@172.104.42.200:47018/video?direct=game&maxPoolSize=200&connectTimeout=30&authSource=video")
// if err := DspDB.Connect(); err != nil {
// log.Error("mgoDB connect err", log.E(err))
// return err
// }
// ManagerDsp = DspDB
// // 初始化表链接
// UserInit()
// RechargeInit()
// WithdrawInit()
statDB := mongos.NewManager("mongodb://stat:ebCJuLfJQAGKVDecdFH0@172.104.42.200:47017,139.162.18.46:47017,139.162.35.214:47017/statcentre?maxPoolSize=200&connectTimeout=30&authSource=statcentre")
if err := statDB.Connect(); err != nil {
log.Error("mgoDB connect err", log.E(err))
return err
}
mongos.MgoManager = statDB
// 初始化数据库索引
models.InitIndex()
return nil
}
+93
View File
@@ -0,0 +1,93 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"stat/common/utils"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type DspRecharge struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
UID uint64 `json:"uid" bson:"uid"` //用户id
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
OID string `json:"oid" bson:"oid"` //支付平台订单号
WithdrawType string `json:"WithdrawType" bson:"WithdrawType"` //充值类型
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
IsDirect bool `json:"isDirect" bson:"isDirect"` //true:是直推用户
DistrictCode string `json:"districtCode" bson:"districtCode"` //商区码
}
const CollRecharge = "recharge_order"
var dbRecharge *mongos.MongoTool
func RechargeInit() {
dbRecharge = mongos.New(ManagerDsp, CollRecharge)
}
// FindDspRecharge 查询用户
func FindDspRecharge(ctx context.Context, skip int64, limit int64) ([]DspRecharge, error) {
list := make([]DspRecharge, 0)
beginTimeStr := "2020-07-01T00:00:00-08:00"
beginTime := utils.StrTimeToTime(beginTimeStr)
query := bson.M{"successAt": bson.M{"$gt": beginTime}}
sort := bson.D{{Key: "successAt", Value: 1}}
opts := options.Find().SetSkip(skip).SetLimit(limit).SetSort(sort)
if err := dbRecharge.Find(ctx, &list, query, opts); err != nil {
log.Error(fmt.Sprintf("model %s FindDspRecharge Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
func FindDspRechargeCount(ctx context.Context) (count int64, err error) {
beginTimeStr := "2020-07-01T00:00:00-08:00"
beginTime := utils.StrTimeToTime(beginTimeStr)
query := bson.M{"successAt": bson.M{"$gt": beginTime}}
count, err = dbRecharge.Count(ctx, query)
if err != nil {
log.Error(fmt.Sprintf("model %s FindDspRecharge Find error", CollDistrict), log.E(err))
return count, err
}
return count, nil
}
// FindDspDistrictRecharge
func FindDspDistrictRecharge(ctx context.Context, district string) ([]DspRecharge, error) {
list := make([]DspRecharge, 0)
beginTimeStr := "2020-10-01T00:00:00-08:00"
beginTime := utils.StrTimeToTime(beginTimeStr)
query := bson.M{"successAt": bson.M{"$gt": beginTime}, "districtCode": district}
if err := dbRecharge.Find(ctx, &list, query); err != nil {
log.Error(fmt.Sprintf("model %s FindDspDistrictRecharge Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
//
+69
View File
@@ -0,0 +1,69 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
type DspUser struct {
UID uint64 `json:"uid" bson:"uid"` //用户id
SysType string `json:"sysType" bson:"sysType"` //系统类型
DevType string `json:"devType" bson:"devType"` //设备类型
Mobile string `json:"mobile" bson:"mobile"` //手机号
Name string `json:"name" bson:"name"` //名字
DistrictCode string `json:"districtCode" bson:"districtCode"` //商区码
PromCode string `json:"promotionCode" bson:"promotionCode"` //推广码
IsDirect bool `json:"isDirect" bson:"isDirect"` //true:是直推用户
CreatedAt time.Time `bson:"createdAt"` //文档创建时间
}
const CollUser = "user"
var dbUser *mongos.MongoTool
func UserInit() {
dbUser = mongos.New(ManagerDsp, CollUser)
}
// FindDspUserInfo 查询用户
func FindDspUserInfo(ctx context.Context, skip int64, limit int64) ([]DspUser, error) {
list := make([]DspUser, 0)
query := bson.M{}
sort := bson.D{{Key: "_id", Value: 1}}
opts := options.Find().SetSkip(skip).SetLimit(limit).SetSort(sort)
if err := dbUser.Find(ctx, &list, query, opts); err != nil {
log.Error(fmt.Sprintf("model %s FindDspUserInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
func FindOneUserInfo(ctx context.Context, uid uint64) (user DspUser, err error) {
query := bson.M{"uid": uid}
if err := dbUser.FindOne(ctx, &user, query); err != nil {
log.Error(fmt.Sprintf("model %s FindDspUserInfo Find error", CollDistrict), log.E(err))
return user, err
}
return user, nil
}
func FindManyUserInfo(ctx context.Context, uid []uint64) (user []DspUser, err error) {
query := bson.M{"uid": bson.M{"$in": uid}}
if err := dbUser.Find(ctx, &user, query); err != nil {
log.Error(fmt.Sprintf("model %s FindDspUserInfo Find error", CollDistrict), log.E(err))
return user, err
}
return user, nil
}
+71
View File
@@ -0,0 +1,71 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"stat/common/utils"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type DspWithdraw struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
AppId int32 `json:"appId" bson:"appId"` // appID
UID uint64 `json:"uid" bson:"uid"` //用户id
Name string `json:"name" bson:"name"` //用户名
Amount int64 `json:"amount" bson:"amount"` //蝴蝶币数量
OID string `json:"oid" bson:"oid"` //第三方支付平台id
Money int64 `json:"money" bson:"money" binding:"required"` //提现金额
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账
PayType string `json:"payType" bson:"payType" binding:"required"` //提现方式,alipay,bankcard
ActName string `json:"actName" bson:"actName"` //交易账户持有人
Act string `json:"act" bson:"act"` //交易账户
UserIP string `json:"userIp" bson:"userIp"` //用户ip
DeviceType string `json:"deviceType" bson:"deviceType"` //设备类型
DevID string `json:"devID" bson:"devID"` //设备id
Status int `json:"status" bson:"status"` //1未审核 2审核通过,转账中 3已拒绝 4未知错误 5提现成功 6提现失败
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态说明
CheckedAt time.Time `json:"checkedAt" bson:"checkedAt"` //审核时间
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //提现申请时间
ReceivedAt time.Time `json:"receivedAt" bson:"receivedAt"` //到账时间 李秋山确认 三方出款时间
BlocDeduction bool `json:"blocDeduction" bson:"blocDeduction"` //集团扣量(特定渠道扣量)
IsDirect bool `json:"isDirect" bson:"isDirect"` //true:是直推用户
DistrictCode string `json:"districtCode" bson:"districtCode"` //渠道码
PromCode string `json:"promCode,omitempty" bson:"promCode"` //用户推广序列
}
const CollWithdraw = "withdraw_order"
var dbWithdraw *mongos.MongoTool
func WithdrawInit() {
dbWithdraw = mongos.New(ManagerDsp, CollWithdraw)
}
// FindDspWithdraw 查询用户
func FindDspWithdraw(ctx context.Context, skip int64, limit int64) ([]DspWithdraw, error) {
list := make([]DspWithdraw, 0)
beginTimeStr := "2020-07-01T00:00:00-08:00"
beginTime := utils.StrTimeToTime(beginTimeStr)
query := bson.M{"successAt": bson.M{"$gt": beginTime}, "withdrawType": 1}
sort := bson.D{{Key: "successAt", Value: 1}}
opts := options.Find().SetSkip(skip).SetLimit(limit).SetSort(sort)
if err := dbWithdraw.Find(ctx, &list, query, opts); err != nil {
log.Error(fmt.Sprintf("model %s FindDspWithdraw Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
+74
View File
@@ -0,0 +1,74 @@
package service
import (
"context"
"fmt"
"stat/models/advertiseMod"
)
type InviteInfo struct {
Count int64
}
func UserStatInfo() error {
ctx := context.Background()
adsList, err := advertiseMod.FindAds(ctx)
if err != nil {
return err
}
//fmt.Println(len(adsList))
for _, v := range adsList {
links := make([]advertiseMod.LinkInfo, 0)
links = append(links, advertiseMod.LinkInfo{
Link: v.Link,
Weight: 100,
Foreign: false,
})
doc := advertiseMod.UpdateAds{
Links: &links,
}
err = advertiseMod.UpdateAdvertise(ctx, v.Id, doc)
if err != nil {
fmt.Println(err)
}
}
return nil
}
// func UserStatInfo() error {
// ctx := context.Background()
// userList, err := registermod.TimeUsersStatInfoByTime(ctx, 1)
// if err != nil {
// return err
// }
// fmt.Println(len(userList))
// userIds := make([]uint64, 0)
// for _, v := range userList {
// if v.AppId == 1 {
// userIds = append(userIds, v.UserId)
// }
// }
// dspuserList, _ := model.FindManyUserInfo(ctx, userIds)
// writeModels := make([]mongo.WriteModel, 0)
// for _, v := range dspuserList {
// model := mongo.NewUpdateOneModel()
// filter := bson.M{"userId": v.UID, "appId": 1}
// update := bson.M{"$set": bson.M{"promCode": v.PromCode}}
// model.SetFilter(filter).SetUpdate(update)
// writeModels = append(writeModels, model)
// fmt.Println(filter, update)
// }
// fmt.Println("update.............")
// err = registermod.UpdateRegisterInfo(ctx, writeModels)
// if err != nil {
// log.Error("SyncUserInfo UpdateRegisterInfo", log.E(err))
// return err
// }
// return nil
// }
View File
+791
View File
@@ -0,0 +1,791 @@
package main
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
"strings"
"go.uber.org/zap/zapcore"
"go.uber.org/zap"
)
var sbr, ser, mbr, mer *regexp.Regexp
var out *bufio.Writer
var model string
var log *zap.SugaredLogger
type table struct {
tableName string
// <字段名、bson名>
filedInfo map[string]interface{}
}
var rootPath string
var dealPath string
var tmpPath string
func init() {
zl, _ := zap.NewDevelopment(zap.IncreaseLevel(zapcore.WarnLevel))
log = zl.Sugar()
// rootPath = "/Volumes/work/prj" // 项目根目录
currDir, _ := os.Getwd() // 获取当前目录
rootPath = func() string {
v := LookupProjectRootByGomod()
if v != "" {
return v
}
// 获取上四级目录
// rootPath = strCurrDir+"/../../../../"
return getParentDir(getParentDir(currDir))
}()
dealPath = "/pub/models" // 处理目录
tmpPath = "/temp" // 临时目录
}
func LookupProjectRootByGomod() string {
currDir, _ := os.Getwd()
var dir = currDir
for {
found, err := isProjectRoot(dir)
if err != nil {
return ""
}
if found {
break
}
dir = filepath.Dir(dir)
if dir == "/" {
return ""
}
}
return dir
}
func isProjectRoot(dir string) (bool, error) {
modFileName := filepath.Join(dir, "go.mod")
_, err := os.Stat(modFileName)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// 验证go.mod文件
f, err := os.Open(modFileName)
if err != nil {
return false, err
}
data, err := ioutil.ReadAll(io.LimitReader(f, 20))
if err != nil {
return false, err
}
if bytes.Contains(data, []byte("module stat")) {
return true, nil
}
return false, nil
}
func getCurDir() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
// log.Fatal(err)
fmt.Sprint(err)
}
return strings.Replace(dir, "\\", "/", -1)
}
func substr(s string, pos, length int) string {
runes := []rune(s)
l := pos + length
if l > len(runes) {
l = len(runes)
}
return string(runes[pos:l])
}
func getParentDir(dir string) string {
return substr(dir, 0, strings.LastIndex(dir, "/"))
}
func shellCmd(cmdStr string) (string, error) {
cmd := exec.Command("/bin/bash", "-c", cmdStr)
var outb bytes.Buffer
var errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
ec := cmd.Run()
log.Infof("command: %s", cmdStr)
if outb.Len() > 0 {
log.Debug("stdout: %s", outb.String())
}
if errb.Len() > 0 {
log.Errorf("stderr: %s", errb.String())
}
return outb.String(), ec
}
func parseStruct(tbName string, br *bufio.Reader) map[string]interface{} {
subStructName := regexp.MustCompile("(\\w+)\\s+struct\\s{$")
// endFlag := regexp.MustCompile(`}`)
endFlag := regexp.MustCompile(`}`)
// <字段名、tag名>
filedInfo := make(map[string]interface{})
for {
line, _, ec := br.ReadLine()
if nil != ec {
return filedInfo
}
if strings.HasPrefix(strings.TrimSpace(string(line)), "//") {
continue
}
if "" == string(line) {
continue
}
end := endFlag.FindStringSubmatch(string(line))
if len(end) > 0 {
log.Info("end ...")
return filedInfo
}
log.Infof(string(line))
if subStruct := subStructName.FindStringSubmatch(string(line)); len(subStruct) > 0 {
subFiledInfo := parseStruct(subStruct[1], br)
filedInfo[subStruct[1]] = &table{
tableName: subStruct[1],
filedInfo: subFiledInfo,
}
continue
}
flags := strings.Split(string(line), "bson")
if len(flags) > 1 {
tag := regexp.MustCompile(":\"(\\w+)\"")
dst := tag.FindStringSubmatch(flags[1])
dstName := ""
if len(dst) < 1 {
// 带有omit的
tagomt := regexp.MustCompile(":\"(\\w+),omitempty\"")
dst = tagomt.FindStringSubmatch(flags[1])
dstName = dst[1]
} else {
dstName = dst[1]
}
filedName := strings.Split(strings.TrimSpace(string(line)), " ")
log.Info("aaaaa, ", filedName[0], " -> ", dstName)
// structBuf += fmt.Sprintf("const T%s%s = \"%s\"\n", tbName, filedName[0], dstName)
filedInfo[filedName[0]] = dstName
} else if strings.Contains(string(line), "\"inline\"") {
// 内联结构体
continue
} else {
log.Error("parse bson is failed, code = ", string(line))
os.Exit(1)
}
}
}
func makeStr(tab table, parentTab string) (string, string) {
structsBuf := fmt.Sprintf("//%s\n", tab.tableName)
if "" != parentTab {
structsBuf += fmt.Sprintf("%s struct {\n", tab.tableName)
} else {
structsBuf += fmt.Sprintf("type Tag%s struct {\n", tab.tableName)
}
initsBuf := fmt.Sprintf("\n")
var sortedNames []string
for name, _ := range tab.filedInfo {
sortedNames = append(sortedNames, name)
}
sort.Strings(sortedNames)
for _, filedName := range sortedNames {
field := tab.filedInfo[filedName]
switch field.(type) {
case string:
structsBuf += fmt.Sprintf("%s string\n", filedName)
if "" != parentTab {
initsBuf += fmt.Sprintf("Fn%s.%s.%s = \"%v\"\n", parentTab, tab.tableName, filedName, field)
} else {
initsBuf += fmt.Sprintf("Fn%s.%s = \"%v\"\n", tab.tableName, filedName, field)
}
case *table:
subTab := field.(*table)
var buf1, buf2 string
if "" != parentTab {
buf1, buf2 = makeStr(*subTab, parentTab+"."+tab.tableName)
} else {
buf1, buf2 = makeStr(*subTab, tab.tableName)
}
structsBuf += buf1
initsBuf += buf2
}
}
structsBuf += fmt.Sprintf("}\n\n\n")
initsBuf += fmt.Sprintf("\n")
return structsBuf, initsBuf
}
func getAllModel(fileName string) []string {
cmd := fmt.Sprintf(`cat %s | grep "^type " | grep "struct {$" | awk '{print $2}' | tr "\n" " "`, fileName)
output, err := shellCmd(cmd)
if nil != err {
panic(err)
}
models := strings.Split(output, " ")
return models[:len(models)-1]
}
func parseOrm(fileName string) (resultFileBuf string) {
models := getAllModel(fileName)
log.Info(fileName, models)
// 构建临时文件
return ""
packageName, _ := shellCmd(fmt.Sprintf(`cat %s | grep ^package | awk '{print $2}'`, fileName))
packageName = strings.TrimSpace(packageName)
if "" == packageName {
log.Errorf("can not parse package name, stop it")
os.Exit(1)
}
var tables []table
defer func() {
if len(tables) > 0 {
resultFileBuf = fmt.Sprintf("package %s\n", packageName)
structsBuf := ""
initsBuf := "func init() {"
for _, v := range tables {
buf1, buf2 := makeStr(v, "")
structsBuf += buf1
initsBuf += buf2
}
initsBuf += fmt.Sprintf("\n}\n")
resultFileBuf += structsBuf
resultFileBuf += fmt.Sprintf("\n\n\n\n\n")
for _, v := range tables {
resultFileBuf += fmt.Sprintf("var Fn%s Tag%s\n", v.tableName, v.tableName)
}
resultFileBuf += initsBuf
resultFileBuf += fmt.Sprintf("\n")
}
}()
// structsBuf := "package " + packageName + "\n"
// fnsBuf := "func init() {\n"
// initBuf := ""
tableName := regexp.MustCompile("^type\\s+(\\w+)\\s+struct\\s{$")
// endFlag := regexp.MustCompile(`}`)
file, _ := os.Open(fileName)
br := bufio.NewReader(file)
// inStruct := false
// tbName := ""
for {
line, _, ec := br.ReadLine()
if nil != ec {
return
}
names := tableName.FindStringSubmatch(string(line))
if len(names) > 1 {
log.Info("begin -> ", names[1])
// tbName = names[1]
// structBuf := ("//" + names[1] + "\n")
// structBuf += fmt.Sprintf("type Tag%s struct {\n", tbName)
// inStruct = true
filedInfo := parseStruct(names[1], br)
tables = append(tables, table{
tableName: names[1],
filedInfo: filedInfo,
})
continue
}
}
}
func writeGoFile(packageName string, packgePath string, tableMetas []TableMeta, dstFile string) {
// orms := `[]interface{}{orm.UserEx{}, orm.User{}}`
// shellCmd(fmt.Sprintf("rm -f %s/src/%s/tag.go", os.Getenv("GOPATH"), packgePath))
// orms := `[]interface{}`
// for k, _ := range tableNames {
// tableNames[k] = "orm." + tableNames[k] + "{}"
// }
var tbOrms []string
var cmdParams []string
for _, meta := range tableMetas {
tbOrms = append(tbOrms, "orm."+meta.StructName+"{}")
cmdParams = append(cmdParams, fmt.Sprintf("%v--%v", meta.StructName, meta.DbName))
}
// strCmdParam := strings.Join(cmdParams, "---")
strCmdParam := func() string {
data, _ := json.Marshal(tableMetas)
return base64.StdEncoding.EncodeToString([]byte(data))
}()
orms := "[]interface{}{" + strings.Join(tbOrms, ",") + "}"
buf := []byte(`package main
import (
// orm "PACKAGE-PATH"
orm "stat/temp/orm"
"fmt"
"io/ioutil"
"os"
"reflect"
"strings"
"sort"
"encoding/json"
"encoding/base64"
)
func getBson(ormName string, tag string) string {
if tag == "" {
panic(ormName + "miss bson tag")
}
array := strings.Split(tag, ",")
if len(array) <= 1 {
return tag
}
return strings.TrimSpace(array[0])
}
type fieldStruct struct {
parentTag string
parentName string
subFieldInfo map[string]string
}
func parse(param interface{}, tab int) map[string]interface{} {
fieldData := make(map[string]interface{})
t := reflect.TypeOf(param)
v := reflect.ValueOf(param)
for i := 0; i < v.NumField(); i++ {
if v.Field(i).CanInterface() {
if v.Field(i).Type().Kind() == reflect.Struct {
if "time.Time" == fmt.Sprintf("%v", t.Field(i).Type) {
fieldData[t.Field(i).Name] = getBson(t.Field(i).Name, t.Field(i).Tag.Get("bson"))
continue
}
structField := v.Field(i).Type()
//fmt.Printf("%v %v\n", t.Field(i).Name, t.Field(i).Tag)
subFields := &fieldStruct{
parentTag: getBson(t.Field(i).Name, t.Field(i).Tag.Get("bson")),
parentName: t.Field(i).Name,
subFieldInfo: make(map[string]string),
}
for j := 0; j < structField.NumField(); j++ {
// fmt.Printf(" %s %s \n",
// structField.Field(j).Name,
// structField.Field(j).Tag)
subFields.subFieldInfo[structField.Field(j).Name] = getBson(structField.Field(j).Name, structField.Field(j).Tag.Get("bson"))
}
fieldData[t.Field(i).Name] = subFields
continue
}
// fmt.Printf("%s %s \n",
// t.Field(i).Name,
// t.Field(i).Tag)
fieldData[t.Field(i).Name] = getBson(t.Field(i).Name, t.Field(i).Tag.Get("bson"))
}
}
return fieldData
}
type TableMeta struct {
StructName string
DbName string
}
func main() {
param := PARAM
packageName := "PACKAGE-NAME"
structsBuf := fmt.Sprintf("package %s \n", packageName)
initsBuf := "func init() {\n"
tabsBuf := "var FN struct {\n"
decodeMetas := func(arg string) []TableMeta {
v, _ := base64.StdEncoding.DecodeString(strings.TrimSpace(arg))
var tableMetas []TableMeta
if err := json.Unmarshal([]byte(v), &tableMetas); err != nil {
panic(err)
}
return tableMetas
}
tableMetas := decodeMetas(os.Args[1])
for _, v := range param {
fieldInfo := parse(v, 0)
if len(fieldInfo) > 0 {
keys := make([]string, 0, len(fieldInfo))
hasID := false
for fieldname, fieldTag := range fieldInfo {
keys = append(keys,fieldname)
switch fieldTag.(type) {
case string:
tempStr := fieldTag.(string)
if tempStr == "_id" {
hasID = true
}
}
}
if !hasID {
panic("table miss _id")
}
sort.Strings(keys)
temp := reflect.TypeOf(v)
tabNames := strings.Split(fmt.Sprintf("%v", temp), ".")
tabName := "Tag" + tabNames[1]
tabsBuf += fmt.Sprintf("%s %s\n", tabNames[1], tabName)
structsBuf += fmt.Sprintf("type %s struct {\n", tabName)
for _, fieldname := range keys {
fieldTag := fieldInfo[fieldname]
switch fieldTag.(type) {
case *fieldStruct:
subStruct := fieldTag.(*fieldStruct)
// 嵌套字段也排序
var sortedFieldNames []string
for subFieldName := range subStruct.subFieldInfo {
sortedFieldNames = append(sortedFieldNames, subFieldName)
}
sort.Strings(sortedFieldNames)
structsBuf += fmt.Sprintf("%s struct {\n", subStruct.parentName)
for _, subFieldName := range sortedFieldNames {
subFieldTag := subStruct.subFieldInfo[subFieldName]
structsBuf += fmt.Sprintf("%s string\n", subFieldName)
initsBuf += fmt.Sprintf("FN.%s.%s.%s = \"%s.%s\"\n", tabNames[1], subStruct.parentName, subFieldName, subStruct.parentTag, subFieldTag)
}
structsBuf += "}\n"
default:
structsBuf += fmt.Sprintf("%s string\n", fieldname)
initsBuf += fmt.Sprintf("FN.%s.%s = \"%s\"\n", tabNames[1], fieldname, fieldTag)
}
}
structsBuf += "}\n"
}
}
//initsBuf += "}\n"
tabsBuf += "}\n\n\n"
//tabsBuf += "var FN XXX\n\n"
tabsBuf += "var TN struct {\n"
//tabsBuf += "var FN XXX\n\n"
for _, meta := range tableMetas {
tabsBuf += fmt.Sprintf("%s string\n", meta.StructName)
initsBuf += fmt.Sprintf("TN.%v = \"%v\"\n", meta.StructName, meta.DbName)
}
tabsBuf += "}\n"
initsBuf += "}\n"
totalBuf := structsBuf + tabsBuf + initsBuf
fmt.Println(totalBuf)
err3 := ioutil.WriteFile(fmt.Sprintf("%s/%s/tag.go", "PACKAGE-ROOTPATH", "PACKAGE-PATH"), []byte(totalBuf), 0777)
// err3 := ioutil.WriteFile(fmt.Sprintf("%s/%s/tag_1.go", "PACKAGE-ROOTPATH", "PACKAGE-PATH"), []byte(totalBuf), 0777)
// err3 := ioutil.WriteFile(fmt.Sprintf("%s/src/%s/tag.go", os.Getenv("GOPATH"), "PACKAGE-PATH"), []byte(totalBuf), 0777)
fmt.Println("write file, err = ", err3)
}`)
ioutil.WriteFile(dstFile, buf, 0777)
// shellCmd(fmt.Sprintf(`echo "%s" > %s`, string(buf), dstFile))
cmd := fmt.Sprintf(`sed -i '' 's#PACKAGE-PATH#%s#g' %s`, packgePath, dstFile)
shellCmd(cmd)
// fmt.Println(cmd)
// output, err := shellCmd(cmd)
// fmt.Println(err, output)
cmd = fmt.Sprintf(`sed -i '' 's#PACKAGE-ROOTPATH#%s#g' %s`, rootPath, dstFile)
shellCmd(cmd)
cmd = fmt.Sprintf(`sed -i '' 's/PACKAGE-NAME/%s/g' %s`, packageName, dstFile)
shellCmd(cmd)
cmd = fmt.Sprintf(`sed -i '' 's/PARAM/%s/g' %s`, orms, dstFile)
shellCmd(cmd)
cmd = "go run " + dstFile + " " + strCmdParam
shellCmd(cmd)
cmd = fmt.Sprintf(`go fmt %s`, rootPath+"/"+packgePath+"/tag.go")
shellCmd(cmd)
}
type TableMeta struct {
StructName string
DbName string
}
// 返回值:<结构体名、表名>
func getOrmName(servicePath string) []TableMeta {
tableMetas := make([]TableMeta, 0)
tableName := regexp.MustCompile("^type\\s+(\\w+)\\s+struct\\s{$")
files, _, _ := GetFilesAndDirs(servicePath)
for _, file := range files {
if "tag.go" != file {
fileBuf, _ := os.Open(file)
br := bufio.NewReader(fileBuf)
// inStruct := false
tbName := ""
// hasFlag := false
for {
line, _, ec := br.ReadLine()
if nil != ec {
break
}
if strings.HasPrefix(string(line), "// @table:") {
temp := strings.Split(string(line), ":")
tbName = strings.TrimSpace(temp[1])
if "" == tbName {
panic("tb name is empty, error table description")
}
// hasFlag = true
continue
}
if "" != tbName {
if names := tableName.FindStringSubmatch(string(line)); len(names) > 0 {
log.Infof("有效表结构: (%v -> %v)\n", names[1], tbName)
// tabs = append(tabs, names[1])
// tabs[names[1]] = tbName
tableMetas = append(tableMetas, TableMeta{
StructName: names[1],
DbName: tbName,
})
}
}
// hasFlag = false
tbName = ""
}
}
}
return tableMetas
}
func genTagImpl(servicePath string) {
// path := servicePath
// files, err := ioutil.ReadDir(path)
// if err != nil {
// fmt.Println("read dir faild:", err.Error())
// return
// }
// fileBuf := "\n\n\n"
// for _, file := range files {
// if "tag.go" != file.Name() && strings.HasSuffix(file.Name(), ".go") {
// fileBuf += parseOrm(path + "/" + file.Name())
// }
// }
// if len(fileBuf) > 100 {
// shellCmd(fmt.Sprintf(`echo '%s' > %s`, fileBuf, path+"/tag.go"))
// shellCmd("go fmt " + path + "/tag.go")
// }
cmd := fmt.Sprintf(`ls -l %s | grep type.go | grep -v "^d"| grep -v "tag.go" | tail -n 1 | awk '{print $NF}'`, servicePath)
output, err := shellCmd(cmd)
if err != nil {
panic("has error, " + cmd)
}
output = strings.TrimSpace(output)
cmd = fmt.Sprintf(`cat %s/%s | grep "^package " | awk '{print $2}'`, servicePath, output)
packageName, err2 := shellCmd(cmd)
if err2 != nil {
panic("has error, " + cmd)
}
packageName = strings.TrimSpace(packageName)
// gopath := os.Getenv("GOPATH")
// packagePath := strings.TrimLeft(servicePath, gopath+"/")
packagePath := strings.TrimPrefix(servicePath, rootPath+"/")
log.Infof("处理%v包...", packageName)
tableMetas := getOrmName(rootPath + "/" + packagePath)
if len(tableMetas) <= 0 {
return
}
// shellCmd("mkdir -p $GOPATH/src/plus/server/temp")
// shellCmd("rm -rf $GOPATH/src/plus/server/temp")
shellCmd(fmt.Sprintf("rm -rf %s%s", rootPath, tmpPath))
// shellCmd("mkdir -p $GOPATH/src/plus/server/temp/orm")
// strTest := fmt.Sprintf("------------- mkdir -p %s%s/orm", rootPath, tmpPath)
// fmt.Println(strTest)
shellCmd(fmt.Sprintf("mkdir -p %s%s/orm", rootPath, tmpPath))
// shellCmd("mkdir -p "+rootPath+tmpPath+"/orm")
// shellCmd("cp $GOPATH/src/" + packagePath + "/*_define.go $GOPATH/src/plus/server/temp/orm/")
shellCmd("cp " + rootPath + "/" + packagePath + "/type.go " + rootPath + tmpPath + "/orm/")
// writeGoFile(packageName, packagePath, tabs, os.Getenv("GOPATH")+"/src/plus/server/temp/main.go")
writeGoFile(packageName, packagePath, tableMetas, fmt.Sprintf("%s%s/main.go", rootPath, tmpPath))
// output, err = shellCmd(``)
// _, err = shellCmd(`cat `)
// writeGoFile(packageName, packagePath)
}
// 获取指定目录下的所有文件和目录
func GetFilesAndDirs(dirPth string) (files []string, dirs []string, err error) {
dir, err := ioutil.ReadDir(dirPth)
if err != nil {
return nil, nil, err
}
PthSep := string(os.PathSeparator)
// suffix = strings.ToUpper(suffix) //忽略后缀匹配的大小写
dirs = append(dirs, dirPth)
for _, fi := range dir {
if fi.IsDir() { // 目录, 递归遍历
dirs = append(dirs, dirPth+PthSep+fi.Name())
GetFilesAndDirs(dirPth + PthSep + fi.Name())
} else {
// 过滤指定格式
ok := strings.HasSuffix(fi.Name(), ".go")
if ok {
files = append(files, dirPth+PthSep+fi.Name())
}
}
}
return files, dirs, nil
}
// 获取指定目录下的所有文件,包含子目录下的文件
func GetAllFiles(dirPth string) (files []string, err error) {
var dirs []string
dir, err := ioutil.ReadDir(dirPth)
if err != nil {
return nil, err
}
PthSep := string(os.PathSeparator)
// suffix = strings.ToUpper(suffix) //忽略后缀匹配的大小写
for _, fi := range dir {
if fi.IsDir() { // 目录, 递归遍历
dirs = append(dirs, dirPth+PthSep+fi.Name())
GetAllFiles(dirPth + PthSep + fi.Name())
} else {
// 过滤指定格式
ok := strings.HasSuffix(fi.Name(), ".go")
if ok {
files = append(files, dirPth+PthSep+fi.Name())
}
}
}
// 读取子目录下文件
for _, table := range dirs {
temp, _ := GetAllFiles(table)
for _, temp1 := range temp {
files = append(files, temp1)
}
}
return files, nil
}
func genTag(path string) {
_, dirs, _ := GetFilesAndDirs(path)
for _, dir := range dirs {
subFiles, _, _ := GetFilesAndDirs(dir)
if len(subFiles) > 0 {
genTagImpl(dir)
}
}
}
// func genTag1(path string) {
// genTagImpl(path)
// }
func main() {
path := ""
if "" == path {
path = rootPath + dealPath
}
flag.StringVar(&model, "m", "", "指定要生成的model,不指定则生成所有model")
flag.Parse()
if model != "" {
path = filepath.Join(path, model)
}
genTagImpl("/Users/mac/code/stat_center/models/channelmod")
}
+93
View File
@@ -0,0 +1,93 @@
package pubtest
import (
"fmt"
"os"
"stat/common/config"
"stat/common/genId"
"stat/common/log"
"stat/common/mongos"
"stat/common/redis"
"stat/models"
"stat/service/cacheSer"
"stat/statg"
"time"
)
func TestInit(workPath string) error {
// 设置时区
time.Local, _ = time.LoadLocation("Asia/Shanghai")
// 更换工作目录
pwd, _ := os.Getwd()
fmt.Println("开始工作目录", pwd)
if err := os.Chdir(workPath); err != nil {
return err
}
// 初始化配置文件
if err := initConfig(); err != nil {
return err
}
// 恢复工作目录
if err := os.Chdir(pwd); err != nil {
return err
}
// 初始化数据库
if err := initMongoDB(); err != nil {
return err
}
// 初始化redis
if err := initRedis(); err != nil {
return err
}
// 初始化缓存
cacheSer.Init()
// 自增id
genId.Start()
return nil
}
func initConfig() error {
err := config.LoadJSON("conf/server.json", &statg.Conf)
if err != nil {
log.Fatal("加载本地配置失败", log.E(err))
return err
}
// set default value
if statg.Conf.Limit.Ip.Capacity <= 0 {
statg.Conf.Limit.Ip.Capacity = 300
}
if statg.Conf.Limit.Ip.Rate <= 0 {
statg.Conf.Limit.Ip.Rate = 5
}
statg.Tgbotsend = statg.Conf.TgbotSend
return nil
}
func initMongoDB() error {
mgoDB := mongos.NewManager(statg.Conf.Mongo.Url)
if err := mgoDB.Connect(); err != nil {
log.Error("mgoDB connect err", log.E(err))
return err
}
mongos.MgoManager = mgoDB
// 初始化数据库索引
models.InitIndex()
return nil
}
func initRedis() error {
rds, err := redis.NewManagerWithUrl(statg.Conf.Redis.Url, nil)
if err != nil {
log.Error("rds init err", log.E(err))
return err
}
redis.StatRds = rds
return nil
}
+25
View File
@@ -0,0 +1,25 @@
package main
import (
"stat/common/log"
"stat/tool/sqSync/model"
"stat/tool/sqSync/service"
)
func initMongoDB() error {
if err := model.InitMongoDB(); err != nil {
log.Error("InitMongoDB err", log.E(err))
return err
}
return nil
}
func main() {
initMongoDB()
// _ = service.SyncDistrictInfo()
_ = service.SyncUserInfo()
// _ = service.SyncAdsInfo()
}
+89
View File
@@ -0,0 +1,89 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"time"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson"
)
// DistrictInfo 渠道原始信息
type DistrictInfo struct {
Code string `bson:"code"` //商区码
Name string `bson:"name"` //账号
Mobile string `bson:"mobile"` //手机号
Parent string `bson:"parent"` //parent
Password string `bson:"password"` //密码
DiscType int `bson:"discType"` //商区类型/结算类型
DividendRatio float64 `bson:"dividendRatio"` //分红比例 参与结算
DisSettlement bool `bson:"disSettlement"` //禁止结算
UserUnitCent float64 `bson:"userUnitCent"` //用户单价 单位:分
NUDeductionRatio float64 `bson:"nuDeductionRatio"` //新增用户扣量比例
NUDedLowerOutset int64 `bson:"nuDedLowerOutset"` //新增用户扣量起点
NUDedAt time.Time `bson:"nuDedAt"` //新增用户扣量时间
RechgDeductionRatio float64 `bson:"rechgDeductionRatio"` //充值扣量比例
RechgDedLowerOutset int64 `bson:"rechgDedLowerOutset"` //充值扣量起点
RechgDedAt time.Time `bson:"rechgDedAt"` //充值扣量时间
ChildMax int `bson:"childMax"` //最大孩子数
Disable bool `bson:"disable"` //禁用
Lock bool `bson:"lock"` //禁止登陆
DisTrans bool `bson:"disTrans"` //禁止交易
DisAd bool `bson:"disAd"` //禁止广告
DisMulDivi bool `bson:"disMulDivi"` //禁止多级分成(目前针对CPS)
PayPassword string `bson:"payPassword"` //支付密码
BalanceCent decimal.Decimal `bson:"balance"` //余额 单位:分
Remark string `bson:"remark"` //备注
CreatedAt time.Time `bson:"createdAt"` //文档创建时间
UpdatedAt time.Time `bson:"updatedAt"` //文档更新时间
}
// YhDistrictCodeInfo 渠道码信息
type YhDistrictCodeInfo struct {
DiscCode string `bson:"discCode"` //商圈码
PromSeq string `bson:"promSeq"` //推广序列
Remark string `bson:"remark"` //备注
PromCode string `bson:"promCode"` //备注
CreatedAt time.Time `bson:"createdAt"`
DeletedAt time.Time `bson:"deletedAt,omitempty"` //删除时间
}
const CollDistrict = "district"
const CollDistrictCode = "disc_prom_seqe"
var dbDistrict *mongos.MongoTool
var dbDistrictcode *mongos.MongoTool
func DistrictInit() {
dbDistrict = mongos.New(ManagerYh, CollDistrict)
dbDistrictcode = mongos.New(ManagerYh, CollDistrictCode)
}
// FindYhDistrictInfo 查询所有渠道
func FindSQDistrictInfo(ctx context.Context) ([]DistrictInfo, error) {
list := make([]DistrictInfo, 0)
query := bson.M{}
if err := dbDistrict.Find(ctx, &list, query); err != nil {
log.Error(fmt.Sprintf("model %s FindYhDistrictInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
// FindSQDistrictCodeInfo 查询渠道的渠道码
func FindSQDistrictCodeInfo(ctx context.Context, discCode string) ([]YhDistrictCodeInfo, error) {
list := make([]YhDistrictCodeInfo, 0)
query := bson.M{"discCode": discCode}
if err := dbDistrictcode.Find(ctx, &list, query); err != nil {
log.Error(fmt.Sprintf("model %s FindYhDistrictInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
+39
View File
@@ -0,0 +1,39 @@
package model
import (
"fmt"
"stat/common/log"
"stat/common/mongos"
"stat/models"
)
var (
ManagerYh *mongos.Manager
ManagerStat *mongos.Manager
)
// InitMongoDB 初始化同步数据库
func InitMongoDB() error {
yhDB := mongos.NewManager("mongodb://read:6zwcDUpPy7dMkLTeWwHX@172.104.42.200:47017,139.162.18.46:47017,139.162.35.214:47017/sz?direct=game&maxPoolSize=200&connectTimeout=30&authSource=admin")
if err := yhDB.Connect(); err != nil {
log.Error("mgoDB connect err", log.E(err))
return err
}
ManagerYh = yhDB
// 初始化表链接
DistrictInit()
UserInit()
statDB := mongos.NewManager("mongodb://bill:E4OSVEd6zuWibxJo@118.107.44.79:47017/statcentre?direct=game&maxPoolSize=200&connectTimeout=30&authSource=statcentre")
if err := statDB.Connect(); err != nil {
log.Error("mgoDB connect err", log.E(err))
return err
}
mongos.MgoManager = statDB
fmt.Println(statDB)
// 初始化数据库索引
models.InitIndex()
return nil
}
+48
View File
@@ -0,0 +1,48 @@
package model
import (
"context"
"fmt"
"stat/common/log"
"stat/common/mongos"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
type YhUser struct {
UID uint64 `json:"id" bson:"id"` //用户id
SysType string `json:"sysType" bson:"sysType"` //系统类型
DevType string `json:"deviceType" bson:"deviceType"` //设备类型
Mobile string `json:"mobile" bson:"mobile"` //手机号
Name string `json:"nickName" bson:"nickName"` //名字
DistrictCode string `json:"agentInviteCode" bson:"agentInviteCode"` //商区码
PromSeqe string `json:"promSeqe" bson:"promSeqe"` //推广序列
PromCode string `json:"inviteCode" bson:"inviteCode"` //邀请码
IsDirect bool `json:"isDirect" bson:"isDirect"` //true:是直推用户
CreatedAt time.Time `bson:"createdAt"` //文档创建时间
}
const CollUser = "server_user"
var dbUser *mongos.MongoTool
func UserInit() {
dbUser = mongos.New(ManagerYh, CollUser)
}
// FindSQUserInfo 查询用户
func FindSQUserInfo(ctx context.Context, skip int64, limit int64) ([]YhUser, error) {
list := make([]YhUser, 0)
query := bson.M{}
sort := bson.D{{Key: "_id", Value: 1}}
opts := options.Find().SetSkip(skip).SetLimit(limit).SetSort(sort).SetProjection(bson.M{"id": 1, "sysType": 1, "deviceType": 1, "mobile": 1, "nickName": 1, "agentInviteCode": 1, "inviteCode": 1, "isDirect": 1, "createdAt": 1})
if err := dbUser.Find(ctx, &list, query, opts); err != nil {
log.Error(fmt.Sprintf("model %s FindYhUserInfo Find error", CollDistrict), log.E(err))
return list, err
}
return list, nil
}
+141
View File
@@ -0,0 +1,141 @@
package service
import (
"context"
"stat/common/log"
"stat/models/registermod"
"stat/tool/sqSync/model"
)
func SyncUserInfo() error {
skip := int64(0)
limit := int64(10000)
ctx := context.Background()
//fmt.Println("before delete:", skip)
for {
//fmt.Println(skip)
userlist, err := model.FindSQUserInfo(ctx, skip, limit)
if err != nil {
log.Error("SyncUserInfo FindSQUserInfo", log.E(err))
return err
}
// 转换
//fmt.Println(len(userlist))
docs := make([]*registermod.RegisterMod, 0)
for _, userInfo := range userlist {
doc := registermod.RegisterMod{
UserId: userInfo.UID,
AppId: 2,
SysType: userInfo.SysType,
DevType: userInfo.DevType,
Mobile: userInfo.Mobile,
Name: userInfo.Name,
IsDirect: userInfo.IsDirect,
DistrictCode: userInfo.DistrictCode,
RegisterTime: userInfo.CreatedAt,
IsDeduction: false,
PromCode: userInfo.PromCode,
}
docs = append(docs, &doc)
}
if err = registermod.AddManyRegisterCode(ctx, &docs); err != nil {
log.Error("SyncUserInfo AddManyRegisterCode", log.E(err))
return err
}
// 插入数据库
skip = skip + int64(len(userlist))
//fmt.Println(skip)
if int64(len(userlist)) < limit {
log.Info("SyncUserInfo total:", log.Any("total", skip))
return nil
}
}
}
/*
滑动窗口告诉发送端 接收端还有多少缓冲去可以接受数据, 于是发送端可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来
以此控制发送数据的速率,从而达到流量控制,窗口大小是一个16bit字段,大小65536 socket的接收缓冲区大小
CLose sync =1 seq=x
syc-send sync=1 ACK=1 seq=y ack=x=1 listen
EStablisend ACK=1 seq=x+1 ack=y+1 SYNC-Recv
Fin——wait FIN =1 seq
fin_wait2 ACk=1 seq=v ack=u+1
FIN=1,acl
半关闭状态, 客户端没有数据发送来 closewait 半关闭状态
Timewait 和closewait的区别:
timewait 指主动发起关闭连接方 在收到对端 fin +ack后进入等待关闭,施放
确保客户端发送的最后一个ACK报文能够到达服务器,因为ACK可能丢失, 服务器可能认为没收到,启动超时从传机制,导致服务器处理close_wait状态,新的连接不会出现旧连接报文
closewait 被动关闭的机器接收到对方请求关闭的fin豹纹,在第一次ACK应答后,进入close——wait状态, 同志应用层发送剩余数据,关闭相关资源
我们一般在/etc/sysctl.conf文件中来修改默认值
滑动窗口
动态改变窗口大小来调节两台主机间数据传输,tcp/IP支持全双工的数据传输,因此TCP有两个滑动串口, 一个用于接收, 一个用于发送
TCP的确认机制,滑动串口是TCP使用的一种流量控制方法,该协议允许发送在同志并等待确认前可以连续发送多个分组,犹豫发送方不必每发送一个分组就停止袭来等待确认,因此该协议
可以加速数据船
流量控制,端到端,接收端额应用层处理速度决定
分布式一致性
对于一个分布式系统而言,分区容错性是一个最基本的要求,因此既然是一个分布式系统,那么分布式系统中的组件必然需要被部署到不同的节点
分区容错性也就成为一个分布式系统必然需要面对和解决的问题,因此系统架构师往往把精力花在如何根据业务特点在C一致性和A可用性之前寻求平衡
base理论
基本可用 出现不可预知状态时,允许
软状态,允许数据存在中间状态,并认为该状态不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
最终一致性
最终一致性 强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一直的状态,因此最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的
强一致性。
大型高可用可扩展的分布式系统和传统ACID特性相反, 牺牲强一致性来活动可用性,
A 原子性 一致性 隔离性能 持久性
etcd就是使用raft算法来保持数据一致性的 与raft类似的还有POXOS算法和 ZAB协议等
etcd和console
leader 和 follower
选举超时时间 一定周期/时间 150ms-300ms 之间的随机数 心跳<选举周期
选举周期
周期数
面对对象编程:
封装
public、pretected、private
继承
多态
nginx 是以even处理模型为基础摩卡,它为了支持跨平台,抽象出了event模块,一部IO,主要是epoll
event模块的主要功能就是监听,监听accept后建立的连接,对读写事件进行添加删除,事件处理模型和nginx的非阻塞IO模型结合在一起使用,当IO可读可写的时候,相应的事件就会被唤醒
此时就会处理事件的回掉函数
面试:
拓扑:
*/
+25
View File
@@ -0,0 +1,25 @@
package main
import (
"stat/common/log"
"stat/tool/yc/model"
"stat/tool/yc/service"
"time"
)
func initMongoDB() error {
if err := model.InitMongoDB(); err != nil {
log.Error("InitMongoDB err", log.E(err))
return err
}
return nil
}
func main() {
initMongoDB()
time.Local, _ = time.LoadLocation("Asia/Shanghai")
_ = service.SyncUserInfo()
}
+25
View File
@@ -0,0 +1,25 @@
package model
import (
"fmt"
"stat/common/log"
"stat/common/mongos"
"stat/models"
)
// InitMongoDB 初始化同步数据库
func InitMongoDB() error {
statDB := mongos.NewManager("mongodb://stat:7u9CUAEE1Nv2tSvz@192.53.118.36:47017,192.53.173.209:47017,139.162.65.62:47017,172.105.237.106:47017,172.105.189.212:47017/stat?replicaSet=MDstat&maxPoolSize=200&connectTimeout=30&authSource=stat")
if err := statDB.Connect(); err != nil {
log.Error("mgoDB connect err", log.E(err))
return err
}
mongos.MgoManager = statDB
// 初始化数据库索引
models.InitIndex()
fmt.Println("init")
return nil
}
+83
View File
@@ -0,0 +1,83 @@
package service
import (
"context"
"stat/common/log"
"stat/common/utils"
"stat/models/syncvip"
"time"
"go.mongodb.org/mongo-driver/bson"
)
func SyncUserInfo() error {
ctx := context.Background()
end := utils.BeginOfToday()
start := end.AddDate(0, 0, -1)
registerMap := make(map[time.Time]int64)
filter := bson.M{
syncvip.FN.SyncVip.AppId: 888,
syncvip.FN.SyncVip.SuccessAt: bson.M{"$gte": start, "$lt": end},
}
VipList, err := syncvip.FindManySyncVip(ctx, filter)
if err != nil {
log.Error("ChannelChannelStatMethod FindManyVisitInfo ", log.E(err))
return err
}
//fmt.Println(len(VipList))
for _, orderinfo := range VipList {
registerTime := utils.BeginWithTime(orderinfo.RegisterTime)
if registerTime.Before(start.AddDate(0, 0, -20)) {
continue
}
if money, ok := registerMap[registerTime]; ok {
registerMap[registerTime] = money + orderinfo.Money
} else {
registerMap[registerTime] = orderinfo.Money
}
}
//for key, value := range registerMap {
// fmt.Println(key, "充值金额:", fmt.Sprintf("%02f", float64(value)/100))
//}
return nil
}
// func SyncUserInfo() error {
// ctx := context.Background()
// end := utils.BeginOfToday().AddDate(0, 0, -15)
// start := end.AddDate(0, 0, -1)
// registerMap := make(map[time.Time]int64)
// // 获取充值金额
// rechargeList, err := rechargemod.TotalDistricRechargeAmountV1(ctx, 888, start, end)
// if err != nil {
// log.Error("DirectAmountMethod DirectRechargeAmount ", log.E(err))
// return err
// }
// for _, orderinfo := range rechargeList {
// registerTime := utils.BeginWithTime(orderinfo.RegisterTime)
// if registerTime.Before(start.AddDate(0, 0, -20)) {
// continue
// }
// if money, ok := registerMap[registerTime]; ok {
// registerMap[registerTime] = money + orderinfo.Money
// } else {
// registerMap[registerTime] = orderinfo.Money
// }
// }
// for key, value := range registerMap {
// fmt.Println(key, "充值金额:", fmt.Sprintf("%02f", float64(value)/100))
// }
// return nil
// }
Executable
BIN
View File
Binary file not shown.