Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
package impl_localfile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
con_FILE_SUFFIX = "txt"
|
||||
|
||||
defaultPanicNum = 10 // 默认支持的连续panic次数
|
||||
defaultPanicIntervals = 5 // 秒
|
||||
|
||||
fileMaxSize = 1 << 27 // 128M
|
||||
)
|
||||
|
||||
type fileLog struct {
|
||||
logPath string
|
||||
|
||||
// fileDir + fileName 用于判断是否需要切换日志文件
|
||||
fileDir string
|
||||
fileName string
|
||||
lv levelType
|
||||
|
||||
msgChan chan logObject
|
||||
|
||||
f *os.File
|
||||
|
||||
// 如果出现未知panic并一直发生,那么应该要真正的panic
|
||||
panicNum int
|
||||
panicTime time.Time
|
||||
|
||||
// 当前已经写入的大小
|
||||
curWriteSize int64
|
||||
}
|
||||
|
||||
func newLog(logPath string, lv levelType) *fileLog {
|
||||
f := &fileLog{
|
||||
logPath: logPath,
|
||||
fileDir: "",
|
||||
fileName: "",
|
||||
msgChan: make(chan logObject, 10240),
|
||||
lv: lv,
|
||||
f: nil,
|
||||
}
|
||||
|
||||
go f.loop()
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *fileLog) loop() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// 将错误输出,而不是记录到文件,是因为可能导致死循环
|
||||
fmt.Println("log file lv:", f.lv, " err:", r)
|
||||
|
||||
// 超过间隔时间重置
|
||||
if time.Since(f.panicTime)/time.Second > defaultPanicIntervals {
|
||||
f.panicNum = 0
|
||||
f.panicTime = time.Now()
|
||||
}
|
||||
|
||||
// 这里处理连续panic 也是防止循环调用形成死循环
|
||||
f.panicNum++
|
||||
if f.panicNum >= defaultPanicNum {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
go f.loop()
|
||||
}()
|
||||
|
||||
for logItem := range f.msgChan {
|
||||
f.writeLog(logItem)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fileLog) writeLog(logObj logObject) {
|
||||
// 由于不使用直接 logUtil 调用,logUtilPlus 存在终端打印的控制,所以 logUtil 只作为纯文件日志组件
|
||||
// if PrintImportantLog && (logObj.level == warn || logObj.level == _error || logObj.level == fatal) {
|
||||
// fmt.Println(logObj.logInfo)
|
||||
// }
|
||||
|
||||
// 检查是否需要去切换文件或者创建文件
|
||||
f.checkFileAndLoop(logObj.level, logObj.ifIncludeHour)
|
||||
|
||||
f.curWriteSize += int64(len(logObj.logInfo))
|
||||
_, _ = f.f.WriteString(logObj.logInfo)
|
||||
}
|
||||
|
||||
// 检查文件是否需要切换
|
||||
func (f *fileLog) checkFileAndLoop(level levelType, ifIncludeHour bool) {
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
fileAbsoluteDirectory := filepath.Join(f.logPath, strconv.Itoa(now.Year()), strconv.Itoa(int(now.Month())))
|
||||
fileName := ""
|
||||
|
||||
if ifIncludeHour {
|
||||
fileName = fmt.Sprintf("%s.%s.%s", time.Now().Format("2006-01-02-15"), level, con_FILE_SUFFIX)
|
||||
} else {
|
||||
fileName = fmt.Sprintf("%s.%s.%s", time.Now().Format("2006-01-02"), level, con_FILE_SUFFIX)
|
||||
}
|
||||
|
||||
// 说明已经存在, 检查文件大小,并切换
|
||||
if f.f != nil && f.fileName == fileName && f.fileDir == fileAbsoluteDirectory {
|
||||
if f.curWriteSize < fileMaxSize {
|
||||
return
|
||||
}
|
||||
|
||||
// 大小超额切换文件
|
||||
f.switchFile()
|
||||
return
|
||||
}
|
||||
|
||||
// 创建文件夹
|
||||
if f.fileDir != fileAbsoluteDirectory {
|
||||
if err := os.MkdirAll(fileAbsoluteDirectory, os.ModePerm|os.ModeTemporary); err != nil {
|
||||
log.Println("make dir all is err :", err)
|
||||
}
|
||||
f.fileDir = fileAbsoluteDirectory
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
if f.fileName != fileName {
|
||||
f.fileName = fileName
|
||||
}
|
||||
|
||||
// 到这里说明要切换了,关闭之前的file
|
||||
if f.f != nil {
|
||||
_ = f.f.Close()
|
||||
}
|
||||
|
||||
// 正常切换文件
|
||||
f.createFile()
|
||||
}
|
||||
|
||||
func (f *fileLog) switchFile() {
|
||||
// 关闭文件
|
||||
_ = f.f.Close()
|
||||
|
||||
// 重命名
|
||||
curFileName := filepath.Join(f.fileDir, f.fileName)
|
||||
newFileName := filepath.Join(f.fileDir, fmt.Sprintf("%s.%s.%s", f.fileName, time.Now().Format("15-04-05.999"), con_FILE_SUFFIX))
|
||||
err := os.Rename(curFileName, newFileName)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
// 再次创建文件
|
||||
f.createFile()
|
||||
}
|
||||
|
||||
func (f *fileLog) createFile() {
|
||||
// 得到最终的文件绝对路径
|
||||
fileAbsolutePath := filepath.Join(f.fileDir, f.fileName)
|
||||
// 打开文件(如果文件存在就以读写模式打开,并追加写入;如果文件不存在就创建,然后以写模式打开。)
|
||||
file, err := os.OpenFile(fileAbsolutePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm|os.ModeTemporary)
|
||||
if err != nil {
|
||||
log.Println("open file is err :", err)
|
||||
return
|
||||
}
|
||||
f.f = file
|
||||
stat, _ := file.Stat()
|
||||
f.curWriteSize = stat.Size()
|
||||
}
|
||||
|
||||
func (f *fileLog) SetLogPath(logPath string) {
|
||||
f.logPath = logPath
|
||||
}
|
||||
|
||||
// Close 最后等待 3s 钟
|
||||
func (f *fileLog) Close(wg *sync.WaitGroup, waitFinish bool) {
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
|
||||
if f.f != nil {
|
||||
_ = f.f.Close()
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
for {
|
||||
if !waitFinish || len(f.msgChan) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ticker.C:
|
||||
fmt.Println("wait close log file timeout:3s")
|
||||
return
|
||||
default:
|
||||
// 1ms 写入文件500条,最多等待 15ms 检查一次就行
|
||||
time.Sleep(15 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package managecenterMgr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"Framework/managecenterModel"
|
||||
. "Framework/managecenterModel"
|
||||
"goutil/logUtil"
|
||||
"goutil/webUtil"
|
||||
)
|
||||
|
||||
var (
|
||||
partnerMap = make(map[int32]*Partner, 128)
|
||||
partnerHash string
|
||||
)
|
||||
|
||||
// 重新加载合作商
|
||||
func reloadPartner(isInit bool) error {
|
||||
//logUtil.DebugLog("开始刷新合作商列表")
|
||||
|
||||
// 连接服务器,以获取数据
|
||||
url := getManageCenterUrl("/API/PartnerList.ashx")
|
||||
|
||||
// 定义请求参数
|
||||
postDict := make(map[string]string)
|
||||
postDict["HashValue"] = partnerHash
|
||||
|
||||
//请求url,请求头
|
||||
header := webUtil.GetFormHeader()
|
||||
transport := webUtil.NewTransport()
|
||||
transport.DisableKeepAlives = true
|
||||
transport = webUtil.GetTimeoutTransport(transport, 30)
|
||||
|
||||
statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, transport)
|
||||
//statusCode, returnBytes, err := webUtil.PostMapData(url, postDict, header, nil)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("获取合作商列表出错,url:%s,错误信息为:%s", url, err))
|
||||
return err
|
||||
}
|
||||
if statusCode != 200 {
|
||||
logUtil.ErrorLog(fmt.Sprintf("获取合作商列表出错,url:%s,错误码为:%d", url, statusCode))
|
||||
return err
|
||||
}
|
||||
|
||||
// 解析返回值
|
||||
returnObj := new(ReturnObject)
|
||||
if err = json.Unmarshal(returnBytes, &returnObj); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("获取合作商列表出错,反序列化返回值出错,错误信息为:%s, str:%s", err, string(returnBytes)))
|
||||
return err
|
||||
}
|
||||
|
||||
// 判断返回状态是否为成功
|
||||
if returnObj.Code != 0 {
|
||||
// 数据没有变化,所以没有获取到新的数据,不能算错误。
|
||||
if returnObj.Code == 47 || returnObj.Message == "DataNotChanged" {
|
||||
//如果本地集合为空,且数据又没变化时,重新初始化一下本地hash值
|
||||
if len(partnerMap) == 0 {
|
||||
partnerHash = ""
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
msg := fmt.Sprintf("获取合作商列表出错,返回状态:%d,信息为:%s", returnObj.Code, returnObj.Message)
|
||||
logUtil.ErrorLog(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// 解析Data
|
||||
tmpPartnerList := make([]*Partner, 0, 128)
|
||||
if data, ok := returnObj.Data.(string); !ok {
|
||||
msg := "获取合作商列表出错,返回的数据不是string类型"
|
||||
logUtil.ErrorLog(msg)
|
||||
return errors.New(msg)
|
||||
} else {
|
||||
if err = json.Unmarshal([]byte(data), &tmpPartnerList); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("获取合作商列表出错,反序列化数据出错,错误信息为:%s", err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//logUtil.DebugLog(fmt.Sprintf("刷新合作商信息结束,合作商数量:%d", len(tmpPartnerList)))
|
||||
|
||||
tmpPartnerMap := make(map[int32]*Partner)
|
||||
for _, item := range tmpPartnerList {
|
||||
tmpPartnerMap[item.Id] = item
|
||||
}
|
||||
|
||||
// 赋值给最终的partnerMap
|
||||
partnerMap = tmpPartnerMap
|
||||
partnerHash = returnObj.HashValue
|
||||
|
||||
//通知变更
|
||||
mcDataChangeCallBack(managecenterModel.PartnerData, isInit)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取合作商对象列表
|
||||
// 返回值:
|
||||
// 合作商对象列表
|
||||
func GetPartnerList() (partnerList []*Partner) {
|
||||
for _, item := range partnerMap {
|
||||
partnerList = append(partnerList, item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 根据合作商Id获取合作商对象
|
||||
// id:合作商Id
|
||||
// 返回值:
|
||||
// 合作商对象
|
||||
// 是否存在
|
||||
func GetPartner(id int32) (partnerObj *Partner, exist bool) {
|
||||
partnerObj, exist = partnerMap[id]
|
||||
return
|
||||
}
|
||||
|
||||
// 根据合作商别名获取合作商对象
|
||||
// alias:合作商别名
|
||||
// 返回值:
|
||||
// 合作商对象
|
||||
// 是否存在
|
||||
func GetPartnerByAlias(alias string) (partnerObj *Partner, exist bool) {
|
||||
for _, item := range partnerMap {
|
||||
if item.Alias == alias {
|
||||
partnerObj = item
|
||||
exist = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取合作商的其它配置信息
|
||||
// id:合作商Id
|
||||
// configKey:其它配置Key
|
||||
// 返回值
|
||||
// 配置内容
|
||||
// 是否存在
|
||||
// 错误对象
|
||||
func GetOtherConfigInfo(id int32, configKey string) (configValue string, exist bool, err error) {
|
||||
partnerObj, exist := GetPartner(id)
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
var otherConfigMap map[string]string
|
||||
otherConfigMap, err = partnerObj.ResolveOtherConfig()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
configValue, exist = otherConfigMap[configKey]
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 批量发送消息请求对象
|
||||
type BatchSendMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 消息正文列表
|
||||
msgBodyList []string
|
||||
|
||||
// 单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
|
||||
delaySeconds int
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *BatchSendMessageRequest) GetActionName() string {
|
||||
return "BatchSendMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequest 设置公共请求对象
|
||||
func (this *BatchSendMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *BatchSendMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
for index, msg := range this.msgBodyList {
|
||||
key := fmt.Sprintf("msgBody.%d", index)
|
||||
paramMap[key] = msg
|
||||
}
|
||||
paramMap["delaySeconds"] = fmt.Sprintf("%d", this.delaySeconds)
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewBatchSendMessageRequest(msgBodyList []string, delaySeconds int) *BatchSendMessageRequest {
|
||||
return &BatchSendMessageRequest{
|
||||
msgBodyList: msgBodyList,
|
||||
delaySeconds: delaySeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// 批量发送消息请求返回结果对象
|
||||
type BatchSendMessageResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
// message信息列表
|
||||
MsgInfoList []*MessageInfo `json:"msgInfoList"`
|
||||
}
|
||||
|
||||
func NewBatchSendMessageResponse() *BatchSendMessageResponse {
|
||||
return &BatchSendMessageResponse{}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package user
|
||||
Reference in New Issue
Block a user