feat: Implement CodexAuth proxy pool management with a new frontend configuration page and a dedicated backend service for API, database, and proxy testing.

This commit is contained in:
2026-02-03 03:00:25 +08:00
parent 51ba54856d
commit b014226074
6 changed files with 283 additions and 28 deletions

View File

@@ -54,10 +54,14 @@ func Init(dbPath string) error {
// migrate 数据库迁移
func (d *DB) migrate() error {
// 添加 last_checked_at 列(如果不存在)
_, err := d.db.Exec(`ALTER TABLE team_owners ADD COLUMN last_checked_at DATETIME`)
if err != nil && !isColumnExistsError(err) {
return err
}
_, _ = d.db.Exec(`ALTER TABLE team_owners ADD COLUMN last_checked_at DATETIME`)
// 添加 last_test_at 列 (如果不存在)
_, _ = d.db.Exec(`ALTER TABLE codex_auth_proxies ADD COLUMN last_test_at DATETIME`)
// 添加 location 列 (如果不存在)
_, _ = d.db.Exec(`ALTER TABLE codex_auth_proxies ADD COLUMN location TEXT`)
return nil
}
@@ -135,6 +139,8 @@ func (d *DB) createTables() error {
last_used_at DATETIME,
success_count INTEGER DEFAULT 0,
fail_count INTEGER DEFAULT 0,
location TEXT,
last_test_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
@@ -272,7 +278,7 @@ func (d *DB) GetTeamOwners(status string, limit, offset int) ([]TeamOwner, int,
return owners, total, nil
}
// GetPendingOwners 获取待处理(排除已使用处理中的)
// GetPendingOwners 获取待处理(排除已使用 and 处理中的)
func (d *DB) GetPendingOwners() ([]TeamOwner, error) {
rows, err := d.db.Query(`
SELECT id, email, password, token, account_id, status, created_at, last_checked_at
@@ -760,6 +766,8 @@ type CodexProxy struct {
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
SuccessCount int `json:"success_count"`
FailCount int `json:"fail_count"`
Location string `json:"location"`
LastTestAt *time.Time `json:"last_test_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
@@ -813,7 +821,7 @@ func (d *DB) AddCodexProxies(proxies []string) (int, error) {
// GetCodexProxies 获取代理列表
func (d *DB) GetCodexProxies() ([]CodexProxy, error) {
rows, err := d.db.Query(`
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, created_at
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, COALESCE(location, ''), last_test_at, created_at
FROM codex_auth_proxies
ORDER BY created_at DESC
`)
@@ -825,14 +833,17 @@ func (d *DB) GetCodexProxies() ([]CodexProxy, error) {
var proxies []CodexProxy
for rows.Next() {
var p CodexProxy
var lastUsedAt sql.NullTime
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.CreatedAt)
var lastUsedAt, lastTestAt sql.NullTime
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.Location, &lastTestAt, &p.CreatedAt)
if err != nil {
continue
}
if lastUsedAt.Valid {
p.LastUsedAt = &lastUsedAt.Time
}
if lastTestAt.Valid {
p.LastTestAt = &lastTestAt.Time
}
proxies = append(proxies, p)
}
return proxies, nil
@@ -841,7 +852,7 @@ func (d *DB) GetCodexProxies() ([]CodexProxy, error) {
// GetEnabledCodexProxies 获取已启用的代理列表
func (d *DB) GetEnabledCodexProxies() ([]CodexProxy, error) {
rows, err := d.db.Query(`
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, created_at
SELECT id, proxy_url, COALESCE(description, ''), is_enabled, last_used_at, success_count, fail_count, COALESCE(location, ''), last_test_at, created_at
FROM codex_auth_proxies
WHERE is_enabled = 1
ORDER BY success_count DESC, fail_count ASC
@@ -854,14 +865,17 @@ func (d *DB) GetEnabledCodexProxies() ([]CodexProxy, error) {
var proxies []CodexProxy
for rows.Next() {
var p CodexProxy
var lastUsedAt sql.NullTime
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.CreatedAt)
var lastUsedAt, lastTestAt sql.NullTime
err := rows.Scan(&p.ID, &p.ProxyURL, &p.Description, &p.IsEnabled, &lastUsedAt, &p.SuccessCount, &p.FailCount, &p.Location, &lastTestAt, &p.CreatedAt)
if err != nil {
continue
}
if lastUsedAt.Valid {
p.LastUsedAt = &lastUsedAt.Time
}
if lastTestAt.Valid {
p.LastTestAt = &lastTestAt.Time
}
proxies = append(proxies, p)
}
return proxies, nil
@@ -897,6 +911,24 @@ func (d *DB) UpdateCodexProxyStats(proxyURL string, success bool) error {
return err
}
// UpdateCodexProxyTestResult 更新代理测试结果
func (d *DB) UpdateCodexProxyTestResult(id int64, location string, success bool) error {
if success {
_, err := d.db.Exec(`
UPDATE codex_auth_proxies
SET location = ?, last_test_at = CURRENT_TIMESTAMP, success_count = success_count + 1
WHERE id = ?
`, location, id)
return err
}
_, err := d.db.Exec(`
UPDATE codex_auth_proxies
SET last_test_at = CURRENT_TIMESTAMP, fail_count = fail_count + 1
WHERE id = ?
`, id)
return err
}
// ToggleCodexProxy 切换代理启用状态
func (d *DB) ToggleCodexProxy(id int64) error {
_, err := d.db.Exec("UPDATE codex_auth_proxies SET is_enabled = 1 - is_enabled WHERE id = ?", id)