Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
420bedd6
Commit
420bedd6
authored
Dec 20, 2025
by
shaw
Browse files
Merge PR #8: refactor(backend): 添加 service 缓存端口
parents
a79f6c5e
7bbf6214
Changes
27
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/ports/email_cache.go
0 → 100644
View file @
420bedd6
package
ports
import
(
"context"
"time"
)
// VerificationCodeData represents verification code data
type
VerificationCodeData
struct
{
Code
string
Attempts
int
CreatedAt
time
.
Time
}
// EmailCache defines cache operations for email service
type
EmailCache
interface
{
GetVerificationCode
(
ctx
context
.
Context
,
email
string
)
(
*
VerificationCodeData
,
error
)
SetVerificationCode
(
ctx
context
.
Context
,
email
string
,
data
*
VerificationCodeData
,
ttl
time
.
Duration
)
error
DeleteVerificationCode
(
ctx
context
.
Context
,
email
string
)
error
}
backend/internal/service/ports/gateway_cache.go
0 → 100644
View file @
420bedd6
package
ports
import
(
"context"
"time"
)
// GatewayCache defines cache operations for gateway service
type
GatewayCache
interface
{
GetSessionAccountID
(
ctx
context
.
Context
,
sessionHash
string
)
(
int64
,
error
)
SetSessionAccountID
(
ctx
context
.
Context
,
sessionHash
string
,
accountID
int64
,
ttl
time
.
Duration
)
error
RefreshSessionTTL
(
ctx
context
.
Context
,
sessionHash
string
,
ttl
time
.
Duration
)
error
}
backend/internal/service/ports/identity_cache.go
0 → 100644
View file @
420bedd6
package
ports
import
"context"
// Fingerprint represents account fingerprint data
type
Fingerprint
struct
{
ClientID
string
UserAgent
string
StainlessLang
string
StainlessPackageVersion
string
StainlessOS
string
StainlessArch
string
StainlessRuntime
string
StainlessRuntimeVersion
string
}
// IdentityCache defines cache operations for identity service
type
IdentityCache
interface
{
GetFingerprint
(
ctx
context
.
Context
,
accountID
int64
)
(
*
Fingerprint
,
error
)
SetFingerprint
(
ctx
context
.
Context
,
accountID
int64
,
fp
*
Fingerprint
)
error
}
backend/internal/service/ports/redeem_cache.go
0 → 100644
View file @
420bedd6
package
ports
import
(
"context"
"time"
)
// RedeemCache defines cache operations for redeem service
type
RedeemCache
interface
{
GetRedeemAttemptCount
(
ctx
context
.
Context
,
userID
int64
)
(
int
,
error
)
IncrementRedeemAttemptCount
(
ctx
context
.
Context
,
userID
int64
)
error
AcquireRedeemLock
(
ctx
context
.
Context
,
code
string
,
ttl
time
.
Duration
)
(
bool
,
error
)
ReleaseRedeemLock
(
ctx
context
.
Context
,
code
string
)
error
}
backend/internal/service/ports/update_cache.go
0 → 100644
View file @
420bedd6
package
ports
import
(
"context"
"time"
)
// UpdateCache defines cache operations for update service
type
UpdateCache
interface
{
GetUpdateInfo
(
ctx
context
.
Context
)
(
string
,
error
)
SetUpdateInfo
(
ctx
context
.
Context
,
data
string
,
ttl
time
.
Duration
)
error
}
backend/internal/service/redeem_service.go
View file @
420bedd6
...
...
@@ -26,11 +26,9 @@ var (
)
const
(
redeemRateLimitKeyPrefix
=
"redeem:rate_limit:"
redeemLockKeyPrefix
=
"redeem:lock:"
redeemMaxErrorsPerHour
=
20
redeemRateLimitDuration
=
time
.
Hour
redeemLockDuration
=
10
*
time
.
Second
// 锁超时时间,防止死锁
redeemMaxErrorsPerHour
=
20
redeemRateLimitDuration
=
time
.
Hour
redeemLockDuration
=
10
*
time
.
Second
// 锁超时时间,防止死锁
)
// GenerateCodesRequest 生成兑换码请求
...
...
@@ -53,7 +51,7 @@ type RedeemService struct {
redeemRepo
ports
.
RedeemCodeRepository
userRepo
ports
.
UserRepository
subscriptionService
*
SubscriptionService
rdb
*
redis
.
Client
cache
ports
.
RedeemCache
billingCacheService
*
BillingCacheService
}
...
...
@@ -62,14 +60,14 @@ func NewRedeemService(
redeemRepo
ports
.
RedeemCodeRepository
,
userRepo
ports
.
UserRepository
,
subscriptionService
*
SubscriptionService
,
rdb
*
redis
.
Client
,
cache
ports
.
RedeemCache
,
billingCacheService
*
BillingCacheService
,
)
*
RedeemService
{
return
&
RedeemService
{
redeemRepo
:
redeemRepo
,
userRepo
:
userRepo
,
subscriptionService
:
subscriptionService
,
rdb
:
rdb
,
cache
:
cache
,
billingCacheService
:
billingCacheService
,
}
}
...
...
@@ -140,13 +138,11 @@ func (s *RedeemService) GenerateCodes(ctx context.Context, req GenerateCodesRequ
// checkRedeemRateLimit 检查用户兑换错误次数是否超限
func
(
s
*
RedeemService
)
checkRedeemRateLimit
(
ctx
context
.
Context
,
userID
int64
)
error
{
if
s
.
rdb
==
nil
{
if
s
.
cache
==
nil
{
return
nil
}
key
:=
fmt
.
Sprintf
(
"%s%d"
,
redeemRateLimitKeyPrefix
,
userID
)
count
,
err
:=
s
.
rdb
.
Get
(
ctx
,
key
)
.
Int
()
count
,
err
:=
s
.
cache
.
GetRedeemAttemptCount
(
ctx
,
userID
)
if
err
!=
nil
&&
!
errors
.
Is
(
err
,
redis
.
Nil
)
{
// Redis 出错时不阻止用户操作
return
nil
...
...
@@ -161,27 +157,21 @@ func (s *RedeemService) checkRedeemRateLimit(ctx context.Context, userID int64)
// incrementRedeemErrorCount 增加用户兑换错误计数
func
(
s
*
RedeemService
)
incrementRedeemErrorCount
(
ctx
context
.
Context
,
userID
int64
)
{
if
s
.
rdb
==
nil
{
if
s
.
cache
==
nil
{
return
}
key
:=
fmt
.
Sprintf
(
"%s%d"
,
redeemRateLimitKeyPrefix
,
userID
)
pipe
:=
s
.
rdb
.
Pipeline
()
pipe
.
Incr
(
ctx
,
key
)
pipe
.
Expire
(
ctx
,
key
,
redeemRateLimitDuration
)
_
,
_
=
pipe
.
Exec
(
ctx
)
_
=
s
.
cache
.
IncrementRedeemAttemptCount
(
ctx
,
userID
)
}
// acquireRedeemLock 尝试获取兑换码的分布式锁
// 返回 true 表示获取成功,false 表示锁已被占用
func
(
s
*
RedeemService
)
acquireRedeemLock
(
ctx
context
.
Context
,
code
string
)
bool
{
if
s
.
rdb
==
nil
{
if
s
.
cache
==
nil
{
return
true
// 无 Redis 时降级为不加锁
}
key
:=
redeemLockKeyPrefix
+
code
ok
,
err
:=
s
.
rdb
.
SetNX
(
ctx
,
key
,
"1"
,
redeemLockDuration
)
.
Result
()
ok
,
err
:=
s
.
cache
.
AcquireRedeemLock
(
ctx
,
code
,
redeemLockDuration
)
if
err
!=
nil
{
// Redis 出错时不阻止操作,依赖数据库层面的状态检查
return
true
...
...
@@ -191,12 +181,11 @@ func (s *RedeemService) acquireRedeemLock(ctx context.Context, code string) bool
// releaseRedeemLock 释放兑换码的分布式锁
func
(
s
*
RedeemService
)
releaseRedeemLock
(
ctx
context
.
Context
,
code
string
)
{
if
s
.
rdb
==
nil
{
if
s
.
cache
==
nil
{
return
}
key
:=
redeemLockKeyPrefix
+
code
s
.
rdb
.
Del
(
ctx
,
key
)
_
=
s
.
cache
.
ReleaseRedeemLock
(
ctx
,
code
)
}
// Redeem 使用兑换码
...
...
backend/internal/service/update_service.go
View file @
420bedd6
...
...
@@ -18,7 +18,7 @@ import (
"strings"
"time"
"
github.com/redis/go-redis/v9
"
"
sub2api/internal/service/ports
"
)
const
(
...
...
@@ -36,15 +36,15 @@ const (
// UpdateService handles software updates
type
UpdateService
struct
{
rdb
*
redis
.
Client
cache
ports
.
UpdateCache
currentVersion
string
buildType
string
// "source" for manual builds, "release" for CI builds
}
// NewUpdateService creates a new UpdateService
func
NewUpdateService
(
rdb
*
redis
.
Client
,
version
,
buildType
string
)
*
UpdateService
{
func
NewUpdateService
(
cache
ports
.
UpdateCache
,
version
,
buildType
string
)
*
UpdateService
{
return
&
UpdateService
{
rdb
:
rdb
,
cache
:
cache
,
currentVersion
:
version
,
buildType
:
buildType
,
}
...
...
@@ -533,7 +533,7 @@ func (s *UpdateService) extractBinary(archivePath, destPath string) error {
}
func
(
s
*
UpdateService
)
getFromCache
(
ctx
context
.
Context
)
(
*
UpdateInfo
,
error
)
{
data
,
err
:=
s
.
rdb
.
Get
(
ctx
,
updateCacheKey
)
.
Result
(
)
data
,
err
:=
s
.
cache
.
GetUpdateInfo
(
ctx
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -573,7 +573,7 @@ func (s *UpdateService) saveToCache(ctx context.Context, info *UpdateInfo) {
}
data
,
_
:=
json
.
Marshal
(
cacheData
)
s
.
rdb
.
Set
(
ctx
,
updateCacheKey
,
data
,
time
.
Duration
(
updateCacheTTL
)
*
time
.
Second
)
s
.
cache
.
SetUpdateInfo
(
ctx
,
string
(
data
)
,
time
.
Duration
(
updateCacheTTL
)
*
time
.
Second
)
}
// compareVersions compares two semantic versions
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment