mirror of
				https://github.com/oarkflow/mq.git
				synced 2025-11-01 02:32:35 +08:00 
			
		
		
		
	update: use oarkflow/json
				
					
				
			This commit is contained in:
		| @@ -45,7 +45,7 @@ func main() { | |||||||
| 		metrics := pool.Metrics() | 		metrics := pool.Metrics() | ||||||
| 		v1.Logger.Info().Msgf("Metrics: %+v", metrics) | 		v1.Logger.Info().Msgf("Metrics: %+v", metrics) | ||||||
| 		pool.Stop() | 		pool.Stop() | ||||||
| 		v1.Logger.Info().Msgf("Dead Letter Queue has %d tasks", len(pool.DLQ.Task())) | 		v1.Logger.Info().Msgf("Dead Letter Queue has %d tasks", len(pool.DLQ().Tasks())) | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
|   | |||||||
| @@ -13,10 +13,12 @@ func main() { | |||||||
| 		Payload: payload, | 		Payload: payload, | ||||||
| 	} | 	} | ||||||
| 	publisher := mq.NewPublisher("publish-1") | 	publisher := mq.NewPublisher("publish-1") | ||||||
| 	// publisher := mq.NewPublisher("publish-1", mq.WithTLS(true, "./certs/server.crt", "./certs/server.key")) | 	for i := 0; i < 10000000; i++ { | ||||||
| 	err := publisher.Publish(context.Background(), task, "queue") | 		// publisher := mq.NewPublisher("publish-1", mq.WithTLS(true, "./certs/server.crt", "./certs/server.key")) | ||||||
| 	if err != nil { | 		err := publisher.Publish(context.Background(), task, "queue1") | ||||||
| 		panic(err) | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	fmt.Println("Async task published successfully") | 	fmt.Println("Async task published successfully") | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								pool.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								pool.go
									
									
									
									
									
								
							| @@ -55,7 +55,7 @@ func NewDeadLetterQueue() *DeadLetterQueue { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dlq *DeadLetterQueue) Task() []*QueueTask { | func (dlq *DeadLetterQueue) Tasks() []*QueueTask { | ||||||
| 	return dlq.tasks | 	return dlq.tasks | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -138,7 +138,7 @@ type Pool struct { | |||||||
| 	completionCallback         CompletionCallback | 	completionCallback         CompletionCallback | ||||||
| 	taskAvailableCond          *sync.Cond | 	taskAvailableCond          *sync.Cond | ||||||
| 	callback                   Callback | 	callback                   Callback | ||||||
| 	DLQ                        *DeadLetterQueue | 	dlq                        *DeadLetterQueue | ||||||
| 	taskQueue                  PriorityQueue | 	taskQueue                  PriorityQueue | ||||||
| 	overflowBuffer             []*QueueTask | 	overflowBuffer             []*QueueTask | ||||||
| 	metrics                    Metrics | 	metrics                    Metrics | ||||||
| @@ -164,6 +164,7 @@ type Pool struct { | |||||||
| 	circuitBreakerFailureCount int32 | 	circuitBreakerFailureCount int32 | ||||||
| 	gracefulShutdownTimeout    time.Duration | 	gracefulShutdownTimeout    time.Duration | ||||||
| 	plugins                    []Plugin | 	plugins                    []Plugin | ||||||
|  | 	port                       int | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewPool(numOfWorkers int, opts ...PoolOption) *Pool { | func NewPool(numOfWorkers int, opts ...PoolOption) *Pool { | ||||||
| @@ -176,7 +177,8 @@ func NewPool(numOfWorkers int, opts ...PoolOption) *Pool { | |||||||
| 		backoffDuration:         Config.BackoffDuration, | 		backoffDuration:         Config.BackoffDuration, | ||||||
| 		maxRetries:              Config.MaxRetries, | 		maxRetries:              Config.MaxRetries, | ||||||
| 		logger:                  Logger, | 		logger:                  Logger, | ||||||
| 		DLQ:                     NewDeadLetterQueue(), | 		port:                    1234, | ||||||
|  | 		dlq:                     NewDeadLetterQueue(), | ||||||
| 		metricsRegistry:         NewInMemoryMetricsRegistry(), | 		metricsRegistry:         NewInMemoryMetricsRegistry(), | ||||||
| 		diagnosticsEnabled:      true, | 		diagnosticsEnabled:      true, | ||||||
| 		gracefulShutdownTimeout: 10 * time.Second, | 		gracefulShutdownTimeout: 10 * time.Second, | ||||||
| @@ -200,7 +202,7 @@ func NewPool(numOfWorkers int, opts ...PoolOption) *Pool { | |||||||
|  |  | ||||||
| func validateDynamicConfig(c *DynamicConfig) error { | func validateDynamicConfig(c *DynamicConfig) error { | ||||||
| 	if c.Timeout <= 0 { | 	if c.Timeout <= 0 { | ||||||
| 		return errors.New("Timeout must be positive") | 		return errors.New("timeout must be positive") | ||||||
| 	} | 	} | ||||||
| 	if c.BatchSize <= 0 { | 	if c.BatchSize <= 0 { | ||||||
| 		return errors.New("BatchSize must be > 0") | 		return errors.New("BatchSize must be > 0") | ||||||
| @@ -259,6 +261,10 @@ func (wp *Pool) Start(numWorkers int) { | |||||||
| 	go wp.monitorIdleWorkers() | 	go wp.monitorIdleWorkers() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (wp *Pool) DLQ() *DeadLetterQueue { | ||||||
|  | 	return wp.dlq | ||||||
|  | } | ||||||
|  |  | ||||||
| func (wp *Pool) worker() { | func (wp *Pool) worker() { | ||||||
| 	defer wp.wg.Done() | 	defer wp.wg.Done() | ||||||
| 	for { | 	for { | ||||||
| @@ -299,10 +305,6 @@ func (wp *Pool) processNextBatch() { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (wp *Pool) handleTask(task *QueueTask) { | func (wp *Pool) handleTask(task *QueueTask) { | ||||||
| 	if err := validateTaskInput(task.payload); err != nil { |  | ||||||
| 		wp.logger.Error().Str("taskID", task.payload.ID).Msgf("Validation failed: %v", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	ctx, cancel := context.WithTimeout(task.ctx, wp.timeout) | 	ctx, cancel := context.WithTimeout(task.ctx, wp.timeout) | ||||||
| 	defer cancel() | 	defer cancel() | ||||||
| 	taskSize := int64(utils.SizeOf(task.payload)) | 	taskSize := int64(utils.SizeOf(task.payload)) | ||||||
| @@ -312,9 +314,7 @@ func (wp *Pool) handleTask(task *QueueTask) { | |||||||
| 	result := wp.handler(ctx, task.payload) | 	result := wp.handler(ctx, task.payload) | ||||||
| 	executionTime := time.Since(startTime).Milliseconds() | 	executionTime := time.Since(startTime).Milliseconds() | ||||||
| 	atomic.AddInt64(&wp.metrics.ExecutionTime, executionTime) | 	atomic.AddInt64(&wp.metrics.ExecutionTime, executionTime) | ||||||
|  | 	if wp.thresholds.LongExecution > 0 && executionTime > wp.thresholds.LongExecution.Milliseconds() { | ||||||
| 	// Warning thresholds check |  | ||||||
| 	if wp.thresholds.LongExecution > 0 && executionTime > int64(wp.thresholds.LongExecution.Milliseconds()) { |  | ||||||
| 		wp.logger.Warn().Str("taskID", task.payload.ID).Msgf("Exceeded execution time threshold: %d ms", executionTime) | 		wp.logger.Warn().Str("taskID", task.payload.ID).Msgf("Exceeded execution time threshold: %d ms", executionTime) | ||||||
| 	} | 	} | ||||||
| 	if wp.thresholds.HighMemory > 0 && taskSize > wp.thresholds.HighMemory { | 	if wp.thresholds.HighMemory > 0 && taskSize > wp.thresholds.HighMemory { | ||||||
| @@ -325,8 +325,6 @@ func (wp *Pool) handleTask(task *QueueTask) { | |||||||
| 		atomic.AddInt64(&wp.metrics.ErrorCount, 1) | 		atomic.AddInt64(&wp.metrics.ErrorCount, 1) | ||||||
| 		wp.logger.Error().Str("taskID", task.payload.ID).Msgf("Error processing task: %v", result.Error) | 		wp.logger.Error().Str("taskID", task.payload.ID).Msgf("Error processing task: %v", result.Error) | ||||||
| 		wp.backoffAndStore(task) | 		wp.backoffAndStore(task) | ||||||
|  |  | ||||||
| 		// Circuit breaker check |  | ||||||
| 		if wp.circuitBreaker.Enabled { | 		if wp.circuitBreaker.Enabled { | ||||||
| 			newCount := atomic.AddInt32(&wp.circuitBreakerFailureCount, 1) | 			newCount := atomic.AddInt32(&wp.circuitBreakerFailureCount, 1) | ||||||
| 			if newCount >= int32(wp.circuitBreaker.FailureThreshold) { | 			if newCount >= int32(wp.circuitBreaker.FailureThreshold) { | ||||||
| @@ -375,7 +373,7 @@ func (wp *Pool) backoffAndStore(task *QueueTask) { | |||||||
| 		time.Sleep(sleepDuration) | 		time.Sleep(sleepDuration) | ||||||
| 	} else { | 	} else { | ||||||
| 		wp.logger.Error().Str("taskID", task.payload.ID).Msg("Task failed after maximum retries") | 		wp.logger.Error().Str("taskID", task.payload.ID).Msg("Task failed after maximum retries") | ||||||
| 		wp.DLQ.Add(task) | 		wp.dlq.Add(task) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -431,13 +429,9 @@ func (wp *Pool) adjustWorkers(newWorkerCount int) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (wp *Pool) EnqueueTask(ctx context.Context, payload *Task, priority int) error { | func (wp *Pool) EnqueueTask(ctx context.Context, payload *Task, priority int) error { | ||||||
| 	// Check circuit breaker state |  | ||||||
| 	if wp.circuitBreaker.Enabled && wp.circuitBreakerOpen { | 	if wp.circuitBreaker.Enabled && wp.circuitBreakerOpen { | ||||||
| 		return fmt.Errorf("circuit breaker open, task rejected") | 		return fmt.Errorf("circuit breaker open, task rejected") | ||||||
| 	} | 	} | ||||||
| 	if err := validateTaskInput(payload); err != nil { |  | ||||||
| 		return fmt.Errorf("invalid task input: %w", err) |  | ||||||
| 	} |  | ||||||
| 	if payload.ID == "" { | 	if payload.ID == "" { | ||||||
| 		payload.ID = NewID() | 		payload.ID = NewID() | ||||||
| 	} | 	} | ||||||
| @@ -572,7 +566,7 @@ func (wp *Pool) startHealthServer() { | |||||||
| 		if wp.gracefulShutdown { | 		if wp.gracefulShutdown { | ||||||
| 			status = "shutting down" | 			status = "shutting down" | ||||||
| 		} | 		} | ||||||
| 		fmt.Fprintf(w, "status: %s\nworkers: %d\nqueueLength: %d\n", | 		_, _ = fmt.Fprintf(w, "status: %s\nworkers: %d\nqueueLength: %d\n", | ||||||
| 			status, atomic.LoadInt32(&wp.numOfWorkers), len(wp.taskQueue)) | 			status, atomic.LoadInt32(&wp.numOfWorkers), len(wp.taskQueue)) | ||||||
| 	}) | 	}) | ||||||
| 	server := &http.Server{ | 	server := &http.Server{ | ||||||
|   | |||||||
| @@ -54,6 +54,12 @@ func WithBatchSize(batchSize int) PoolOption { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func WithHealthServicePort(port int) PoolOption { | ||||||
|  | 	return func(p *Pool) { | ||||||
|  | 		p.port = port | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func WithHandler(handler Handler) PoolOption { | func WithHandler(handler Handler) PoolOption { | ||||||
| 	return func(p *Pool) { | 	return func(p *Pool) { | ||||||
| 		p.handler = handler | 		p.handler = handler | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								scheduler.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								scheduler.go
									
									
									
									
									
								
							| @@ -2,7 +2,6 @@ package mq | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -448,21 +447,10 @@ func nextWeekday(t time.Time, weekday time.Weekday) time.Time { | |||||||
| 	} | 	} | ||||||
| 	return t.AddDate(0, 0, daysUntil) | 	return t.AddDate(0, 0, daysUntil) | ||||||
| } | } | ||||||
| func validateTaskInput(task *Task) error { |  | ||||||
| 	if task.Payload == nil { |  | ||||||
| 		return errors.New("task payload cannot be nil") |  | ||||||
| 	} |  | ||||||
| 	Logger.Info().Str("taskID", task.ID).Msg("Task validated") |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *Scheduler) AddTask(ctx context.Context, payload *Task, opts ...SchedulerOption) { | func (s *Scheduler) AddTask(ctx context.Context, payload *Task, opts ...SchedulerOption) { | ||||||
| 	s.mu.Lock() | 	s.mu.Lock() | ||||||
| 	defer s.mu.Unlock() | 	defer s.mu.Unlock() | ||||||
| 	if err := validateTaskInput(payload); err != nil { |  | ||||||
| 		Logger.Error().Err(err).Msg("Invalid task input") |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	options := defaultSchedulerOptions() | 	options := defaultSchedulerOptions() | ||||||
| 	for _, opt := range opts { | 	for _, opt := range opts { | ||||||
| 		opt(options) | 		opt(options) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Oarkflow
					Oarkflow