95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
|
|
package job
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"log"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
jobdom "haixun-backend/internal/model/job/domain/usecase"
|
||
|
|
threadsaccountdomain "haixun-backend/internal/model/threads_account/domain/usecase"
|
||
|
|
)
|
||
|
|
|
||
|
|
const refreshThreadsTokenTemplateType = "refresh-threads-token"
|
||
|
|
|
||
|
|
type ThreadsTokenSweeper struct {
|
||
|
|
accounts threadsaccountdomain.UseCase
|
||
|
|
jobs jobdom.UseCase
|
||
|
|
leadTime time.Duration
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewThreadsTokenSweeper(
|
||
|
|
accounts threadsaccountdomain.UseCase,
|
||
|
|
jobs jobdom.UseCase,
|
||
|
|
leadTime time.Duration,
|
||
|
|
) *ThreadsTokenSweeper {
|
||
|
|
if leadTime <= 0 {
|
||
|
|
leadTime = 7 * 24 * time.Hour
|
||
|
|
}
|
||
|
|
return &ThreadsTokenSweeper{
|
||
|
|
accounts: accounts,
|
||
|
|
jobs: jobs,
|
||
|
|
leadTime: leadTime,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *ThreadsTokenSweeper) Start(ctx context.Context, interval time.Duration) {
|
||
|
|
if s == nil || s.accounts == nil || s.jobs == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if interval <= 0 {
|
||
|
|
interval = time.Hour
|
||
|
|
}
|
||
|
|
log.Printf("threads token sweeper started: interval=%s lead_time=%s", interval, s.leadTime)
|
||
|
|
ticker := time.NewTicker(interval)
|
||
|
|
defer ticker.Stop()
|
||
|
|
|
||
|
|
for {
|
||
|
|
select {
|
||
|
|
case <-ctx.Done():
|
||
|
|
log.Printf("threads token sweeper stopped")
|
||
|
|
return
|
||
|
|
case <-ticker.C:
|
||
|
|
created, err := s.tick(ctx)
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("threads token sweeper tick error: %v", err)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if created > 0 {
|
||
|
|
log.Printf("threads token sweeper enqueued %d refresh job(s)", created)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *ThreadsTokenSweeper) tick(ctx context.Context) (int, error) {
|
||
|
|
candidates, err := s.accounts.ListTokenRefreshCandidates(ctx, s.leadTime)
|
||
|
|
if err != nil {
|
||
|
|
return 0, err
|
||
|
|
}
|
||
|
|
created := 0
|
||
|
|
for _, item := range candidates {
|
||
|
|
if item.AccountID == "" || item.TenantID == "" || item.OwnerUID == "" {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
_, err := s.jobs.CreateRun(ctx, jobdom.CreateRunRequest{
|
||
|
|
TemplateType: refreshThreadsTokenTemplateType,
|
||
|
|
Scope: "threads_account",
|
||
|
|
ScopeID: item.AccountID,
|
||
|
|
TenantID: item.TenantID,
|
||
|
|
OwnerUID: item.OwnerUID,
|
||
|
|
Payload: map[string]any{
|
||
|
|
"tenant_id": item.TenantID,
|
||
|
|
"owner_uid": item.OwnerUID,
|
||
|
|
"account_id": item.AccountID,
|
||
|
|
"expires_at": item.ExpiresAt,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("threads token sweeper skip account=%s: %v", item.AccountID, err)
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
created++
|
||
|
|
}
|
||
|
|
return created, nil
|
||
|
|
}
|