Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"bugly.go",
"bugly_batch_run.go",
"mail.go",
"service.go",
"tapd.go",
"user.go",
],
importpath = "go-common/app/admin/ep/marthe/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/marthe/conf:go_default_library",
"//app/admin/ep/marthe/dao:go_default_library",
"//app/admin/ep/marthe/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/robfig/cron:go_default_library",
"//vendor/github.com/satori/go.uuid:go_default_library",
"//vendor/gopkg.in/gomail.v2:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,386 @@
package service
import (
"context"
"go-common/app/admin/ep/marthe/model"
"go-common/library/ecode"
)
// UpdateBuglyVersion update Bugly Version.
func (s *Service) UpdateBuglyVersion(c context.Context, username string, req *model.AddVersionRequest) (rep map[string]interface{}, err error) {
var (
bugVersionID int64
buglyProject *model.BuglyProject
)
// check project
if buglyProject, err = s.dao.QueryBuglyProject(req.BuglyProjectID); err != nil {
return
}
if buglyProject.ID == 0 {
err = ecode.NothingFound
return
}
if req.ID > 0 {
// update
var tmpVersion *model.BuglyVersion
if tmpVersion, err = s.dao.QueryBuglyVersion(req.ID); err != nil {
return
}
if tmpVersion.ID == 0 {
err = ecode.NothingFound
return
}
tmpVersion.BuglyProjectID = req.BuglyProjectID
tmpVersion.Version = req.Version
tmpVersion.Action = req.Action
if err = s.dao.UpdateBuglyVersion(tmpVersion); err != nil {
return
}
bugVersionID = tmpVersion.ID
} else {
// add
var tmpVersion *model.BuglyVersion
//check name
if tmpVersion, err = s.dao.QueryBuglyVersionByVersion(req.Version); err != nil {
return
}
if tmpVersion.ID > 0 {
err = ecode.MartheDuplicateErr
return
}
buglyVersion := &model.BuglyVersion{
ID: req.ID,
Version: req.Version,
BuglyProjectID: req.BuglyProjectID,
Action: req.Action,
TaskStatus: model.BuglyVersionTaskStatusReady,
UpdateBy: username,
}
if err = s.dao.InsertBuglyVersion(buglyVersion); err != nil {
return
}
bugVersionID = buglyVersion.ID
}
rep = make(map[string]interface{})
rep["bug_version_id"] = bugVersionID
return
}
// QueryBuglyVersions Query Bugly Versions.
func (s *Service) QueryBuglyVersions(c context.Context, req *model.QueryBuglyVersionRequest) (rep *model.PaginateBuglyProjectVersions, err error) {
var (
total int64
buglyProjectVersions []*model.BuglyProjectVersion
)
if total, buglyProjectVersions, err = s.dao.FindBuglyProjectVersions(req); err != nil {
return
}
rep = &model.PaginateBuglyProjectVersions{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
BuglyProjectVersions: buglyProjectVersions,
}
return
}
// BuglyVersionAndProjectList Bugly Version and project List.
func (s *Service) BuglyVersionAndProjectList(c context.Context) (rep map[string]interface{}, err error) {
var (
versionList []string
projectList []string
)
rep = make(map[string]interface{})
if versionList, err = s.dao.QueryBuglyVersionList(); err != nil {
return
}
if projectList, err = s.dao.QueryBuglyProjectList(); err != nil {
return
}
rep["versions"] = versionList
rep["projects"] = projectList
return
}
// UpdateCookie update Cookie.
func (s *Service) UpdateCookie(c context.Context, username string, req *model.AddCookieRequest) (rep map[string]interface{}, err error) {
var cookieID int64
if req.ID > 0 {
buglyCookie := &model.BuglyCookie{
ID: req.ID,
QQAccount: req.QQAccount,
Cookie: req.Cookie,
Token: req.Token,
Status: req.Status,
UpdateBy: username,
}
if err = s.dao.UpdateCookie(buglyCookie); err != nil {
return
}
cookieID = req.ID
} else {
buglyCookie := &model.BuglyCookie{
QQAccount: req.QQAccount,
Cookie: req.Cookie,
Token: req.Token,
Status: req.Status,
UpdateBy: username,
}
if err = s.dao.InsertCookie(buglyCookie); err != nil {
return
}
cookieID = buglyCookie.ID
}
rep = make(map[string]interface{})
rep["cookie_id"] = cookieID
return
}
// QueryCookies Add Cookie.
func (s *Service) QueryCookies(c context.Context, req *model.QueryBuglyCookiesRequest) (rep *model.PaginateBuglyCookies, err error) {
var (
total int64
buglyCookies []*model.BuglyCookie
)
if total, buglyCookies, err = s.dao.FindCookies(req); err != nil {
return
}
rep = &model.PaginateBuglyCookies{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
BuglyCookies: buglyCookies,
}
return
}
// UpdateCookieStatus Update Cookie Status.
func (s *Service) UpdateCookieStatus(c context.Context, cookieID int64, status int) (err error) {
err = s.dao.UpdateCookieStatus(cookieID, status)
return
}
// GetEnableCookie Get Enable Cookie.
func (s *Service) GetEnableCookie() (buglyCookie *model.BuglyCookie, err error) {
var buglyCookies []*model.BuglyCookie
if buglyCookies, err = s.dao.QueryCookieByStatus(model.BuglyCookieStatusEnable); err != nil {
return
}
/*for _, ele := range buglyCookies {
if ele.UsageCount < s.c.Bugly.CookieUsageUpper {
buglyCookie = ele
err = s.dao.UpdateCookieUsageCount(buglyCookie.ID, buglyCookie.UsageCount+1)
return
}
}*/
if len(buglyCookies) > 0 {
buglyCookie = buglyCookies[0]
err = s.dao.UpdateCookieUsageCount(buglyCookie.ID, buglyCookie.UsageCount+1)
return
}
//not found enable cookie
s.DoWhenNoEnableCookie()
err = ecode.MartheNoCookie
return
}
// DisableCookie Disable Cookie.
func (s *Service) DisableCookie(c context.Context, cookieID int64) (err error) {
err = s.dao.UpdateCookieStatus(cookieID, model.BuglyCookieStatusDisable)
return
}
// DoWhenNoEnableCookie Do When No Enable Cookie.
func (s *Service) DoWhenNoEnableCookie() {
// todo notice
s.SendMail(s.c.Mail.NoticeOwner, "marthe has no enable cookie", "")
}
// QueryBuglyIssueRecords Query Bugly Issue Records
func (s *Service) QueryBuglyIssueRecords(c context.Context, req *model.QueryBuglyIssueRequest) (rep *model.PaginateBuglyIssues, err error) {
var (
total int64
buglyIssues []*model.BuglyIssue
)
if total, buglyIssues, err = s.dao.FindBuglyIssues(req); err != nil {
return
}
rep = &model.PaginateBuglyIssues{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
BuglyIssues: buglyIssues,
}
return
}
// QueryBatchRuns Query Batch Runs
func (s *Service) QueryBatchRuns(c context.Context, req *model.QueryBuglyBatchRunsRequest) (rep *model.PaginateBuglyBatchRuns, err error) {
var (
total int64
buglyBatchRuns []*model.BuglyBatchRun
)
if total, buglyBatchRuns, err = s.dao.FindBuglyBatchRuns(req); err != nil {
return
}
rep = &model.PaginateBuglyBatchRuns{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
BuglyBatchRuns: buglyBatchRuns,
}
return
}
// UpdateBuglyProject update bugly project.
func (s *Service) UpdateBuglyProject(c context.Context, username string, req *model.AddProjectRequest) (rep map[string]interface{}, err error) {
var buglyProjectID int64
if req.ID > 0 {
buglyProject := &model.BuglyProject{
ID: req.ID,
ProjectID: req.ProjectID,
//ProjectName: req.ProjectName,
PlatformID: req.PlatformID,
ExceptionType: req.ExceptionType,
UpdateBy: username,
}
if err = s.dao.UpdateBuglyProject(buglyProject); err != nil {
return
}
buglyProjectID = req.ID
} else {
var buglyProjectInDB *model.BuglyProject
if buglyProjectInDB, err = s.dao.QueryBuglyProjectByName(req.ProjectName); err != nil {
return
}
if buglyProjectInDB.ID > 0 {
err = ecode.MartheDuplicateErr
return
}
buglyProject := &model.BuglyProject{
ProjectID: req.ProjectID,
ProjectName: req.ProjectName,
PlatformID: req.PlatformID,
ExceptionType: req.ExceptionType,
UpdateBy: username,
}
if err = s.dao.InsertBuglyProject(buglyProject); err != nil {
return
}
buglyProjectID = buglyProject.ID
}
rep = make(map[string]interface{})
rep["bugly_project_id"] = buglyProjectID
return
}
// QueryBuglyProjects Query Bugly Project.
func (s *Service) QueryBuglyProjects(c context.Context, req *model.QueryBuglyProjectRequest) (rep *model.PaginateBuglyProjects, err error) {
var (
total int64
buglyProjects []*model.BuglyProject
)
if total, buglyProjects, err = s.dao.FindBuglyProjects(req); err != nil {
return
}
rep = &model.PaginateBuglyProjects{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
BuglyProjects: buglyProjects,
}
return
}
// QueryBuglyProject Query Bugly Project.
func (s *Service) QueryBuglyProject(c context.Context, id int64) (buglyProject *model.BuglyProject, err error) {
return s.dao.QueryBuglyProject(id)
}
// QueryAllBuglyProjects Query All Bugly Projects.
func (s *Service) QueryAllBuglyProjects(c context.Context) (buglyProjects []*model.BuglyProject, err error) {
return s.dao.QueryAllBuglyProjects()
}
// QueryBuglyProjectVersions Query Bugly Project Versions.
func (s *Service) QueryBuglyProjectVersions(c context.Context, buglyProjectID int64) (rep map[string]interface{}, err error) {
var (
buglyProject *model.BuglyProject
buglyCookie *model.BuglyCookie
buglyVersions []*model.BugVersion
versions []string
)
defer func() {
if err != nil && err == ecode.MartheCookieExpired {
s.DisableCookie(c, buglyCookie.ID)
}
}()
if buglyProject, err = s.dao.QueryBuglyProject(buglyProjectID); err != nil {
return
}
if buglyProject.ID == 0 {
err = ecode.NothingFound
return
}
//get enable cookie
if buglyCookie, err = s.GetEnableCookie(); err != nil {
return
}
if buglyVersions, err = s.dao.BuglyVersion(c, buglyCookie, buglyProject.ProjectID, buglyProject.PlatformID); err != nil || buglyVersions == nil {
return
}
for _, buglyVersion := range buglyVersions {
versions = append(versions, buglyVersion.Name)
}
rep = make(map[string]interface{})
rep["versions"] = versions
return
}

View File

@@ -0,0 +1,358 @@
package service
import (
"context"
"fmt"
"sync"
"time"
"go-common/app/admin/ep/marthe/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/satori/go.uuid"
)
// RunVersions Run Versions.
func (s *Service) RunVersions(buglyVersionID int64) (rep map[string]interface{}, err error) {
lock := s.getBatchRunLock(buglyVersionID)
lock.Lock()
defer lock.Unlock()
var (
buglyRunVersions []*model.BuglyVersion
uid string
isEnableRun bool
)
// 获取可以跑的版本号list
if buglyRunVersions, err = s.GetBatchRunVersions(); err != nil {
log.Error("GetBatchRunVersions err(%v) ", err)
return
}
for _, buglyRunVersion := range buglyRunVersions {
if buglyRunVersion.ID == buglyVersionID {
isEnableRun = true
uid = uuid.NewV4().String()
// 插入batchrun表
buglyBatchRun := &model.BuglyBatchRun{
BuglyVersionID: buglyRunVersion.ID,
Version: buglyRunVersion.Version,
BatchID: uid,
Status: model.BuglyBatchRunStatusRunning,
}
if err = s.dao.InsertBuglyBatchRun(buglyBatchRun); err != nil {
return
}
s.batchRunCache.Do(context.Background(), func(ctx context.Context) {
if err = s.runPerVersion(uid, buglyRunVersion); err != nil {
log.Error("runPerVersion uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
}
defer func() {
// batch run 并且更新batch run表
batchStatus := model.BuglyBatchRunStatusDone
errMsg := ""
endTime := time.Now()
if err != nil {
batchStatus = model.BuglyBatchRunStatusFailed
errMsg = err.Error()
}
updateBuglyBatchRun := &model.BuglyBatchRun{
ID: buglyBatchRun.ID,
Status: batchStatus,
ErrorMsg: errMsg,
EndTime: endTime,
}
if err = s.dao.UpdateBuglyBatchRun(updateBuglyBatchRun); err != nil {
log.Error("runPerVersion UpdateBuglyBatchRun uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
}
}()
})
break
}
}
rep = make(map[string]interface{})
rep["uid"] = uid
rep["enable_to_run"] = isEnableRun
if !isEnableRun {
err = ecode.MartheTaskInRunning
}
return
}
// BatchRunVersions Batch Run Versions
func (s *Service) BatchRunVersions() (err error) {
var (
buglyRunVersions []*model.BuglyVersion
uid = uuid.NewV4().String()
)
// 获取可以跑的版本号list
if buglyRunVersions, err = s.dao.FindEnableAndReadyVersions(); err != nil {
log.Error("GetBatchRunVersions err(%v) ", err)
return
}
for _, buglyRunVersion := range buglyRunVersions {
if _, err = s.RunVersions(buglyRunVersion.ID); err != nil {
log.Error("runPerVersion uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
}
}
return
}
func (s *Service) runPerVersion(uid string, buglyRunVersion *model.BuglyVersion) (err error) {
var (
buglyRet *model.BugRet
buglyCookie *model.BuglyCookie
requestPageCnt int
c = context.Background()
lastRunTime time.Time
buglyBatchRun *model.BuglyBatchRun
buglyProject *model.BuglyProject
)
log.Info("start run version: [%s] batchId: [%s]", buglyRunVersion.Version, uid)
if buglyProject, err = s.dao.QueryBuglyProject(buglyRunVersion.BuglyProjectID); err != nil {
return
}
if buglyProject.ID == 0 {
err = ecode.NothingFound
return
}
//get issue total count
bugIssueRequest := &model.BugIssueRequest{
ProjectID: buglyProject.ProjectID,
PlatformID: buglyProject.PlatformID,
Version: buglyRunVersion.Version,
ExceptionType: buglyProject.ExceptionType,
StartNum: 0,
Rows: 1,
}
//get last run time
if buglyBatchRun, err = s.dao.QueryLastSuccessBatchRunByVersion(buglyRunVersion.Version); err != nil {
return
}
if buglyBatchRun.ID > 0 {
lastRunTime = buglyBatchRun.CTime
} else {
loc, _ := time.LoadLocation("Local")
if lastRunTime, err = time.ParseInLocation(model.TimeLayout, model.TimeLayout, loc); err != nil {
return
}
}
//get enable cookie
if buglyCookie, err = s.GetEnableCookie(); err != nil {
return
}
// if cookie, update cookie as expired
defer func() {
if err != nil && err == ecode.MartheCookieExpired {
s.DisableCookie(c, buglyCookie.ID)
}
}()
if buglyRet, err = s.dao.BuglyIssueAndRetry(c, buglyCookie, bugIssueRequest); err != nil || len(buglyRet.BugIssues) < 1 {
return
}
//获取issue count 和 page 上限
requestPageCnt = int(buglyRet.NumFound/s.c.Bugly.IssuePageSize) + 1
requestPageCntMax := s.c.Bugly.IssueCountUpper / s.c.Bugly.IssuePageSize
if requestPageCnt > requestPageCntMax {
requestPageCnt = requestPageCntMax
}
// update or add issue
for i := 0; i < requestPageCnt; i++ {
innerBreak := false
bugIssueRequest.StartNum = s.c.Bugly.IssuePageSize * i
bugIssueRequest.Rows = s.c.Bugly.IssuePageSize
var ret *model.BugRet
if ret, err = s.dao.BuglyIssueAndRetry(c, buglyCookie, bugIssueRequest); err != nil {
return
}
loc, _ := time.LoadLocation("Local")
issueLink := "/v2/crash-reporting/errors/%s/%s/report?pid=%s&searchType=detail&version=%s&start=0&date=all"
for _, issueDto := range ret.BugIssues {
var (
issueTime time.Time
bugIssueDetail *model.BugIssueDetail
tagStr string
bugDetail = "no detail"
)
tmpTime := []rune(issueDto.LastTime)
issueTime, _ = time.ParseInLocation(model.TimeLayout, string(tmpTime[:len(tmpTime)-4]), loc)
//issue时间早于库里面最新时间的跳出
if issueTime.Before(lastRunTime) {
innerBreak = true
break
}
var tmpBuglyIssue *model.BuglyIssue
if tmpBuglyIssue, err = s.dao.GetBuglyIssue(issueDto.IssueID, issueDto.Version); err != nil {
log.Error("d.GetSaveIssues url(%s) err(%v)", "GetSaveIssues", err)
continue
}
for _, bugTag := range issueDto.Tags {
tagStr = tagStr + bugTag.TagName + ","
}
if tmpBuglyIssue.ID != 0 {
//update
issueRecord := &model.BuglyIssue{
IssueNo: issueDto.IssueID,
Title: issueDto.Title,
LastTime: issueTime,
HappenTimes: issueDto.Count,
UserTimes: issueDto.UserCount,
Version: issueDto.Version,
Tags: tagStr,
}
s.dao.UpdateBuglyIssue(issueRecord)
} else {
//create
if bugIssueDetail, err = s.dao.BuglyIssueDetailAndRetry(c, buglyCookie, buglyProject.ProjectID, buglyProject.PlatformID, issueDto.IssueID); err == nil {
bugDetail = bugIssueDetail.CallStack
}
issueURL := s.c.Bugly.Host + fmt.Sprintf(issueLink, buglyProject.ProjectID, issueDto.IssueID, buglyProject.PlatformID, buglyRunVersion.Version)
issueRecord := &model.BuglyIssue{
IssueNo: issueDto.IssueID,
Title: issueDto.Title,
LastTime: issueTime,
HappenTimes: issueDto.Count,
UserTimes: issueDto.UserCount,
Version: issueDto.Version,
Tags: tagStr,
Detail: bugDetail,
ExceptionMsg: issueDto.ExceptionMsg,
KeyStack: issueDto.KeyStack,
IssueLink: issueURL,
ProjectID: buglyProject.ProjectID,
}
s.dao.InsertBuglyIssue(issueRecord)
}
}
if innerBreak {
break
}
}
log.Info("end run version: [%s] batchId: [%s]", buglyRunVersion.Version, uid)
return
}
// GetBatchRunVersions Get Batch Run Versions.
func (s *Service) GetBatchRunVersions() (buglyRunVersions []*model.BuglyVersion, err error) {
var (
buglyVersions []*model.BuglyVersion
buglyBatchRuns []*model.BuglyBatchRun
)
if buglyVersions, err = s.dao.FindEnableAndReadyVersions(); err != nil {
return
}
if buglyBatchRuns, err = s.dao.QueryBuglyBatchRunsByStatus(model.BuglyBatchRunStatusRunning); err != nil {
return
}
// 排除正在执行的版本
for _, buglyVersion := range buglyVersions {
var isVersionRun bool
for _, buglyBatchRun := range buglyBatchRuns {
if buglyBatchRun.Version == buglyVersion.Version {
isVersionRun = true
break
}
}
if !isVersionRun {
buglyRunVersions = append(buglyRunVersions, buglyVersion)
}
}
return
}
// DisableBatchRunOverTime Disable Batch Run OverTime.
func (s *Service) DisableBatchRunOverTime() (err error) {
var (
buglyBatchRuns []*model.BuglyBatchRun
tapdBugRecords []*model.TapdBugRecord
timeNow = time.Now()
)
//清 未完成 disable batch run
if buglyBatchRuns, err = s.dao.QueryBuglyBatchRunsByStatus(model.BuglyBatchRunStatusRunning); err != nil {
return
}
for _, buglyBatchRun := range buglyBatchRuns {
if timeNow.Sub(buglyBatchRun.CTime).Hours() > float64(s.c.Scheduler.BatchRunOverHourTime) {
updateBuglyBatchRun := &model.BuglyBatchRun{
ID: buglyBatchRun.ID,
Status: model.BuglyBatchRunStatusFailed,
ErrorMsg: "over time",
EndTime: timeNow,
}
if err = s.dao.UpdateBuglyBatchRun(updateBuglyBatchRun); err != nil {
continue
}
}
}
// 清 未完成 disable insert tapd bug
if tapdBugRecords, err = s.dao.QueryTapdBugRecordByStatus(model.InsertBugStatusRunning); err != nil {
return
}
for _, tapdBugRecord := range tapdBugRecords {
if timeNow.Sub(tapdBugRecord.CTime).Hours() > float64(s.c.Scheduler.BatchRunOverHourTime) {
tapdBugRecord.Status = model.InsertBugStatusFailed
if err = s.dao.UpdateTapdBugRecord(tapdBugRecord); err != nil {
continue
}
}
}
return
}
func (s *Service) getBatchRunLock(buglyVersionId int64) (batchRunLock *sync.Mutex) {
s.syncBatchRunLock.Lock()
defer s.syncBatchRunLock.Unlock()
var ok bool
if batchRunLock, ok = s.mapBatchRunLocks[buglyVersionId]; !ok {
batchRunLock = new(sync.Mutex)
s.mapBatchRunLocks[buglyVersionId] = batchRunLock
}
return
}

View File

@@ -0,0 +1,12 @@
package service
import "gopkg.in/gomail.v2"
// SendMail Send Mail.
func (s *Service) SendMail(receiver []string, header, body string) {
m := gomail.NewMessage()
m.SetHeader("To", receiver...)
m.SetHeader("Subject", header)
m.SetBody("text/html", body)
s.dao.SendMail(m)
}

View File

@@ -0,0 +1,106 @@
package service
import (
"context"
"sync"
"go-common/app/admin/ep/marthe/conf"
"go-common/app/admin/ep/marthe/dao"
"go-common/app/admin/ep/marthe/model"
"go-common/library/sync/pipeline/fanout"
"github.com/robfig/cron"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
batchRunCache *fanout.Fanout
tapdBugCache *fanout.Fanout
taskCache *fanout.Fanout
cron *cron.Cron
syncWechatContactsLock sync.Mutex
syncTapdBugInsertLock sync.Mutex
mapTapdBugInsertLocks map[int64]*sync.Mutex
syncBatchRunLock sync.Mutex
mapBatchRunLocks map[int64]*sync.Mutex
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
batchRunCache: fanout.New("batchRunCache", fanout.Worker(5), fanout.Buffer(10240)),
tapdBugCache: fanout.New("tapdBugCache", fanout.Worker(5), fanout.Buffer(10240)),
taskCache: fanout.New("taskCache", fanout.Worker(5), fanout.Buffer(10240)),
mapTapdBugInsertLocks: make(map[int64]*sync.Mutex),
mapBatchRunLocks: make(map[int64]*sync.Mutex),
}
if c.Scheduler.Active {
s.cron = cron.New()
// 定时批量 跑enable version 抓bugly数据
if err := s.cron.AddFunc(c.Scheduler.BatchRunEnableVersion, func() { s.BatchRunTask(model.TaskBatchRunVersions, s.BatchRunVersions) }); err != nil {
panic(err)
}
// 定时把超过三小时为执行完毕的任务修改为失败
if err := s.cron.AddFunc(c.Scheduler.DisableBatchRunOverTime, func() { s.BatchRunTask(model.TaskDisableBatchRunOverTime, s.DisableBatchRunOverTime) }); err != nil {
panic(err)
}
// 定时更新tapd bug
if err := s.cron.AddFunc(c.Scheduler.BatchRunUpdateTapdBug, func() { s.BatchRunTask(model.TaskBatchRunUpdateBugInTapd, s.BatchRunUpdateBugInTapd) }); err != nil {
panic(err)
}
// 定时更新SyncWechatContact
if err := s.cron.AddFunc(c.Scheduler.SyncWechatContact, func() { s.BatchRunTask(model.TaskSyncWechatContact, s.SyncWechatContacts) }); err != nil {
panic(err)
}
s.cron.Start()
}
return s
}
// Ping Service
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close Service
func (s *Service) Close() {
s.dao.Close()
}
// BatchRunTask Batch Run Task.
func (s *Service) BatchRunTask(taskName string, task func() error) {
var err error
scheduleTask := &model.ScheduleTask{
Name: taskName,
Status: model.TaskStatusRunning,
}
if err = s.dao.InsertScheduleTask(scheduleTask); err != nil {
return
}
err = task()
defer func() {
if err != nil {
scheduleTask.Status = model.TaskStatusFailed
} else {
scheduleTask.Status = model.TaskStatusDone
}
if err = s.dao.UpdateScheduleTask(scheduleTask); err != nil {
return
}
}()
}

View File

@@ -0,0 +1,764 @@
package service
import (
"context"
"fmt"
"strconv"
"strings"
"sync"
"time"
"go-common/app/admin/ep/marthe/model"
"go-common/library/ecode"
"go-common/library/log"
)
// UpdateTapdBugTpl Update Tapd Bug Tpl.
func (s *Service) UpdateTapdBugTpl(c context.Context, username string, req *model.UpdateTapdBugTplRequest) (rep map[string]interface{}, err error) {
//check if access to workspace
if !s.AccessToWorkspace(req.WorkspaceID, username) {
err = ecode.AccessDenied
return
}
//check sql
if _, err = s.CheckTapdBugTplSQL(c, req.IssueFilterSQL); err != nil {
return
}
tapdBugTemplate := &model.TapdBugTemplate{
ID: req.ID,
WorkspaceID: req.WorkspaceID,
BuglyProjectId: req.BuglyProjectId,
IssueFilterSQL: req.IssueFilterSQL,
SeverityKey: req.SeverityKey,
UpdateBy: username,
TapdProperty: req.TapdProperty,
}
if req.ID > 0 {
err = s.dao.UpdateTapdBugTemplate(tapdBugTemplate)
} else {
// add new
err = s.dao.InsertTapdBugTemplate(tapdBugTemplate)
}
rep = make(map[string]interface{})
rep["template_id"] = tapdBugTemplate.ID
return
}
// QueryTapdBugTpl Query Tapd Bug Tpl
func (s *Service) QueryTapdBugTpl(c context.Context, req *model.QueryTapdBugTemplateRequest) (rep *model.PaginateTapdBugTemplates, err error) {
var (
total int64
tapdBugTemplates []*model.TapdBugTemplate
tapdBugTemplateWithProjectNames []*model.TapdBugTemplateWithProjectName
)
if total, tapdBugTemplates, err = s.dao.FindTapdBugTemplates(req); err != nil {
return
}
for _, tapdBugTemplate := range tapdBugTemplates {
var buglyProject *model.BuglyProject
if buglyProject, err = s.dao.QueryBuglyProject(tapdBugTemplate.BuglyProjectId); err != nil {
return
}
if req.ProjectName == "" || strings.Contains(buglyProject.ProjectName, req.ProjectName) {
tapdBugTemplateWithProjectName := &model.TapdBugTemplateWithProjectName{
TapdBugTemplate: tapdBugTemplate,
ProjectName: buglyProject.ProjectName,
}
tapdBugTemplateWithProjectNames = append(tapdBugTemplateWithProjectNames, tapdBugTemplateWithProjectName)
}
}
rep = &model.PaginateTapdBugTemplates{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
TapdBugTemplateWithProjectNames: tapdBugTemplateWithProjectNames,
}
return
}
// QueryAllTapdBugTpl Query All Tapd Bug Tpl
func (s *Service) QueryAllTapdBugTpl(c context.Context) (rep []*model.TapdBugTemplateShortResponse, err error) {
var tapdBugTemplates []*model.TapdBugTemplate
if tapdBugTemplates, err = s.dao.QueryAllTapdBugTemplates(); err != nil {
return
}
for _, tapdBugTemplate := range tapdBugTemplates {
var buglyProject *model.BuglyProject
if buglyProject, err = s.dao.QueryBuglyProject(tapdBugTemplate.BuglyProjectId); err != nil {
return
}
ret := &model.TapdBugTemplateShortResponse{
ID: tapdBugTemplate.ID,
WorkspaceID: tapdBugTemplate.WorkspaceID,
BuglyProjectId: tapdBugTemplate.BuglyProjectId,
BuglyProjectName: buglyProject.ProjectName,
}
rep = append(rep, ret)
}
return
}
// UpdateTapdBugVersionTpl Update Tapd Bug Version Tpl.
func (s *Service) UpdateTapdBugVersionTpl(c context.Context, username string, req *model.UpdateTapdBugVersionTplRequest) (rep map[string]interface{}, err error) {
// check sql
if req.IssueFilterSQL != "" {
if _, err = s.CheckTapdBugTplSQL(c, req.IssueFilterSQL); err != nil {
return
}
}
//check project id
var tmp *model.TapdBugTemplate
if tmp, err = s.dao.QueryTapdBugTemplate(req.ProjectTemplateID); err != nil {
return
}
if tmp.ID == 0 {
err = ecode.NothingFound
return
}
//check if access to workspace
if !s.AccessToWorkspace(tmp.WorkspaceID, username) {
err = ecode.AccessDenied
return
}
tapdBugVersionTemplate := &model.TapdBugVersionTemplate{
ID: req.ID,
Version: req.Version,
ProjectTemplateID: req.ProjectTemplateID,
IssueFilterSQL: req.IssueFilterSQL,
SeverityKey: req.SeverityKey,
UpdateBy: username,
TapdProperty: req.TapdProperty,
}
if req.ID > 0 {
err = s.dao.UpdateTapdBugVersionTemplate(tapdBugVersionTemplate)
} else {
// add new
err = s.dao.InsertTapdBugVersionTemplate(tapdBugVersionTemplate)
}
rep = make(map[string]interface{})
rep["version_template_id"] = tapdBugVersionTemplate.ID
return
}
// QueryTapdBugVersionTpl Query Tapd Bug Version Tpl
func (s *Service) QueryTapdBugVersionTpl(c context.Context, req *model.QueryTapdBugVersionTemplateRequest) (rep *model.PaginateTapdBugVersionTemplates, err error) {
var (
total int64
tapdBugVersionTemplates []*model.TapdBugVersionTemplate
)
if total, tapdBugVersionTemplates, err = s.dao.FindTapdBugVersionTemplates(req); err != nil {
return
}
rep = &model.PaginateTapdBugVersionTemplates{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
TapdBugVersionTemplates: tapdBugVersionTemplates,
}
return
}
// CheckTapdBugTplSQL Check Tapd Bug Tpl SQL.
func (s *Service) CheckTapdBugTplSQL(c context.Context, sql string) (rep map[string]interface{}, err error) {
var buglyIssues []*model.BuglyIssue
if buglyIssues, err = s.getBuglyIssuesByFilterSQLWithNoTapdBug(sql); err != nil {
err = ecode.MartheFilterSqlError
return
}
rep = make(map[string]interface{})
rep["count"] = len(buglyIssues)
return
}
// BugInsertTapdWithProject Bug Insert Tapd With Project.
func (s *Service) BugInsertTapdWithProject(c context.Context, id int64, username string) (rep map[string]interface{}, err error) {
var count int
count, err = s.bugInsertTapd(id, 0, username)
rep = make(map[string]interface{})
rep["tapd_bug_count"] = count
return
}
// BugInsertTapdWithVersion Bug Insert Tapd With Version.
func (s *Service) BugInsertTapdWithVersion(c context.Context, id int64, username string) (rep map[string]interface{}, err error) {
var count int
count, err = s.bugInsertTapd(0, id, username)
rep = make(map[string]interface{})
rep["tapd_bug_count"] = count
return
}
func (s *Service) bugInsertTapd(projectTemplateId, versionTemplateId int64, username string) (count int, err error) {
var (
tapdBugTemplate *model.TapdBugTemplate
tapdBugVersionTemplate *model.TapdBugVersionTemplate
buglyIssues []*model.BuglyIssue
tapdBugRecords []*model.TapdBugRecord
)
if (projectTemplateId == 0 && versionTemplateId == 0) || (projectTemplateId > 0 && versionTemplateId > 0) {
return
}
if projectTemplateId > 0 {
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(projectTemplateId); err != nil {
return
}
if tapdBugTemplate.ID == 0 {
err = ecode.NothingFound
return
}
} else if versionTemplateId > 0 {
if tapdBugVersionTemplate, err = s.dao.QueryTapdBugVersionTemplate(versionTemplateId); err != nil {
return
}
if tapdBugVersionTemplate.ID == 0 {
err = ecode.NothingFound
return
}
projectTemplateId = tapdBugVersionTemplate.ProjectTemplateID
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(projectTemplateId); err != nil {
return
}
if tapdBugTemplate.ID == 0 {
err = ecode.NothingFound
return
}
if err = s.UpdateTplAsVersionTpl(tapdBugVersionTemplate, tapdBugTemplate); err != nil {
return
}
}
// get map lock, every project tpl 串行
insertLock := s.getTapdBugInsertLock(projectTemplateId)
insertLock.Lock()
defer insertLock.Unlock()
//check if access to workspace
if !s.AccessToWorkspace(tapdBugTemplate.WorkspaceID, username) {
err = ecode.AccessDenied
return
}
if tapdBugRecords, err = s.dao.QueryTapdBugRecordByProjectIDAndStatus(projectTemplateId, model.InsertBugStatusRunning); err != nil {
return
}
if len(tapdBugRecords) > 0 {
err = ecode.MartheTaskInRunning
return
}
if buglyIssues, err = s.getBuglyIssuesByFilterSQLWithNoTapdBug(tapdBugTemplate.IssueFilterSQL); err != nil {
return
}
count = len(buglyIssues)
if count > 0 {
tapdBugInsertLog := &model.TapdBugRecord{
ProjectTemplateID: projectTemplateId,
VersionTemplateID: versionTemplateId,
Operator: username,
Count: count,
IssueFilterSQL: tapdBugTemplate.IssueFilterSQL,
Status: model.InsertBugStatusRunning,
}
if err = s.dao.InsertTapdBugRecord(tapdBugInsertLog); err != nil {
return
}
s.tapdBugCache.Do(context.TODO(), func(ctx context.Context) {
defer func() {
if err != nil {
tapdBugInsertLog.Status = model.InsertBugStatusFailed
} else {
tapdBugInsertLog.Status = model.InsertBugStatusDone
}
err = s.dao.UpdateTapdBugRecord(tapdBugInsertLog)
}()
for _, buglyIssue := range buglyIssues {
var (
bug *model.Bug
bugID string
)
if bug, err = s.getBugModel(buglyIssue, tapdBugTemplate); err != nil {
log.Error("getLiveIOSBugModel error (%v)", err)
continue
}
if bugID, err = s.dao.CreateBug(bug); err != nil && bugID == "" {
log.Error("CreateBug error (%v)", err)
continue
}
log.Info("insert issue no: [%s], bug number [%s]", buglyIssue.IssueNo, bugID)
if err = s.dao.UpdateBuglyIssueTapdBugID(buglyIssue.ID, bugID); err != nil {
log.Error("UpdateIssueRecordTapdBugID error (%v)", err)
continue
}
buglyIssue.TapdBugID = bugID
if err = s.updateBugInTapd(tapdBugTemplate, buglyIssue, time.Now()); err != nil {
continue
}
log.Info("update issue no [%s], bug number [%s]", buglyIssue.IssueNo, buglyIssue.TapdBugID)
}
})
}
return
}
func (s *Service) getBugModel(bugIssue *model.BuglyIssue, bugTemplate *model.TapdBugTemplate) (bug *model.Bug, err error) {
title := fmt.Sprintf(bugTemplate.Title, bugIssue.IssueNo, bugIssue.Version, bugIssue.Title, strconv.Itoa(bugIssue.HappenTimes), strconv.Itoa(bugIssue.UserTimes))
description := fmt.Sprintf(bugTemplate.Description, title, bugIssue.KeyStack,
bugIssue.IssueLink, bugIssue.IssueLink, bugIssue.IssueLink,
bugIssue.Detail)
bug = &model.Bug{
Title: title,
Description: description,
Priority: bugTemplate.Priority,
Severity: bugTemplate.Severity,
Module: bugTemplate.Module,
Status: bugTemplate.Status,
Reporter: bugTemplate.Reporter,
BugType: bugTemplate.BugType,
CurrentOwner: bugTemplate.CurrentOwner,
Source: bugTemplate.Source,
OriginPhase: bugTemplate.OriginPhase,
Platform: bugTemplate.Platform,
ReleaseID: bugTemplate.ReleaseID,
CustomFieldThree: bugTemplate.CustomFieldThree,
CustomFieldFour: bugTemplate.CustomFieldFour,
WorkspaceID: bugTemplate.WorkspaceID,
IterationID: bugTemplate.IterationID,
}
return
}
// UpdateTplAsVersionTpl Update Tpl As Version Tpl.
func (s *Service) UpdateTplAsVersionTpl(tapdBugVersionTemplate *model.TapdBugVersionTemplate, tapdBugTemplate *model.TapdBugTemplate) (err error) {
if tapdBugVersionTemplate.ProjectTemplateID != tapdBugTemplate.ID {
log.Error("projectID should be [%s],actual [%s]", tapdBugVersionTemplate.ProjectTemplateID, tapdBugTemplate.ID)
return
}
if strings.TrimSpace(tapdBugVersionTemplate.Title) != "" {
tapdBugTemplate.Title = tapdBugVersionTemplate.Title
}
if strings.TrimSpace(tapdBugVersionTemplate.Description) != "" {
tapdBugTemplate.Description = tapdBugVersionTemplate.Description
}
if strings.TrimSpace(tapdBugVersionTemplate.CurrentOwner) != "" {
tapdBugTemplate.CurrentOwner = tapdBugVersionTemplate.CurrentOwner
}
if strings.TrimSpace(tapdBugVersionTemplate.Platform) != "" {
tapdBugTemplate.Platform = tapdBugVersionTemplate.Platform
}
if strings.TrimSpace(tapdBugVersionTemplate.Module) != "" {
tapdBugTemplate.Module = tapdBugVersionTemplate.Module
}
if strings.TrimSpace(tapdBugVersionTemplate.IterationID) != "" {
tapdBugTemplate.IterationID = tapdBugVersionTemplate.IterationID
}
if strings.TrimSpace(tapdBugVersionTemplate.ReleaseID) != "" {
tapdBugTemplate.ReleaseID = tapdBugVersionTemplate.ReleaseID
}
if strings.TrimSpace(tapdBugVersionTemplate.Priority) != "" {
tapdBugTemplate.Priority = tapdBugVersionTemplate.Priority
}
if strings.TrimSpace(tapdBugVersionTemplate.Severity) != "" {
tapdBugTemplate.Severity = tapdBugVersionTemplate.Severity
}
if strings.TrimSpace(tapdBugVersionTemplate.Source) != "" {
tapdBugTemplate.Source = tapdBugVersionTemplate.Source
}
if strings.TrimSpace(tapdBugVersionTemplate.CustomFieldFour) != "" {
tapdBugTemplate.CustomFieldFour = tapdBugVersionTemplate.CustomFieldFour
}
if strings.TrimSpace(tapdBugVersionTemplate.BugType) != "" {
tapdBugTemplate.BugType = tapdBugVersionTemplate.BugType
}
if strings.TrimSpace(tapdBugVersionTemplate.OriginPhase) != "" {
tapdBugTemplate.OriginPhase = tapdBugVersionTemplate.OriginPhase
}
if strings.TrimSpace(tapdBugVersionTemplate.CustomFieldThree) != "" {
tapdBugTemplate.CustomFieldThree = tapdBugVersionTemplate.CustomFieldThree
}
if strings.TrimSpace(tapdBugVersionTemplate.Reporter) != "" {
tapdBugTemplate.Reporter = tapdBugVersionTemplate.Reporter
}
if strings.TrimSpace(tapdBugVersionTemplate.Status) != "" {
tapdBugTemplate.Status = tapdBugVersionTemplate.Status
}
if strings.TrimSpace(tapdBugVersionTemplate.IssueFilterSQL) != "" {
tapdBugTemplate.IssueFilterSQL = tapdBugVersionTemplate.IssueFilterSQL
}
if strings.TrimSpace(tapdBugVersionTemplate.SeverityKey) != "" {
tapdBugTemplate.SeverityKey = tapdBugVersionTemplate.SeverityKey
}
return
}
// BatchRunUpdateBugInTapd Batch Run Update Bug In Tapd.
func (s *Service) BatchRunUpdateBugInTapd() (err error) {
var buglyIssues []*model.BuglyIssue
if buglyIssues, err = s.dao.GetBuglyIssuesHasInTapd(); err != nil {
return
}
for _, buglyIssue := range buglyIssues {
var (
tapdBugTemplate *model.TapdBugTemplate
tapdBugVersionTemplate *model.TapdBugVersionTemplate
)
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplateByProjectID(buglyIssue.ProjectID); err != nil {
continue
}
if tapdBugTemplate.ID == 0 {
continue
}
if tapdBugVersionTemplate, err = s.dao.QueryTapdBugVersionTemplateByVersion(buglyIssue.Version); err != nil {
continue
}
if tapdBugVersionTemplate.ID > 0 {
if err = s.UpdateTplAsVersionTpl(tapdBugVersionTemplate, tapdBugTemplate); err != nil {
continue
}
}
err = s.updateBugInTapd(tapdBugTemplate, buglyIssue, time.Now())
}
return
}
func (s *Service) updateBugInTapd(tapdBugTemplate *model.TapdBugTemplate, bugIssue *model.BuglyIssue, timeNow time.Time) (err error) {
var bug *model.Bug
// update title
title := fmt.Sprintf(tapdBugTemplate.Title, bugIssue.IssueNo, bugIssue.Version, bugIssue.Title, strconv.Itoa(bugIssue.HappenTimes), strconv.Itoa(bugIssue.UserTimes))
if bug, err = s.dao.BugPre(tapdBugTemplate.WorkspaceID, bugIssue.TapdBugID); err != nil {
log.Error("BugPre projectId %s, error (%v)", bugIssue.ProjectID, err)
return
}
bug.Title = title
// update priority
var (
tapdBugPriorityConfs []*model.TapdBugPriorityConf
)
if tapdBugPriorityConfs, err = s.dao.QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus(tapdBugTemplate.ID, model.TapdBugPriorityConfEnable); err != nil {
return
}
for _, tmpTapdBugPriorityConf := range tapdBugPriorityConfs {
if timeNow.After(tmpTapdBugPriorityConf.StartTime) && timeNow.Before(tmpTapdBugPriorityConf.EndTime) {
if bugIssue.UserTimes >= tmpTapdBugPriorityConf.Urgent || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.Urgent {
bug.Priority = "urgent"
} else if bugIssue.UserTimes >= tmpTapdBugPriorityConf.High || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.High {
bug.Priority = "high"
} else if bugIssue.UserTimes >= tmpTapdBugPriorityConf.Medium || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.Medium {
bug.Priority = "medium"
}
break
}
}
// update serious
if strings.TrimSpace(tapdBugTemplate.SeverityKey) != "" {
keys := strings.Split(tapdBugTemplate.SeverityKey, ",")
for _, key := range keys {
if strings.Contains(bug.Description, key) {
bug.Severity = "serious"
break
}
}
}
updateBug := &model.UpdateBug{
Bug: bug,
CurrentUser: bug.CurrentOwner,
}
if err := s.dao.UpdateBug(updateBug); err != nil {
log.Error("UpdateBug bugid %s, error (%v)", bug.ID, err)
}
return
}
// QueryBugRecords Query Bug Records
func (s *Service) QueryBugRecords(c context.Context, req *model.QueryBugRecordsRequest) (rep *model.PaginateBugRecords, err error) {
var (
total int64
tapdBugRecords []*model.TapdBugRecord
)
if total, tapdBugRecords, err = s.dao.FindBugRecords(req); err != nil {
return
}
rep = &model.PaginateBugRecords{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
TapdBugRecords: tapdBugRecords,
}
return
}
// QueryTapdBugPriorityConfsRequest Query Tapd Bug Priority Confs Request
func (s *Service) QueryTapdBugPriorityConfsRequest(c context.Context, req *model.QueryTapdBugPriorityConfsRequest) (rep *model.PaginateTapdBugPriorityConfs, err error) {
var (
total int64
tapdBugPriorityConfs []*model.TapdBugPriorityConf
)
if total, tapdBugPriorityConfs, err = s.dao.FindTapdBugPriorityConfs(req); err != nil {
return
}
rep = &model.PaginateTapdBugPriorityConfs{
PaginationRep: model.PaginationRep{
Total: total,
PageSize: req.PageSize,
PageNum: req.PageNum,
},
TapdBugPriorityConfs: tapdBugPriorityConfs,
}
return
}
// UpdateTapdBugPriorityConf Update Tapd Bug Priority Conf.
func (s *Service) UpdateTapdBugPriorityConf(c context.Context, username string, req *model.UpdateTapdBugPriorityConfRequest) (rep map[string]interface{}, err error) {
var (
startTime time.Time
endTime time.Time
tapdBugPriorityConfsInDB []*model.TapdBugPriorityConf
tapdBugTemplate *model.TapdBugTemplate
)
//check project id
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(req.ProjectTemplateID); err != nil {
return
}
if tapdBugTemplate.ID == 0 {
err = ecode.NothingFound
return
}
//check if access to workspace
if !s.AccessToWorkspace(tapdBugTemplate.WorkspaceID, username) {
err = ecode.AccessDenied
return
}
if startTime, err = time.ParseInLocation(model.TimeLayout, req.StartTime, time.Local); err != nil {
return
}
if endTime, err = time.ParseInLocation(model.TimeLayout, req.EndTime, time.Local); err != nil {
return
}
// when status == enable, check time if conflict
if req.Status == model.TapdBugPriorityConfEnable {
if tapdBugPriorityConfsInDB, err = s.dao.QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus(req.ProjectTemplateID, model.TapdBugPriorityConfEnable); err != nil {
return
}
for _, tapdBugPriorityConfInDB := range tapdBugPriorityConfsInDB {
isStartTimeInDuration := tapdBugPriorityConfInDB.StartTime.After(startTime) && tapdBugPriorityConfInDB.StartTime.Before(endTime)
isEndTimeInDuration := tapdBugPriorityConfInDB.EndTime.After(startTime) && tapdBugPriorityConfInDB.EndTime.Before(endTime)
if isStartTimeInDuration || isEndTimeInDuration {
err = ecode.MartheTimeConflictError
return
}
}
}
tapdBugPriorityConf := &model.TapdBugPriorityConf{
ID: req.ID,
ProjectTemplateID: req.ProjectTemplateID,
Urgent: req.Urgent,
High: req.High,
Medium: req.Medium,
UpdateBy: username,
Status: req.Status,
StartTime: startTime,
EndTime: endTime,
}
if req.ID > 0 {
err = s.dao.UpdateTapdBugPriorityConf(tapdBugPriorityConf)
} else {
// add new
err = s.dao.InsertTapdBugPriorityConf(tapdBugPriorityConf)
}
rep = make(map[string]interface{})
rep["tapd_bug_priority_conf"] = tapdBugPriorityConf.ID
return
}
// AccessToWorkspace Access To Workspace.
func (s *Service) AccessToWorkspace(workspaceID, username string) (isAccess bool) {
if !s.c.Tapd.BugOperateAuth {
return true
}
var (
usernames []string
contactInfo *model.ContactInfo
err error
)
if contactInfo, err = s.dao.QueryContactInfoByUsername(username); err != nil {
return
}
if contactInfo.ID == 0 {
err = ecode.NothingFound
return
}
if usernames, err = s.dao.WorkspaceUser(workspaceID); err != nil {
return
}
for _, u := range usernames {
if u == contactInfo.NickName {
return true
}
}
return
}
// HttpAccessToWorkspace Access To Workspace.
func (s *Service) HttpAccessToWorkspace(c context.Context, workspaceID, username string) (rep map[string]interface{}, err error) {
var (
usernames []string
contactInfo *model.ContactInfo
isAccess bool
)
if contactInfo, err = s.dao.QueryContactInfoByUsername(username); err != nil {
return
}
if contactInfo.ID == 0 {
err = ecode.NothingFound
return
}
if usernames, err = s.dao.WorkspaceUser(workspaceID); err != nil {
return
}
for _, u := range usernames {
if u == contactInfo.NickName {
isAccess = true
break
}
}
rep = make(map[string]interface{})
rep["is_access"] = isAccess
rep["names"] = usernames
return
}
func (s *Service) getBuglyIssuesByFilterSQLWithNoTapdBug(issueFilterSQL string) (buglyIssues []*model.BuglyIssue, err error) {
var tmpBuglyIssues []*model.BuglyIssue
if tmpBuglyIssues, err = s.dao.GetBuglyIssuesByFilterSQL(issueFilterSQL); err != nil {
return
}
for _, buglyIssue := range tmpBuglyIssues {
if buglyIssue.TapdBugID == "" {
buglyIssues = append(buglyIssues, buglyIssue)
}
}
return
}
func (s *Service) getTapdBugInsertLock(projectTplId int64) (tapdBugInsertLock *sync.Mutex) {
s.syncTapdBugInsertLock.Lock()
defer s.syncTapdBugInsertLock.Unlock()
var ok bool
if tapdBugInsertLock, ok = s.mapTapdBugInsertLocks[projectTplId]; !ok {
tapdBugInsertLock = new(sync.Mutex)
s.mapTapdBugInsertLocks[projectTplId] = tapdBugInsertLock
}
return
}

View File

@@ -0,0 +1,134 @@
package service
import (
"context"
"go-common/library/log"
"go-common/app/admin/ep/marthe/model"
"go-common/library/ecode"
)
// QueryUserInfo query user info.
func (s *Service) QueryUserInfo(c context.Context, username string) (userInfo *model.User, err error) {
if userInfo, err = s.dao.FindUserByUserName(username); err != nil {
return
}
if userInfo.ID == 0 {
user := model.User{Name: username, EMail: username + "@bilibili.com"}
s.dao.CreateUser(&user)
userInfo, err = s.dao.FindUserByUserName(username)
}
return
}
// HttpSyncWechatContacts Http Sync Wechat Contacts.
func (s *Service) HttpSyncWechatContacts(ctx context.Context) (err error) {
s.taskCache.Do(context.TODO(), func(ctx context.Context) {
s.SyncWechatContacts()
})
return
}
// SyncWechatContacts Sync Wechat Contacts.
func (s *Service) SyncWechatContacts() (err error) {
s.syncWechatContactsLock.Lock()
defer s.syncWechatContactsLock.Unlock()
log.Info("start")
var (
wechatContacts []*model.WechatContact
contactInfosInDB []*model.ContactInfo
)
if wechatContacts, err = s.dao.WechatContacts(context.Background()); err != nil {
return
}
if contactInfosInDB, err = s.dao.QueryAllContactInfos(); err != nil {
return
}
for _, wechatContact := range wechatContacts {
var (
tmpContactInfoInDB *model.ContactInfo
)
for _, contactInfoInDB := range contactInfosInDB {
if contactInfoInDB.UserID == wechatContact.UserID {
tmpContactInfoInDB = contactInfoInDB
break
}
}
if tmpContactInfoInDB != nil {
//update
tmpContactInfoInDB.UserName = wechatContact.EnglishName
tmpContactInfoInDB.NickName = wechatContact.Name
if err = s.dao.UpdateContactInfo(tmpContactInfoInDB); err != nil {
continue
}
} else {
//add
tmpContactInfoInDB = &model.ContactInfo{
UserName: wechatContact.EnglishName,
NickName: wechatContact.Name,
UserID: wechatContact.UserID,
}
if err = s.dao.InsertContactInfo(tmpContactInfoInDB); err != nil {
continue
}
}
}
log.Info("end")
return
}
// AccessToBugly Access To Bugly.
func (s *Service) AccessToBugly(c context.Context, username string) (isAccess bool) {
var (
userInfo *model.User
err error
)
if userInfo, err = s.QueryUserInfo(c, username); err != nil {
return
}
isAccess = userInfo.VisibleBugly
return
}
// UpdateUserVisibleBugly Update User Visible Bugly.
func (s *Service) UpdateUserVisibleBugly(c context.Context, username, updateUsername string, visibleBugly bool) (err error) {
var (
hasRight bool
userInfo *model.User
)
for _, super := range s.c.Bugly.SuperOwner {
if username == super {
hasRight = true
break
}
}
if !hasRight {
err = ecode.AccessDenied
return
}
if userInfo, err = s.dao.FindUserByUserName(updateUsername); err != nil {
return
}
if userInfo.ID == 0 {
err = ecode.NothingFound
return
}
err = s.dao.UpdateUserVisibleBugly(userInfo.ID, visibleBugly)
return
}