Skip to content

Commit 5675490

Browse files
authored
Merge pull request #499 from LydiaCai1203/fix-repo-list
feat: 获取仓库列表处加了缓存逻辑
2 parents 5df4fac + 4ccf17c commit 5675490

File tree

13 files changed

+129
-63
lines changed

13 files changed

+129
-63
lines changed

backend/biz/git/handler/v1/identity.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func NewGitIdentityHandler(i *do.Injector) (*GitIdentityHandler, error) {
4949
// @Accept json
5050
// @Produce json
5151
// @Security MonkeyCodeAIAuth
52-
// @Success 200 {object} web.Resp{data=[]domain.GitIdentity} "成功"
53-
// @Failure 500 {object} web.Resp "服务器内部错误"
52+
// @Success 200 {object} web.Resp{data=[]domain.GitIdentity} "成功"
53+
// @Failure 500 {object} web.Resp "服务器内部错误"
5454
// @Router /api/v1/users/git-identities [get]
5555
func (h *GitIdentityHandler) List(c *web.Context) error {
5656
user := middleware.GetUser(c)
@@ -69,15 +69,16 @@ func (h *GitIdentityHandler) List(c *web.Context) error {
6969
// @Accept json
7070
// @Produce json
7171
// @Security MonkeyCodeAIAuth
72-
// @Param id path string true "Git 身份认证ID"
73-
// @Success 200 {object} web.Resp{data=domain.GitIdentity} "成功"
74-
// @Failure 400 {object} web.Resp "请求参数错误"
75-
// @Failure 404 {object} web.Resp "资源不存在"
76-
// @Failure 500 {object} web.Resp "服务器内部错误"
72+
// @Param id path string true "Git 身份认证ID"
73+
// @Param flush query bool false "是否刷新缓存"
74+
// @Success 200 {object} web.Resp{data=domain.GitIdentity} "成功"
75+
// @Failure 400 {object} web.Resp "请求参数错误"
76+
// @Failure 404 {object} web.Resp "资源不存在"
77+
// @Failure 500 {object} web.Resp "服务器内部错误"
7778
// @Router /api/v1/users/git-identities/{id} [get]
7879
func (h *GitIdentityHandler) Get(c *web.Context, req domain.GetGitIdentityReq) error {
7980
user := middleware.GetUser(c)
80-
identity, err := h.usecase.Get(c.Request().Context(), user.ID, req.ID)
81+
identity, err := h.usecase.Get(c.Request().Context(), user.ID, req.ID, req.Flush)
8182
if err != nil {
8283
return err
8384
}

backend/biz/git/usecase/identity.go

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"fmt"
66
"log/slog"
77
"strings"
8+
"time"
89

910
"github.com/google/uuid"
11+
"github.com/patrickmn/go-cache"
1012
"github.com/samber/do"
1113

1214
"github.com/chaitin/MonkeyCode/backend/config"
@@ -15,6 +17,7 @@ import (
1517
"github.com/chaitin/MonkeyCode/backend/domain"
1618
"github.com/chaitin/MonkeyCode/backend/errcode"
1719
"github.com/chaitin/MonkeyCode/backend/pkg/cvt"
20+
gitpkg "github.com/chaitin/MonkeyCode/backend/pkg/git"
1821
"github.com/chaitin/MonkeyCode/backend/pkg/git/gitea"
1922
"github.com/chaitin/MonkeyCode/backend/pkg/git/gitee"
2023
"github.com/chaitin/MonkeyCode/backend/pkg/git/github"
@@ -27,6 +30,7 @@ type GitIdentityUsecase struct {
2730
repo domain.GitIdentityRepo
2831
tokenProvider *TokenProvider
2932
logger *slog.Logger
33+
repoCache *cache.Cache
3034
}
3135

3236
// NewGitIdentityUsecase 创建 Git 身份认证用例
@@ -36,6 +40,7 @@ func NewGitIdentityUsecase(i *do.Injector) (domain.GitIdentityUsecase, error) {
3640
repo: do.MustInvoke[domain.GitIdentityRepo](i),
3741
tokenProvider: do.MustInvoke[*TokenProvider](i),
3842
logger: do.MustInvoke[*slog.Logger](i).With("module", "GitIdentityUsecase"),
43+
repoCache: cache.New(7*24*time.Hour, 10*time.Minute),
3944
}, nil
4045
}
4146

@@ -47,45 +52,29 @@ func (u *GitIdentityUsecase) List(ctx context.Context, uid uuid.UUID) ([]*domain
4752
return nil, err
4853
}
4954
return cvt.Iter(identities, func(_ int, identity *db.GitIdentity) *domain.GitIdentity {
50-
tmp := cvt.From(identity, &domain.GitIdentity{})
51-
if client := u.gitClienter(identity); client != nil {
52-
token, err := u.tokenProvider.GetToken(ctx, identity.ID)
53-
if err != nil {
54-
u.logger.WarnContext(ctx, "failed to get token", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
55-
return tmp
56-
}
57-
repos, err := client.Repositories(ctx, &domain.RepositoryOptions{
58-
Token: token,
59-
InstallID: identity.InstallationID,
60-
IsOAuth: identity.OauthRefreshToken != "",
61-
})
62-
if err != nil {
63-
u.logger.WarnContext(ctx, "failed to get authorized repositories", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
64-
} else {
65-
tmp.AuthorizedRepositories = repos
66-
}
67-
}
68-
return tmp
55+
return cvt.From(identity, &domain.GitIdentity{})
6956
}), nil
7057
}
7158

7259
func (u *GitIdentityUsecase) gitClienter(identity *db.GitIdentity) domain.GitClienter {
60+
var inner domain.GitClienter
7361
switch identity.Platform {
7462
case consts.GitPlatformGithub:
75-
return github.NewGithub(u.logger, u.cfg)
63+
inner = github.NewGithub(u.logger, u.cfg)
7664
case consts.GitPlatformGitLab:
77-
return gitlab.NewGitlabForBaseURL(identity.BaseURL, u.logger)
65+
inner = gitlab.NewGitlabForBaseURL(identity.BaseURL, u.logger)
7866
case consts.GitPlatformGitea:
79-
return gitea.NewGitea(u.logger, identity.BaseURL)
67+
inner = gitea.NewGitea(u.logger, identity.BaseURL)
8068
case consts.GitPlatformGitee:
81-
return gitee.NewGitee(identity.BaseURL, u.logger)
69+
inner = gitee.NewGitee(identity.BaseURL, u.logger)
8270
default:
8371
return nil
8472
}
73+
return gitpkg.NewCachedGitClient(inner, u.repoCache, identity.UserID.String()+":"+identity.ID.String())
8574
}
8675

8776
// Get 获取单个 Git 身份认证(仅限当前用户)
88-
func (u *GitIdentityUsecase) Get(ctx context.Context, uid uuid.UUID, id uuid.UUID) (*domain.GitIdentity, error) {
77+
func (u *GitIdentityUsecase) Get(ctx context.Context, uid uuid.UUID, id uuid.UUID, flush bool) (*domain.GitIdentity, error) {
8978
identity, err := u.repo.GetByUserID(ctx, uid, id)
9079
if err != nil {
9180
if db.IsNotFound(err) {
@@ -99,19 +88,20 @@ func (u *GitIdentityUsecase) Get(ctx context.Context, uid uuid.UUID, id uuid.UUI
9988
if client := u.gitClienter(identity); client != nil {
10089
token, err := u.tokenProvider.GetToken(ctx, identity.ID)
10190
if err != nil {
102-
u.logger.WarnContext(ctx, "failed to get token", "error", err, "platform", identity.Platform, "identity_id", id)
91+
u.logger.WarnContext(ctx, "failed to get token", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
10392
return gi, nil
10493
}
10594
repos, err := client.Repositories(ctx, &domain.RepositoryOptions{
10695
Token: token,
10796
InstallID: identity.InstallationID,
10897
IsOAuth: identity.OauthRefreshToken != "",
98+
Flush: flush,
10999
})
110100
if err != nil {
111-
u.logger.WarnContext(ctx, "failed to get authorized repositories", "error", err, "platform", identity.Platform, "identity_id", id)
112-
} else {
113-
gi.AuthorizedRepositories = repos
101+
u.logger.WarnContext(ctx, "failed to get authorized repositories", "error", err, "platform", identity.Platform, "identity_id", identity.ID)
102+
return gi, nil
114103
}
104+
gi.AuthorizedRepositories = repos
115105
}
116106

117107
return gi, nil
@@ -134,6 +124,7 @@ func (u *GitIdentityUsecase) Update(ctx context.Context, uid uuid.UUID, req *dom
134124
return err
135125
}
136126
u.tokenProvider.ClearCache(req.ID)
127+
u.repoCache.Delete(uid.String() + ":" + req.ID.String())
137128
return nil
138129
}
139130

@@ -164,6 +155,7 @@ func (u *GitIdentityUsecase) Delete(ctx context.Context, uid uuid.UUID, id uuid.
164155
return err
165156
}
166157
u.tokenProvider.ClearCache(id)
158+
u.repoCache.Delete(uid.String() + ":" + id.String())
167159
return nil
168160
}
169161

backend/biz/host/usecase/host.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ type HostUsecase struct {
4545

4646
func NewHostUsecase(i *do.Injector) (domain.HostUsecase, error) {
4747
h := &HostUsecase{
48-
cfg: do.MustInvoke[*config.Config](i),
49-
redis: do.MustInvoke[*redis.Client](i),
50-
taskflow: do.MustInvoke[taskflow.Clienter](i),
51-
logger: do.MustInvoke[*slog.Logger](i).With("module", "HostUsecase"),
52-
repo: do.MustInvoke[domain.HostRepo](i),
53-
userRepo: do.MustInvoke[domain.UserRepo](i),
54-
girepo: do.MustInvoke[domain.GitIdentityRepo](i),
55-
vmexpireQueue: do.MustInvoke[*delayqueue.VMExpireQueue](i),
56-
tokenProvider: do.MustInvoke[*gituc.TokenProvider](i),
48+
cfg: do.MustInvoke[*config.Config](i),
49+
redis: do.MustInvoke[*redis.Client](i),
50+
taskflow: do.MustInvoke[taskflow.Clienter](i),
51+
logger: do.MustInvoke[*slog.Logger](i).With("module", "HostUsecase"),
52+
repo: do.MustInvoke[domain.HostRepo](i),
53+
userRepo: do.MustInvoke[domain.UserRepo](i),
54+
girepo: do.MustInvoke[domain.GitIdentityRepo](i),
55+
vmexpireQueue: do.MustInvoke[*delayqueue.VMExpireQueue](i),
56+
tokenProvider: do.MustInvoke[*gituc.TokenProvider](i),
5757
}
5858

5959
// 可选注入 PrivilegeChecker

backend/biz/register.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"github.com/samber/do"
55

66
"github.com/chaitin/MonkeyCode/backend/biz/file"
7-
"github.com/chaitin/MonkeyCode/backend/biz/vmidle"
87
"github.com/chaitin/MonkeyCode/backend/biz/git"
98
"github.com/chaitin/MonkeyCode/backend/biz/host"
109
"github.com/chaitin/MonkeyCode/backend/biz/notify"
@@ -14,6 +13,7 @@ import (
1413
"github.com/chaitin/MonkeyCode/backend/biz/task"
1514
"github.com/chaitin/MonkeyCode/backend/biz/team"
1615
"github.com/chaitin/MonkeyCode/backend/biz/user"
16+
"github.com/chaitin/MonkeyCode/backend/biz/vmidle"
1717
)
1818

1919
// RegisterAll 注册所有 biz 模块

backend/biz/task/service/types.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,3 @@ type wsContent struct {
3535
Content string `json:"content"`
3636
Message string `json:"message"`
3737
}
38-

backend/consts/host.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ const (
2222
type ProxyProtocol string
2323

2424
const (
25-
ProxyProtocolHTTP ProxyProtocol = "http"
26-
ProxyProtocolHTTPS ProxyProtocol = "https"
27-
ProxyProtocolSOCKS5 ProxyProtocol = "socks5"
25+
ProxyProtocolHTTP ProxyProtocol = "http"
26+
ProxyProtocolHTTPS ProxyProtocol = "https"
27+
ProxyProtocolSOCKS5 ProxyProtocol = "socks5"
2828
)
2929

3030
// TerminalMode 终端模式

backend/domain/git.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ type RepositoryOptions struct {
108108
Token string
109109
InstallID int64 // GitHub App 模式,其他平台忽略
110110
IsOAuth bool // GitLab/Gitea OAuth 模式,其他平台忽略
111+
Flush bool
111112
}
112113

113114
// TreeOptions 获取文件树参数

backend/domain/gitidentity.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
// GitIdentityUsecase Git 身份认证业务逻辑接口
1414
type GitIdentityUsecase interface {
1515
List(ctx context.Context, uid uuid.UUID) ([]*GitIdentity, error)
16-
Get(ctx context.Context, uid uuid.UUID, id uuid.UUID) (*GitIdentity, error)
16+
Get(ctx context.Context, uid uuid.UUID, id uuid.UUID, flush bool) (*GitIdentity, error)
1717
Add(ctx context.Context, uid uuid.UUID, req *AddGitIdentityReq) (*GitIdentity, error)
1818
Update(ctx context.Context, uid uuid.UUID, req *UpdateGitIdentityReq) error
1919
Delete(ctx context.Context, uid uuid.UUID, id uuid.UUID) error
@@ -92,9 +92,11 @@ type UpdateGitIdentityReq struct {
9292
OAuthExpiresAt *time.Time `json:"-"` // 内部使用,OAuth 过期时间
9393
}
9494

95+
9596
// GetGitIdentityReq 获取 Git 身份认证详情请求
9697
type GetGitIdentityReq struct {
97-
ID uuid.UUID `param:"id" validate:"required"`
98+
ID uuid.UUID `param:"id" validate:"required"`
99+
Flush bool `query:"flush"`
98100
}
99101

100102
// DeleteGitIdentityReq 删除 Git 身份认证请求

backend/domain/notify.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ type NotifyEventPayload struct {
107107

108108
// CreateNotifySendLogReq 创建通知发送日志请求
109109
type CreateNotifySendLogReq struct {
110-
SubscriptionID uuid.UUID `json:"subscription_id"`
111-
ChannelID uuid.UUID `json:"channel_id"`
112-
EventType consts.NotifyEventType `json:"event_type"`
113-
EventRefID string `json:"event_ref_id"`
114-
Status consts.NotifySendStatus `json:"status"`
115-
Error string `json:"error"`
110+
SubscriptionID uuid.UUID `json:"subscription_id"`
111+
ChannelID uuid.UUID `json:"channel_id"`
112+
EventType consts.NotifyEventType `json:"event_type"`
113+
EventRefID string `json:"event_ref_id"`
114+
Status consts.NotifySendStatus `json:"status"`
115+
Error string `json:"error"`
116116
}

backend/errcode/errcode.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ var (
9797
ErrEmailNotBound = web.NewErr(http.StatusOK, 10615, "err-email-not-bound")
9898

9999
// captcha 模块
100-
ErrCreateCaptchaFailed = web.NewErr(http.StatusOK, 10700, "err-create-captcha-failed")
101-
ErrRedeemCaptchaFailed = web.NewErr(http.StatusOK, 10701, "err-redeem-captcha-failed")
102-
ErrCaptchaVerifyFailed = web.NewErr(http.StatusOK, 10702, "err-captcha-verify-failed")
100+
ErrCreateCaptchaFailed = web.NewErr(http.StatusOK, 10700, "err-create-captcha-failed")
101+
ErrRedeemCaptchaFailed = web.NewErr(http.StatusOK, 10701, "err-redeem-captcha-failed")
102+
ErrCaptchaVerifyFailed = web.NewErr(http.StatusOK, 10702, "err-captcha-verify-failed")
103103

104104
ErrDepositFailed = web.NewErr(http.StatusOK, 10801, "err-deposit-failed")
105105

0 commit comments

Comments
 (0)