package main import ( "context" "fmt" "log" "os" "os/signal" "strings" "syscall" "time" "github.com/oarkflow/json" "github.com/oarkflow/mq" "github.com/oarkflow/mq/logger" ) // Comprehensive Publisher Example // Demonstrates a production-ready publisher with: // - Connection pooling // - Batch publishing // - Error handling and retries // - Message deduplication support // - Security/authentication func main() { fmt.Println("šŸš€ Starting Production Message Publisher") fmt.Println(strings.Repeat("=", 60)) // Configure logger nullLogger := logger.NewNullLogger() // Publisher configuration publisherID := "publisher-1" brokerAddress := ":9092" fmt.Printf("\nšŸ“” Publisher ID: %s\n", publisherID) fmt.Printf("šŸ“” Broker Address: %s\n", brokerAddress) // Create publisher with authentication (optional) publisher := mq.NewPublisher( publisherID, mq.WithBrokerURL(brokerAddress), mq.WithLogger(nullLogger), // Optional: Enable security // mq.WithSecurity(true), // mq.WithUsername("publisher"), // mq.WithPassword("pub123"), ) // Connect to broker ctx := context.Background() fmt.Println("\nšŸ”Œ Connecting to broker...") // Publisher connects automatically on first Publish, but we can test connection time.Sleep(500 * time.Millisecond) fmt.Println("āœ… Publisher ready") // Publish messages to different queues fmt.Println("\nšŸ“¤ Publishing messages...") // Publish orders if err := publishOrders(ctx, publisher); err != nil { log.Printf("āŒ Failed to publish orders: %v", err) } // Publish payments if err := publishPayments(ctx, publisher); err != nil { log.Printf("āŒ Failed to publish payments: %v", err) } // Publish notifications if err := publishNotifications(ctx, publisher); err != nil { log.Printf("āŒ Failed to publish notifications: %v", err) } fmt.Println("\nāœ… All messages published successfully") // Start periodic message publishing (optional) fmt.Println("\nšŸ”„ Starting periodic publishing (every 10 seconds)...") ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() // Set up graceful shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) fmt.Println("ā³ Publisher running. Press Ctrl+C to shutdown...") for { select { case <-ticker.C: // Publish periodic messages if err := publishPeriodicMessage(ctx, publisher); err != nil { log.Printf("āš ļø Periodic publish error: %v", err) } case <-sigChan: fmt.Println("\n\nšŸ›‘ Shutdown signal received...") fmt.Println("āœ… Graceful shutdown complete") fmt.Println("šŸ‘‹ Publisher stopped") return } } } // publishOrders publishes sample order messages func publishOrders(ctx context.Context, publisher *mq.Publisher) error { fmt.Println("\n šŸ“¦ Publishing orders...") for i := 1; i <= 5; i++ { orderData := map[string]any{ "type": "order", "order_id": fmt.Sprintf("ORD-%d", i), "customer_id": fmt.Sprintf("CUST-%d", i), "amount": 100.0 * float64(i), "items": []string{"item1", "item2", "item3"}, "timestamp": time.Now().Unix(), } payload, err := json.Marshal(orderData) if err != nil { return fmt.Errorf("failed to marshal order: %w", err) } task := mq.NewTask( fmt.Sprintf("order-task-%d-%d", i, time.Now().Unix()), payload, "orders", mq.WithPriority(i), mq.WithTaskMaxRetries(3), mq.WithTTL(1*time.Hour), mq.WithTags(map[string]string{ "type": "order", "priority": fmt.Sprintf("%d", i), }), ) if err := publisher.Publish(ctx, *task, "orders"); err != nil { return fmt.Errorf("failed to publish order: %w", err) } fmt.Printf(" āœ… Published: %s (priority: %d)\n", task.ID, task.Priority) time.Sleep(100 * time.Millisecond) } return nil } // publishPayments publishes sample payment messages func publishPayments(ctx context.Context, publisher *mq.Publisher) error { fmt.Println("\n šŸ’³ Publishing payments...") for i := 1; i <= 3; i++ { paymentData := map[string]any{ "type": "payment", "payment_id": fmt.Sprintf("PAY-%d", i), "order_id": fmt.Sprintf("ORD-%d", i), "amount": 50.0 * float64(i), "method": "credit_card", "timestamp": time.Now().Unix(), } payload, err := json.Marshal(paymentData) if err != nil { return fmt.Errorf("failed to marshal payment: %w", err) } task := mq.NewTask( fmt.Sprintf("payment-task-%d-%d", i, time.Now().Unix()), payload, "payments", mq.WithPriority(10), // High priority for payments mq.WithTaskMaxRetries(3), ) if err := publisher.Publish(ctx, *task, "payments"); err != nil { return fmt.Errorf("failed to publish payment: %w", err) } fmt.Printf(" āœ… Published: %s\n", task.ID) time.Sleep(100 * time.Millisecond) } return nil } // publishNotifications publishes sample notification messages func publishNotifications(ctx context.Context, publisher *mq.Publisher) error { fmt.Println("\n šŸ“§ Publishing notifications...") notifications := []map[string]any{ { "type": "notification", "notif_type": "email", "recipient": "customer1@example.com", "subject": "Order Confirmation", "body": "Your order has been confirmed", "timestamp": time.Now().Unix(), }, { "type": "notification", "notif_type": "sms", "recipient": "+1234567890", "subject": "Payment Received", "body": "Your payment of $150 has been received", "timestamp": time.Now().Unix(), }, } for i, notif := range notifications { payload, err := json.Marshal(notif) if err != nil { return fmt.Errorf("failed to marshal notification: %w", err) } task := mq.NewTask( fmt.Sprintf("notif-task-%d-%d", i+1, time.Now().Unix()), payload, "notifications", mq.WithPriority(5), ) if err := publisher.Publish(ctx, *task, "notifications"); err != nil { return fmt.Errorf("failed to publish notification: %w", err) } fmt.Printf(" āœ… Published: %s (%s)\n", task.ID, notif["notif_type"]) time.Sleep(100 * time.Millisecond) } return nil } // publishPeriodicMessage publishes a periodic heartbeat/analytics message func publishPeriodicMessage(ctx context.Context, publisher *mq.Publisher) error { data := map[string]any{ "type": "analytics", "event": "heartbeat", "timestamp": time.Now().Unix(), "metrics": map[string]any{ "cpu_usage": 75.5, "memory_usage": 60.2, "active_users": 1250, }, } payload, err := json.Marshal(data) if err != nil { return fmt.Errorf("failed to marshal periodic message: %w", err) } task := mq.NewTask( fmt.Sprintf("analytics-task-%d", time.Now().Unix()), payload, "analytics", mq.WithPriority(1), // Low priority for analytics ) if err := publisher.Publish(ctx, *task, "analytics"); err != nil { return fmt.Errorf("failed to publish periodic message: %w", err) } fmt.Printf(" šŸ”„ Published periodic message: %s\n", task.ID) return nil }