335 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			335 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package entities | |||
|  | 
 | |||
|  | import ( | |||
|  | 	"context" | |||
|  | 	"encoding/json" | |||
|  | 	"fmt" | |||
|  | 	"time" | |||
|  | 
 | |||
|  | 	"tyapi-server/internal/infrastructure/task/types" | |||
|  | ) | |||
|  | 
 | |||
|  | // TaskFactory 任务工厂 | |||
|  | type TaskFactory struct { | |||
|  | 	taskManager interface{} // 使用interface{}避免循环导入 | |||
|  | } | |||
|  | 
 | |||
|  | // NewTaskFactory 创建任务工厂 | |||
|  | func NewTaskFactory() *TaskFactory { | |||
|  | 	return &TaskFactory{} | |||
|  | } | |||
|  | 
 | |||
|  | // NewTaskFactoryWithManager 创建带管理器的任务工厂 | |||
|  | func NewTaskFactoryWithManager(taskManager interface{}) *TaskFactory { | |||
|  | 	return &TaskFactory{ | |||
|  | 		taskManager: taskManager, | |||
|  | 	} | |||
|  | } | |||
|  | 
 | |||
|  | // CreateArticlePublishTask 创建文章发布任务 | |||
|  | func (f *TaskFactory) CreateArticlePublishTask(articleID string, publishAt time.Time, userID string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:        string(types.TaskTypeArticlePublish), | |||
|  | 		Status:      TaskStatusPending, | |||
|  | 		ScheduledAt: &publishAt, | |||
|  | 		CreatedAt:   time.Now(), | |||
|  | 		UpdatedAt:   time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务ID(将在保存后更新) | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"article_id": articleID, | |||
|  | 		"publish_at": publishAt, | |||
|  | 		"user_id":    userID, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateArticleCancelTask 创建文章取消任务 | |||
|  | func (f *TaskFactory) CreateArticleCancelTask(articleID string, userID string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:      string(types.TaskTypeArticleCancel), | |||
|  | 		Status:    TaskStatusPending, | |||
|  | 		CreatedAt: time.Now(), | |||
|  | 		UpdatedAt: time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"article_id": articleID, | |||
|  | 		"user_id":    userID, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateArticleModifyTask 创建文章修改任务 | |||
|  | func (f *TaskFactory) CreateArticleModifyTask(articleID string, newPublishAt time.Time, userID string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:        string(types.TaskTypeArticleModify), | |||
|  | 		Status:      TaskStatusPending, | |||
|  | 		ScheduledAt: &newPublishAt, | |||
|  | 		CreatedAt:   time.Now(), | |||
|  | 		UpdatedAt:   time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"article_id":      articleID, | |||
|  | 		"new_publish_at":  newPublishAt, | |||
|  | 		"user_id":         userID, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateApiCallTask 创建API调用任务 | |||
|  | func (f *TaskFactory) CreateApiCallTask(apiCallID string, userID string, productID string, amount string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:      string(types.TaskTypeApiCall), | |||
|  | 		Status:    TaskStatusPending, | |||
|  | 		CreatedAt: time.Now(), | |||
|  | 		UpdatedAt: time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"api_call_id": apiCallID, | |||
|  | 		"user_id":     userID, | |||
|  | 		"product_id":  productID, | |||
|  | 		"amount":      amount, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateDeductionTask 创建扣款任务 | |||
|  | func (f *TaskFactory) CreateDeductionTask(apiCallID string, userID string, productID string, amount string, transactionID string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:      string(types.TaskTypeDeduction), | |||
|  | 		Status:    TaskStatusPending, | |||
|  | 		CreatedAt: time.Now(), | |||
|  | 		UpdatedAt: time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"api_call_id":    apiCallID, | |||
|  | 		"user_id":        userID, | |||
|  | 		"product_id":     productID, | |||
|  | 		"amount":         amount, | |||
|  | 		"transaction_id": transactionID, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateApiCallLogTask 创建API调用日志任务 | |||
|  | func (f *TaskFactory) CreateApiCallLogTask(transactionID string, userID string, apiName string, productID string) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:      string(types.TaskTypeApiLog), | |||
|  | 		Status:    TaskStatusPending, | |||
|  | 		CreatedAt: time.Now(), | |||
|  | 		UpdatedAt: time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"transaction_id": transactionID, | |||
|  | 		"user_id":        userID, | |||
|  | 		"api_name":       apiName, | |||
|  | 		"product_id":     productID, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateUsageStatsTask 创建使用统计任务 | |||
|  | func (f *TaskFactory) CreateUsageStatsTask(subscriptionID string, userID string, productID string, increment int) (*AsyncTask, error) { | |||
|  | 	// 创建任务实体,ID将由GORM的BeforeCreate钩子自动生成UUID | |||
|  | 	task := &AsyncTask{ | |||
|  | 		Type:      string(types.TaskTypeUsageStats), | |||
|  | 		Status:    TaskStatusPending, | |||
|  | 		CreatedAt: time.Now(), | |||
|  | 		UpdatedAt: time.Now(), | |||
|  | 	} | |||
|  | 	 | |||
|  | 	// 在payload中添加任务数据 | |||
|  | 	payloadWithID := map[string]interface{}{ | |||
|  | 		"subscription_id": subscriptionID, | |||
|  | 		"user_id":         userID, | |||
|  | 		"product_id":      productID, | |||
|  | 		"increment":       increment, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	payloadDataWithID, err := json.Marshal(payloadWithID) | |||
|  | 	if err != nil { | |||
|  | 		return nil, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task.Payload = string(payloadDataWithID) | |||
|  | 	return task, nil | |||
|  | } | |||
|  | 
 | |||
|  | // CreateAndEnqueueArticlePublishTask 创建并入队文章发布任务 | |||
|  | func (f *TaskFactory) CreateAndEnqueueArticlePublishTask(ctx context.Context, articleID string, publishAt time.Time, userID string) error { | |||
|  | 	if f.taskManager == nil { | |||
|  | 		return fmt.Errorf("TaskManager未初始化") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task, err := f.CreateArticlePublishTask(articleID, publishAt, userID) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	delay := publishAt.Sub(time.Now()) | |||
|  | 	if delay < 0 { | |||
|  | 		delay = 0 | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用类型断言调用TaskManager方法 | |||
|  | 	if tm, ok := f.taskManager.(interface { | |||
|  | 		CreateAndEnqueueDelayedTask(ctx context.Context, task *AsyncTask, delay time.Duration) error | |||
|  | 	}); ok { | |||
|  | 		return tm.CreateAndEnqueueDelayedTask(ctx, task, delay) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return fmt.Errorf("TaskManager类型不匹配") | |||
|  | } | |||
|  | 
 | |||
|  | // CreateAndEnqueueApiLogTask 创建并入队API日志任务 | |||
|  | func (f *TaskFactory) CreateAndEnqueueApiLogTask(ctx context.Context, transactionID string, userID string, apiName string, productID string) error { | |||
|  | 	if f.taskManager == nil { | |||
|  | 		return fmt.Errorf("TaskManager未初始化") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task, err := f.CreateApiCallLogTask(transactionID, userID, apiName, productID) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用类型断言调用TaskManager方法 | |||
|  | 	if tm, ok := f.taskManager.(interface { | |||
|  | 		CreateAndEnqueueTask(ctx context.Context, task *AsyncTask) error | |||
|  | 	}); ok { | |||
|  | 		return tm.CreateAndEnqueueTask(ctx, task) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return fmt.Errorf("TaskManager类型不匹配") | |||
|  | } | |||
|  | 
 | |||
|  | // CreateAndEnqueueApiCallTask 创建并入队API调用任务 | |||
|  | func (f *TaskFactory) CreateAndEnqueueApiCallTask(ctx context.Context, apiCallID string, userID string, productID string, amount string) error { | |||
|  | 	if f.taskManager == nil { | |||
|  | 		return fmt.Errorf("TaskManager未初始化") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task, err := f.CreateApiCallTask(apiCallID, userID, productID, amount) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用类型断言调用TaskManager方法 | |||
|  | 	if tm, ok := f.taskManager.(interface { | |||
|  | 		CreateAndEnqueueTask(ctx context.Context, task *AsyncTask) error | |||
|  | 	}); ok { | |||
|  | 		return tm.CreateAndEnqueueTask(ctx, task) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return fmt.Errorf("TaskManager类型不匹配") | |||
|  | } | |||
|  | 
 | |||
|  | // CreateAndEnqueueDeductionTask 创建并入队扣款任务 | |||
|  | func (f *TaskFactory) CreateAndEnqueueDeductionTask(ctx context.Context, apiCallID string, userID string, productID string, amount string, transactionID string) error { | |||
|  | 	if f.taskManager == nil { | |||
|  | 		return fmt.Errorf("TaskManager未初始化") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task, err := f.CreateDeductionTask(apiCallID, userID, productID, amount, transactionID) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用类型断言调用TaskManager方法 | |||
|  | 	if tm, ok := f.taskManager.(interface { | |||
|  | 		CreateAndEnqueueTask(ctx context.Context, task *AsyncTask) error | |||
|  | 	}); ok { | |||
|  | 		return tm.CreateAndEnqueueTask(ctx, task) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return fmt.Errorf("TaskManager类型不匹配") | |||
|  | } | |||
|  | 
 | |||
|  | // CreateAndEnqueueUsageStatsTask 创建并入队使用统计任务 | |||
|  | func (f *TaskFactory) CreateAndEnqueueUsageStatsTask(ctx context.Context, subscriptionID string, userID string, productID string, increment int) error { | |||
|  | 	if f.taskManager == nil { | |||
|  | 		return fmt.Errorf("TaskManager未初始化") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	task, err := f.CreateUsageStatsTask(subscriptionID, userID, productID, increment) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用类型断言调用TaskManager方法 | |||
|  | 	if tm, ok := f.taskManager.(interface { | |||
|  | 		CreateAndEnqueueTask(ctx context.Context, task *AsyncTask) error | |||
|  | 	}); ok { | |||
|  | 		return tm.CreateAndEnqueueTask(ctx, task) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return fmt.Errorf("TaskManager类型不匹配") | |||
|  | } | |||
|  | 
 | |||
|  | // generateRandomString 生成随机字符串 | |||
|  | func generateRandomString(length int) string { | |||
|  | 	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | |||
|  | 	b := make([]byte, length) | |||
|  | 	for i := range b { | |||
|  | 		b[i] = charset[time.Now().UnixNano()%int64(len(charset))] | |||
|  | 	} | |||
|  | 	return string(b) | |||
|  | } |