Commit f51ad2e1 authored by Forest's avatar Forest
Browse files

refactor: 删除 ports 目录

parent f57f12c6
...@@ -3,10 +3,11 @@ package repository ...@@ -3,10 +3,11 @@ package repository
import ( import (
"context" "context"
"errors" "errors"
"time"
"github.com/Wei-Shaw/sub2api/internal/model" "github.com/Wei-Shaw/sub2api/internal/model"
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination" "github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"time"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
...@@ -357,7 +358,7 @@ func (r *AccountRepository) UpdateExtra(ctx context.Context, id int64, updates m ...@@ -357,7 +358,7 @@ func (r *AccountRepository) UpdateExtra(ctx context.Context, id int64, updates m
// BulkUpdate updates multiple accounts with the provided fields. // BulkUpdate updates multiple accounts with the provided fields.
// It merges credentials/extra JSONB fields instead of overwriting them. // It merges credentials/extra JSONB fields instead of overwriting them.
func (r *AccountRepository) BulkUpdate(ctx context.Context, ids []int64, updates ports.AccountBulkUpdate) (int64, error) { func (r *AccountRepository) BulkUpdate(ctx context.Context, ids []int64, updates service.AccountBulkUpdate) (int64, error) {
if len(ids) == 0 { if len(ids) == 0 {
return 0, nil return 0, nil
} }
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/Wei-Shaw/sub2api/internal/model" "github.com/Wei-Shaw/sub2api/internal/model"
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination" "github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"gorm.io/gorm" "gorm.io/gorm"
) )
...@@ -513,7 +513,7 @@ func (s *AccountRepoSuite) TestBulkUpdate() { ...@@ -513,7 +513,7 @@ func (s *AccountRepoSuite) TestBulkUpdate() {
a2 := mustCreateAccount(s.T(), s.db, &model.Account{Name: "bulk2", Priority: 1}) a2 := mustCreateAccount(s.T(), s.db, &model.Account{Name: "bulk2", Priority: 1})
newPriority := 99 newPriority := 99
affected, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID, a2.ID}, ports.AccountBulkUpdate{ affected, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID, a2.ID}, service.AccountBulkUpdate{
Priority: &newPriority, Priority: &newPriority,
}) })
s.Require().NoError(err) s.Require().NoError(err)
...@@ -531,7 +531,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeCredentials() { ...@@ -531,7 +531,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeCredentials() {
Credentials: model.JSONB{"existing": "value"}, Credentials: model.JSONB{"existing": "value"},
}) })
_, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, ports.AccountBulkUpdate{ _, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, service.AccountBulkUpdate{
Credentials: model.JSONB{"new_key": "new_value"}, Credentials: model.JSONB{"new_key": "new_value"},
}) })
s.Require().NoError(err) s.Require().NoError(err)
...@@ -547,7 +547,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeExtra() { ...@@ -547,7 +547,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeExtra() {
Extra: model.JSONB{"existing": "val"}, Extra: model.JSONB{"existing": "val"},
}) })
_, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, ports.AccountBulkUpdate{ _, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, service.AccountBulkUpdate{
Extra: model.JSONB{"new_key": "new_val"}, Extra: model.JSONB{"new_key": "new_val"},
}) })
s.Require().NoError(err) s.Require().NoError(err)
...@@ -558,7 +558,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeExtra() { ...@@ -558,7 +558,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_MergeExtra() {
} }
func (s *AccountRepoSuite) TestBulkUpdate_EmptyIDs() { func (s *AccountRepoSuite) TestBulkUpdate_EmptyIDs() {
affected, err := s.repo.BulkUpdate(s.ctx, []int64{}, ports.AccountBulkUpdate{}) affected, err := s.repo.BulkUpdate(s.ctx, []int64{}, service.AccountBulkUpdate{})
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Zero(affected) s.Require().Zero(affected)
} }
...@@ -566,7 +566,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_EmptyIDs() { ...@@ -566,7 +566,7 @@ func (s *AccountRepoSuite) TestBulkUpdate_EmptyIDs() {
func (s *AccountRepoSuite) TestBulkUpdate_EmptyUpdates() { func (s *AccountRepoSuite) TestBulkUpdate_EmptyUpdates() {
a1 := mustCreateAccount(s.T(), s.db, &model.Account{Name: "bulk-empty"}) a1 := mustCreateAccount(s.T(), s.db, &model.Account{Name: "bulk-empty"})
affected, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, ports.AccountBulkUpdate{}) affected, err := s.repo.BulkUpdate(s.ctx, []int64{a1.ID}, service.AccountBulkUpdate{})
s.Require().NoError(err) s.Require().NoError(err)
s.Require().Zero(affected) s.Require().Zero(affected)
} }
......
...@@ -5,8 +5,7 @@ import ( ...@@ -5,8 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -19,7 +18,7 @@ type apiKeyCache struct { ...@@ -19,7 +18,7 @@ type apiKeyCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewApiKeyCache(rdb *redis.Client) ports.ApiKeyCache { func NewApiKeyCache(rdb *redis.Client) service.ApiKeyCache {
return &apiKeyCache{rdb: rdb} return &apiKeyCache{rdb: rdb}
} }
......
...@@ -8,8 +8,7 @@ import ( ...@@ -8,8 +8,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -58,7 +57,7 @@ type billingCache struct { ...@@ -58,7 +57,7 @@ type billingCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewBillingCache(rdb *redis.Client) ports.BillingCache { func NewBillingCache(rdb *redis.Client) service.BillingCache {
return &billingCache{rdb: rdb} return &billingCache{rdb: rdb}
} }
...@@ -90,7 +89,7 @@ func (c *billingCache) InvalidateUserBalance(ctx context.Context, userID int64) ...@@ -90,7 +89,7 @@ func (c *billingCache) InvalidateUserBalance(ctx context.Context, userID int64)
return c.rdb.Del(ctx, key).Err() return c.rdb.Del(ctx, key).Err()
} }
func (c *billingCache) GetSubscriptionCache(ctx context.Context, userID, groupID int64) (*ports.SubscriptionCacheData, error) { func (c *billingCache) GetSubscriptionCache(ctx context.Context, userID, groupID int64) (*service.SubscriptionCacheData, error) {
key := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID) key := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID)
result, err := c.rdb.HGetAll(ctx, key).Result() result, err := c.rdb.HGetAll(ctx, key).Result()
if err != nil { if err != nil {
...@@ -102,8 +101,8 @@ func (c *billingCache) GetSubscriptionCache(ctx context.Context, userID, groupID ...@@ -102,8 +101,8 @@ func (c *billingCache) GetSubscriptionCache(ctx context.Context, userID, groupID
return c.parseSubscriptionCache(result) return c.parseSubscriptionCache(result)
} }
func (c *billingCache) parseSubscriptionCache(data map[string]string) (*ports.SubscriptionCacheData, error) { func (c *billingCache) parseSubscriptionCache(data map[string]string) (*service.SubscriptionCacheData, error) {
result := &ports.SubscriptionCacheData{} result := &service.SubscriptionCacheData{}
result.Status = data[subFieldStatus] result.Status = data[subFieldStatus]
if result.Status == "" { if result.Status == "" {
...@@ -136,7 +135,7 @@ func (c *billingCache) parseSubscriptionCache(data map[string]string) (*ports.Su ...@@ -136,7 +135,7 @@ func (c *billingCache) parseSubscriptionCache(data map[string]string) (*ports.Su
return result, nil return result, nil
} }
func (c *billingCache) SetSubscriptionCache(ctx context.Context, userID, groupID int64, data *ports.SubscriptionCacheData) error { func (c *billingCache) SetSubscriptionCache(ctx context.Context, userID, groupID int64, data *service.SubscriptionCacheData) error {
if data == nil { if data == nil {
return nil return nil
} }
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
...@@ -21,18 +21,18 @@ type BillingCacheSuite struct { ...@@ -21,18 +21,18 @@ type BillingCacheSuite struct {
func (s *BillingCacheSuite) TestUserBalance() { func (s *BillingCacheSuite) TestUserBalance() {
tests := []struct { tests := []struct {
name string name string
fn func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) fn func(ctx context.Context, rdb *redis.Client, cache service.BillingCache)
}{ }{
{ {
name: "missing_key_returns_redis_nil", name: "missing_key_returns_redis_nil",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
_, err := cache.GetUserBalance(ctx, 1) _, err := cache.GetUserBalance(ctx, 1)
require.ErrorIs(s.T(), err, redis.Nil, "expected redis.Nil for missing balance key") require.ErrorIs(s.T(), err, redis.Nil, "expected redis.Nil for missing balance key")
}, },
}, },
{ {
name: "deduct_on_nonexistent_is_noop", name: "deduct_on_nonexistent_is_noop",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(1) userID := int64(1)
balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID) balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID)
...@@ -44,7 +44,7 @@ func (s *BillingCacheSuite) TestUserBalance() { ...@@ -44,7 +44,7 @@ func (s *BillingCacheSuite) TestUserBalance() {
}, },
{ {
name: "set_and_get_with_ttl", name: "set_and_get_with_ttl",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(2) userID := int64(2)
balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID) balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID)
...@@ -61,7 +61,7 @@ func (s *BillingCacheSuite) TestUserBalance() { ...@@ -61,7 +61,7 @@ func (s *BillingCacheSuite) TestUserBalance() {
}, },
{ {
name: "deduct_reduces_balance", name: "deduct_reduces_balance",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(3) userID := int64(3)
require.NoError(s.T(), cache.SetUserBalance(ctx, userID, 10.5), "SetUserBalance") require.NoError(s.T(), cache.SetUserBalance(ctx, userID, 10.5), "SetUserBalance")
...@@ -74,7 +74,7 @@ func (s *BillingCacheSuite) TestUserBalance() { ...@@ -74,7 +74,7 @@ func (s *BillingCacheSuite) TestUserBalance() {
}, },
{ {
name: "invalidate_removes_key", name: "invalidate_removes_key",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(100) userID := int64(100)
balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID) balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID)
...@@ -96,7 +96,7 @@ func (s *BillingCacheSuite) TestUserBalance() { ...@@ -96,7 +96,7 @@ func (s *BillingCacheSuite) TestUserBalance() {
}, },
{ {
name: "deduct_refreshes_ttl", name: "deduct_refreshes_ttl",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(103) userID := int64(103)
balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID) balanceKey := fmt.Sprintf("%s%d", billingBalanceKeyPrefix, userID)
...@@ -133,11 +133,11 @@ func (s *BillingCacheSuite) TestUserBalance() { ...@@ -133,11 +133,11 @@ func (s *BillingCacheSuite) TestUserBalance() {
func (s *BillingCacheSuite) TestSubscriptionCache() { func (s *BillingCacheSuite) TestSubscriptionCache() {
tests := []struct { tests := []struct {
name string name string
fn func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) fn func(ctx context.Context, rdb *redis.Client, cache service.BillingCache)
}{ }{
{ {
name: "missing_key_returns_redis_nil", name: "missing_key_returns_redis_nil",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(10) userID := int64(10)
groupID := int64(20) groupID := int64(20)
...@@ -147,7 +147,7 @@ func (s *BillingCacheSuite) TestSubscriptionCache() { ...@@ -147,7 +147,7 @@ func (s *BillingCacheSuite) TestSubscriptionCache() {
}, },
{ {
name: "update_usage_on_nonexistent_is_noop", name: "update_usage_on_nonexistent_is_noop",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(11) userID := int64(11)
groupID := int64(21) groupID := int64(21)
subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID) subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID)
...@@ -161,12 +161,12 @@ func (s *BillingCacheSuite) TestSubscriptionCache() { ...@@ -161,12 +161,12 @@ func (s *BillingCacheSuite) TestSubscriptionCache() {
}, },
{ {
name: "set_and_get_with_ttl", name: "set_and_get_with_ttl",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(12) userID := int64(12)
groupID := int64(22) groupID := int64(22)
subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID) subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID)
data := &ports.SubscriptionCacheData{ data := &service.SubscriptionCacheData{
Status: "active", Status: "active",
ExpiresAt: time.Now().Add(1 * time.Hour), ExpiresAt: time.Now().Add(1 * time.Hour),
DailyUsage: 1.0, DailyUsage: 1.0,
...@@ -189,11 +189,11 @@ func (s *BillingCacheSuite) TestSubscriptionCache() { ...@@ -189,11 +189,11 @@ func (s *BillingCacheSuite) TestSubscriptionCache() {
}, },
{ {
name: "update_usage_increments_all_fields", name: "update_usage_increments_all_fields",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(13) userID := int64(13)
groupID := int64(23) groupID := int64(23)
data := &ports.SubscriptionCacheData{ data := &service.SubscriptionCacheData{
Status: "active", Status: "active",
ExpiresAt: time.Now().Add(1 * time.Hour), ExpiresAt: time.Now().Add(1 * time.Hour),
DailyUsage: 1.0, DailyUsage: 1.0,
...@@ -214,12 +214,12 @@ func (s *BillingCacheSuite) TestSubscriptionCache() { ...@@ -214,12 +214,12 @@ func (s *BillingCacheSuite) TestSubscriptionCache() {
}, },
{ {
name: "invalidate_removes_key", name: "invalidate_removes_key",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(101) userID := int64(101)
groupID := int64(10) groupID := int64(10)
subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID) subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID)
data := &ports.SubscriptionCacheData{ data := &service.SubscriptionCacheData{
Status: "active", Status: "active",
ExpiresAt: time.Now().Add(1 * time.Hour), ExpiresAt: time.Now().Add(1 * time.Hour),
DailyUsage: 1.0, DailyUsage: 1.0,
...@@ -245,7 +245,7 @@ func (s *BillingCacheSuite) TestSubscriptionCache() { ...@@ -245,7 +245,7 @@ func (s *BillingCacheSuite) TestSubscriptionCache() {
}, },
{ {
name: "missing_status_returns_parsing_error", name: "missing_status_returns_parsing_error",
fn: func(ctx context.Context, rdb *redis.Client, cache ports.BillingCache) { fn: func(ctx context.Context, rdb *redis.Client, cache service.BillingCache) {
userID := int64(102) userID := int64(102)
groupID := int64(11) groupID := int64(11)
subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID) subKey := fmt.Sprintf("%s%d:%d", billingSubKeyPrefix, userID, groupID)
......
...@@ -5,8 +5,7 @@ import ( ...@@ -5,8 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -107,7 +106,7 @@ type concurrencyCache struct { ...@@ -107,7 +106,7 @@ type concurrencyCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewConcurrencyCache(rdb *redis.Client) ports.ConcurrencyCache { func NewConcurrencyCache(rdb *redis.Client) service.ConcurrencyCache {
return &concurrencyCache{rdb: rdb} return &concurrencyCache{rdb: rdb}
} }
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
type ConcurrencyCacheSuite struct { type ConcurrencyCacheSuite struct {
IntegrationRedisSuite IntegrationRedisSuite
cache ports.ConcurrencyCache cache service.ConcurrencyCache
} }
func (s *ConcurrencyCacheSuite) SetupTest() { func (s *ConcurrencyCacheSuite) SetupTest() {
......
...@@ -5,8 +5,7 @@ import ( ...@@ -5,8 +5,7 @@ import (
"encoding/json" "encoding/json"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -16,24 +15,24 @@ type emailCache struct { ...@@ -16,24 +15,24 @@ type emailCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewEmailCache(rdb *redis.Client) ports.EmailCache { func NewEmailCache(rdb *redis.Client) service.EmailCache {
return &emailCache{rdb: rdb} return &emailCache{rdb: rdb}
} }
func (c *emailCache) GetVerificationCode(ctx context.Context, email string) (*ports.VerificationCodeData, error) { func (c *emailCache) GetVerificationCode(ctx context.Context, email string) (*service.VerificationCodeData, error) {
key := verifyCodeKeyPrefix + email key := verifyCodeKeyPrefix + email
val, err := c.rdb.Get(ctx, key).Result() val, err := c.rdb.Get(ctx, key).Result()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var data ports.VerificationCodeData var data service.VerificationCodeData
if err := json.Unmarshal([]byte(val), &data); err != nil { if err := json.Unmarshal([]byte(val), &data); err != nil {
return nil, err return nil, err
} }
return &data, nil return &data, nil
} }
func (c *emailCache) SetVerificationCode(ctx context.Context, email string, data *ports.VerificationCodeData, ttl time.Duration) error { func (c *emailCache) SetVerificationCode(ctx context.Context, email string, data *service.VerificationCodeData, ttl time.Duration) error {
key := verifyCodeKeyPrefix + email key := verifyCodeKeyPrefix + email
val, err := json.Marshal(data) val, err := json.Marshal(data)
if err != nil { if err != nil {
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
type EmailCacheSuite struct { type EmailCacheSuite struct {
IntegrationRedisSuite IntegrationRedisSuite
cache ports.EmailCache cache service.EmailCache
} }
func (s *EmailCacheSuite) SetupTest() { func (s *EmailCacheSuite) SetupTest() {
...@@ -31,7 +31,7 @@ func (s *EmailCacheSuite) TestGetVerificationCode_Missing() { ...@@ -31,7 +31,7 @@ func (s *EmailCacheSuite) TestGetVerificationCode_Missing() {
func (s *EmailCacheSuite) TestSetAndGetVerificationCode() { func (s *EmailCacheSuite) TestSetAndGetVerificationCode() {
email := "a@example.com" email := "a@example.com"
emailTTL := 2 * time.Minute emailTTL := 2 * time.Minute
data := &ports.VerificationCodeData{Code: "123456", Attempts: 1, CreatedAt: time.Now()} data := &service.VerificationCodeData{Code: "123456", Attempts: 1, CreatedAt: time.Now()}
require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, emailTTL), "SetVerificationCode") require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, emailTTL), "SetVerificationCode")
...@@ -44,7 +44,7 @@ func (s *EmailCacheSuite) TestSetAndGetVerificationCode() { ...@@ -44,7 +44,7 @@ func (s *EmailCacheSuite) TestSetAndGetVerificationCode() {
func (s *EmailCacheSuite) TestVerificationCode_TTL() { func (s *EmailCacheSuite) TestVerificationCode_TTL() {
email := "ttl@example.com" email := "ttl@example.com"
emailTTL := 2 * time.Minute emailTTL := 2 * time.Minute
data := &ports.VerificationCodeData{Code: "654321", Attempts: 0, CreatedAt: time.Now()} data := &service.VerificationCodeData{Code: "654321", Attempts: 0, CreatedAt: time.Now()}
require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, emailTTL), "SetVerificationCode") require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, emailTTL), "SetVerificationCode")
...@@ -56,7 +56,7 @@ func (s *EmailCacheSuite) TestVerificationCode_TTL() { ...@@ -56,7 +56,7 @@ func (s *EmailCacheSuite) TestVerificationCode_TTL() {
func (s *EmailCacheSuite) TestDeleteVerificationCode() { func (s *EmailCacheSuite) TestDeleteVerificationCode() {
email := "delete@example.com" email := "delete@example.com"
data := &ports.VerificationCodeData{Code: "999999", Attempts: 0, CreatedAt: time.Now()} data := &service.VerificationCodeData{Code: "999999", Attempts: 0, CreatedAt: time.Now()}
require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, 2*time.Minute), "SetVerificationCode") require.NoError(s.T(), s.cache.SetVerificationCode(s.ctx, email, data, 2*time.Minute), "SetVerificationCode")
......
...@@ -4,8 +4,7 @@ import ( ...@@ -4,8 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -15,7 +14,7 @@ type gatewayCache struct { ...@@ -15,7 +14,7 @@ type gatewayCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewGatewayCache(rdb *redis.Client) ports.GatewayCache { func NewGatewayCache(rdb *redis.Client) service.GatewayCache {
return &gatewayCache{rdb: rdb} return &gatewayCache{rdb: rdb}
} }
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
...@@ -15,7 +15,7 @@ import ( ...@@ -15,7 +15,7 @@ import (
type GatewayCacheSuite struct { type GatewayCacheSuite struct {
IntegrationRedisSuite IntegrationRedisSuite
cache ports.GatewayCache cache service.GatewayCache
} }
func (s *GatewayCacheSuite) SetupTest() { func (s *GatewayCacheSuite) SetupTest() {
......
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/config" "github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
) )
// httpUpstreamService is a generic HTTP upstream service that can be used for // httpUpstreamService is a generic HTTP upstream service that can be used for
...@@ -17,7 +17,7 @@ type httpUpstreamService struct { ...@@ -17,7 +17,7 @@ type httpUpstreamService struct {
} }
// NewHTTPUpstream creates a new generic HTTP upstream service // NewHTTPUpstream creates a new generic HTTP upstream service
func NewHTTPUpstream(cfg *config.Config) ports.HTTPUpstream { func NewHTTPUpstream(cfg *config.Config) service.HTTPUpstream {
responseHeaderTimeout := time.Duration(cfg.Gateway.ResponseHeaderTimeout) * time.Second responseHeaderTimeout := time.Duration(cfg.Gateway.ResponseHeaderTimeout) * time.Second
if responseHeaderTimeout == 0 { if responseHeaderTimeout == 0 {
responseHeaderTimeout = 300 * time.Second responseHeaderTimeout = 300 * time.Second
......
...@@ -6,8 +6,7 @@ import ( ...@@ -6,8 +6,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -20,24 +19,24 @@ type identityCache struct { ...@@ -20,24 +19,24 @@ type identityCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewIdentityCache(rdb *redis.Client) ports.IdentityCache { func NewIdentityCache(rdb *redis.Client) service.IdentityCache {
return &identityCache{rdb: rdb} return &identityCache{rdb: rdb}
} }
func (c *identityCache) GetFingerprint(ctx context.Context, accountID int64) (*ports.Fingerprint, error) { func (c *identityCache) GetFingerprint(ctx context.Context, accountID int64) (*service.Fingerprint, error) {
key := fmt.Sprintf("%s%d", fingerprintKeyPrefix, accountID) key := fmt.Sprintf("%s%d", fingerprintKeyPrefix, accountID)
val, err := c.rdb.Get(ctx, key).Result() val, err := c.rdb.Get(ctx, key).Result()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var fp ports.Fingerprint var fp service.Fingerprint
if err := json.Unmarshal([]byte(val), &fp); err != nil { if err := json.Unmarshal([]byte(val), &fp); err != nil {
return nil, err return nil, err
} }
return &fp, nil return &fp, nil
} }
func (c *identityCache) SetFingerprint(ctx context.Context, accountID int64, fp *ports.Fingerprint) error { func (c *identityCache) SetFingerprint(ctx context.Context, accountID int64, fp *service.Fingerprint) error {
key := fmt.Sprintf("%s%d", fingerprintKeyPrefix, accountID) key := fmt.Sprintf("%s%d", fingerprintKeyPrefix, accountID)
val, err := json.Marshal(fp) val, err := json.Marshal(fp)
if err != nil { if err != nil {
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
...@@ -30,7 +30,7 @@ func (s *IdentityCacheSuite) TestGetFingerprint_Missing() { ...@@ -30,7 +30,7 @@ func (s *IdentityCacheSuite) TestGetFingerprint_Missing() {
} }
func (s *IdentityCacheSuite) TestSetAndGetFingerprint() { func (s *IdentityCacheSuite) TestSetAndGetFingerprint() {
fp := &ports.Fingerprint{ClientID: "c1", UserAgent: "ua"} fp := &service.Fingerprint{ClientID: "c1", UserAgent: "ua"}
require.NoError(s.T(), s.cache.SetFingerprint(s.ctx, 1, fp), "SetFingerprint") require.NoError(s.T(), s.cache.SetFingerprint(s.ctx, 1, fp), "SetFingerprint")
gotFP, err := s.cache.GetFingerprint(s.ctx, 1) gotFP, err := s.cache.GetFingerprint(s.ctx, 1)
require.NoError(s.T(), err, "GetFingerprint") require.NoError(s.T(), err, "GetFingerprint")
...@@ -39,7 +39,7 @@ func (s *IdentityCacheSuite) TestSetAndGetFingerprint() { ...@@ -39,7 +39,7 @@ func (s *IdentityCacheSuite) TestSetAndGetFingerprint() {
} }
func (s *IdentityCacheSuite) TestFingerprint_TTL() { func (s *IdentityCacheSuite) TestFingerprint_TTL() {
fp := &ports.Fingerprint{ClientID: "c1", UserAgent: "ua"} fp := &service.Fingerprint{ClientID: "c1", UserAgent: "ua"}
require.NoError(s.T(), s.cache.SetFingerprint(s.ctx, 2, fp)) require.NoError(s.T(), s.cache.SetFingerprint(s.ctx, 2, fp))
fpKey := fmt.Sprintf("%s%d", fingerprintKeyPrefix, 2) fpKey := fmt.Sprintf("%s%d", fingerprintKeyPrefix, 2)
......
...@@ -7,13 +7,12 @@ import ( ...@@ -7,13 +7,12 @@ import (
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai" "github.com/Wei-Shaw/sub2api/internal/pkg/openai"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/imroc/req/v3" "github.com/imroc/req/v3"
) )
// NewOpenAIOAuthClient creates a new OpenAI OAuth client // NewOpenAIOAuthClient creates a new OpenAI OAuth client
func NewOpenAIOAuthClient() ports.OpenAIOAuthClient { func NewOpenAIOAuthClient() service.OpenAIOAuthClient {
return &openaiOAuthService{tokenURL: openai.TokenURL} return &openaiOAuthService{tokenURL: openai.TokenURL}
} }
......
...@@ -5,8 +5,7 @@ import ( ...@@ -5,8 +5,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -20,7 +19,7 @@ type redeemCache struct { ...@@ -20,7 +19,7 @@ type redeemCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewRedeemCache(rdb *redis.Client) ports.RedeemCache { func NewRedeemCache(rdb *redis.Client) service.RedeemCache {
return &redeemCache{rdb: rdb} return &redeemCache{rdb: rdb}
} }
......
...@@ -4,8 +4,7 @@ import ( ...@@ -4,8 +4,7 @@ import (
"context" "context"
"time" "time"
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
) )
...@@ -15,7 +14,7 @@ type updateCache struct { ...@@ -15,7 +14,7 @@ type updateCache struct {
rdb *redis.Client rdb *redis.Client
} }
func NewUpdateCache(rdb *redis.Client) ports.UpdateCache { func NewUpdateCache(rdb *redis.Client) service.UpdateCache {
return &updateCache{rdb: rdb} return &updateCache{rdb: rdb}
} }
......
package repository package repository
import ( import (
"github.com/Wei-Shaw/sub2api/internal/service/ports" "github.com/Wei-Shaw/sub2api/internal/service"
"github.com/google/wire" "github.com/google/wire"
) )
...@@ -40,13 +39,13 @@ var ProviderSet = wire.NewSet( ...@@ -40,13 +39,13 @@ var ProviderSet = wire.NewSet(
NewOpenAIOAuthClient, NewOpenAIOAuthClient,
// Bind concrete repositories to service port interfaces // Bind concrete repositories to service port interfaces
wire.Bind(new(ports.UserRepository), new(*UserRepository)), wire.Bind(new(service.UserRepository), new(*UserRepository)),
wire.Bind(new(ports.ApiKeyRepository), new(*ApiKeyRepository)), wire.Bind(new(service.ApiKeyRepository), new(*ApiKeyRepository)),
wire.Bind(new(ports.GroupRepository), new(*GroupRepository)), wire.Bind(new(service.GroupRepository), new(*GroupRepository)),
wire.Bind(new(ports.AccountRepository), new(*AccountRepository)), wire.Bind(new(service.AccountRepository), new(*AccountRepository)),
wire.Bind(new(ports.ProxyRepository), new(*ProxyRepository)), wire.Bind(new(service.ProxyRepository), new(*ProxyRepository)),
wire.Bind(new(ports.RedeemCodeRepository), new(*RedeemCodeRepository)), wire.Bind(new(service.RedeemCodeRepository), new(*RedeemCodeRepository)),
wire.Bind(new(ports.UsageLogRepository), new(*UsageLogRepository)), wire.Bind(new(service.UsageLogRepository), new(*UsageLogRepository)),
wire.Bind(new(ports.SettingRepository), new(*SettingRepository)), wire.Bind(new(service.SettingRepository), new(*SettingRepository)),
wire.Bind(new(ports.UserSubscriptionRepository), new(*UserSubscriptionRepository)), wire.Bind(new(service.UserSubscriptionRepository), new(*UserSubscriptionRepository)),
) )
...@@ -4,10 +4,10 @@ import ( ...@@ -4,10 +4,10 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"time"
"github.com/Wei-Shaw/sub2api/internal/model" "github.com/Wei-Shaw/sub2api/internal/model"
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination" "github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
"github.com/Wei-Shaw/sub2api/internal/service/ports"
"gorm.io/gorm" "gorm.io/gorm"
) )
...@@ -15,6 +15,51 @@ var ( ...@@ -15,6 +15,51 @@ var (
ErrAccountNotFound = errors.New("account not found") ErrAccountNotFound = errors.New("account not found")
) )
type AccountRepository interface {
Create(ctx context.Context, account *model.Account) error
GetByID(ctx context.Context, id int64) (*model.Account, error)
// GetByCRSAccountID finds an account previously synced from CRS.
// Returns (nil, nil) if not found.
GetByCRSAccountID(ctx context.Context, crsAccountID string) (*model.Account, error)
Update(ctx context.Context, account *model.Account) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, params pagination.PaginationParams) ([]model.Account, *pagination.PaginationResult, error)
ListWithFilters(ctx context.Context, params pagination.PaginationParams, platform, accountType, status, search string) ([]model.Account, *pagination.PaginationResult, error)
ListByGroup(ctx context.Context, groupID int64) ([]model.Account, error)
ListActive(ctx context.Context) ([]model.Account, error)
ListByPlatform(ctx context.Context, platform string) ([]model.Account, error)
UpdateLastUsed(ctx context.Context, id int64) error
SetError(ctx context.Context, id int64, errorMsg string) error
SetSchedulable(ctx context.Context, id int64, schedulable bool) error
BindGroups(ctx context.Context, accountID int64, groupIDs []int64) error
ListSchedulable(ctx context.Context) ([]model.Account, error)
ListSchedulableByGroupID(ctx context.Context, groupID int64) ([]model.Account, error)
ListSchedulableByPlatform(ctx context.Context, platform string) ([]model.Account, error)
ListSchedulableByGroupIDAndPlatform(ctx context.Context, groupID int64, platform string) ([]model.Account, error)
SetRateLimited(ctx context.Context, id int64, resetAt time.Time) error
SetOverloaded(ctx context.Context, id int64, until time.Time) error
ClearRateLimit(ctx context.Context, id int64) error
UpdateSessionWindow(ctx context.Context, id int64, start, end *time.Time, status string) error
UpdateExtra(ctx context.Context, id int64, updates map[string]any) error
BulkUpdate(ctx context.Context, ids []int64, updates AccountBulkUpdate) (int64, error)
}
// AccountBulkUpdate describes the fields that can be updated in a bulk operation.
// Nil pointers mean "do not change".
type AccountBulkUpdate struct {
Name *string
ProxyID *int64
Concurrency *int
Priority *int
Status *string
Credentials map[string]any
Extra map[string]any
}
// CreateAccountRequest 创建账号请求 // CreateAccountRequest 创建账号请求
type CreateAccountRequest struct { type CreateAccountRequest struct {
Name string `json:"name"` Name string `json:"name"`
...@@ -42,12 +87,12 @@ type UpdateAccountRequest struct { ...@@ -42,12 +87,12 @@ type UpdateAccountRequest struct {
// AccountService 账号管理服务 // AccountService 账号管理服务
type AccountService struct { type AccountService struct {
accountRepo ports.AccountRepository accountRepo AccountRepository
groupRepo ports.GroupRepository groupRepo GroupRepository
} }
// NewAccountService 创建账号服务实例 // NewAccountService 创建账号服务实例
func NewAccountService(accountRepo ports.AccountRepository, groupRepo ports.GroupRepository) *AccountService { func NewAccountService(accountRepo AccountRepository, groupRepo GroupRepository) *AccountService {
return &AccountService{ return &AccountService{
accountRepo: accountRepo, accountRepo: accountRepo,
groupRepo: groupRepo, groupRepo: groupRepo,
......
...@@ -17,8 +17,6 @@ import ( ...@@ -17,8 +17,6 @@ import (
"github.com/Wei-Shaw/sub2api/internal/model" "github.com/Wei-Shaw/sub2api/internal/model"
"github.com/Wei-Shaw/sub2api/internal/pkg/claude" "github.com/Wei-Shaw/sub2api/internal/pkg/claude"
"github.com/Wei-Shaw/sub2api/internal/pkg/openai" "github.com/Wei-Shaw/sub2api/internal/pkg/openai"
"github.com/Wei-Shaw/sub2api/internal/service/ports"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
) )
...@@ -40,14 +38,14 @@ type TestEvent struct { ...@@ -40,14 +38,14 @@ type TestEvent struct {
// AccountTestService handles account testing operations // AccountTestService handles account testing operations
type AccountTestService struct { type AccountTestService struct {
accountRepo ports.AccountRepository accountRepo AccountRepository
oauthService *OAuthService oauthService *OAuthService
openaiOAuthService *OpenAIOAuthService openaiOAuthService *OpenAIOAuthService
httpUpstream ports.HTTPUpstream httpUpstream HTTPUpstream
} }
// NewAccountTestService creates a new AccountTestService // NewAccountTestService creates a new AccountTestService
func NewAccountTestService(accountRepo ports.AccountRepository, oauthService *OAuthService, openaiOAuthService *OpenAIOAuthService, httpUpstream ports.HTTPUpstream) *AccountTestService { func NewAccountTestService(accountRepo AccountRepository, oauthService *OAuthService, openaiOAuthService *OpenAIOAuthService, httpUpstream HTTPUpstream) *AccountTestService {
return &AccountTestService{ return &AccountTestService{
accountRepo: accountRepo, accountRepo: accountRepo,
oauthService: oauthService, oauthService: oauthService,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment