github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/engine/function/kafkaproducer.go (about)

     1  package funcs
     2  
     3  import (
     4  	//	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"time"
     8  
     9  	"os"
    10  	"os/signal"
    11  
    12  	"github.com/IBM/sarama"
    13  )
    14  
    15  type SendMessagebyKafka struct {
    16  }
    17  
    18  func (cf *SendMessagebyKafka) Execute(f *Funcs) {
    19  	startTime := time.Now()
    20  	defer func() {
    21  		elapsed := time.Since(startTime)
    22  		f.iLog.PerformanceWithDuration("engine.funcs.SendMessagebyKafka.Execute", elapsed)
    23  	}()
    24  	defer func() {
    25  		if err := recover(); err != nil {
    26  			f.iLog.Error(fmt.Sprintf("There is error to engine.funcs.SendMessagebyKafka.Execute with error: %s", err))
    27  			f.CancelExecution(fmt.Sprintf("There is error to engine.funcs.SendMessagebyKafka.Execute with error: %s", err))
    28  			f.ErrorMessage = fmt.Sprintf("There is error to engine.funcs.SendMessagebyKafka.Execute with error: %s", err)
    29  			return
    30  		}
    31  	}()
    32  
    33  	f.iLog.Debug(fmt.Sprintf("SendMessagebyKafka Execute: %v", f))
    34  
    35  	namelist, valuelist, _ := f.SetInputs()
    36  	f.iLog.Debug(fmt.Sprintf("SendMessagebyKafka Execute: %v, %v", namelist, valuelist))
    37  	kafkaServer := ""
    38  	Topic := ""
    39  	data := make(map[string]interface{})
    40  	for i, name := range namelist {
    41  		if name == "Topic" {
    42  			Topic = valuelist[i]
    43  
    44  			continue
    45  		} else if name == "Server" {
    46  			kafkaServer = valuelist[i]
    47  		}
    48  		data[name] = valuelist[i]
    49  	}
    50  
    51  	if Topic == "" {
    52  		f.iLog.Error(fmt.Sprintf("SendMessagebyKafka validate wrong: %v", "Topic is empty"))
    53  		return
    54  	}
    55  
    56  	if kafkaServer == "" {
    57  		f.iLog.Error(fmt.Sprintf("SendMessagebyKafka validate wrong: %v", "kafkaServer is empty"))
    58  		return
    59  	}
    60  
    61  	config := sarama.NewConfig()
    62  	config.Producer.Return.Successes = true
    63  
    64  	producer, err := sarama.NewAsyncProducer([]string{kafkaServer}, config)
    65  	if err != nil {
    66  		f.iLog.Error(fmt.Sprintf("Error creating producer: %v", err))
    67  		f.ErrorMessage = fmt.Sprintf("Error creating producer: %v", err)
    68  		return
    69  	}
    70  	defer producer.Close()
    71  
    72  	signals := make(chan os.Signal, 1)
    73  	signal.Notify(signals, os.Interrupt)
    74  
    75  	// Produce messages to topic (asynchronously)
    76  
    77  	jsonData, err := json.Marshal(data)
    78  	if err != nil {
    79  		f.iLog.Error(fmt.Sprintf("Error:%v", err))
    80  		return
    81  	}
    82  	// Convert JSON byte array to string
    83  	jsonString := string(jsonData)
    84  
    85  	f.iLog.Debug(fmt.Sprintf("SendMessagebyKafka Execute: topic, %s, message: %v", Topic, jsonString))
    86  
    87  ProducerLoop:
    88  	for {
    89  		select {
    90  		case <-signals:
    91  			break ProducerLoop
    92  		case err := <-producer.Errors():
    93  			f.iLog.Error(fmt.Sprintf("Failed to produce message: %v", err))
    94  		case success := <-producer.Successes():
    95  			f.iLog.Info(fmt.Sprintf("Produced message to topic %s partition %d offset %d",
    96  				success.Topic, success.Partition, success.Offset))
    97  		}
    98  
    99  		message := &sarama.ProducerMessage{
   100  			Topic: Topic,
   101  			Value: sarama.StringEncoder(jsonString),
   102  		}
   103  
   104  		producer.Input() <- message
   105  	}
   106  
   107  	outputs := make(map[string][]interface{})
   108  	f.SetOutputs(f.convertMap(outputs))
   109  }
   110  
   111  // Validate validates the SendMessagebyKafka function.
   112  // It checks if the namelist and valuelist are empty,
   113  // and if the "Topic" name is present in the namelist.
   114  // Returns true if the validation passes, otherwise returns false with an error.
   115  // It also logs the performance of the function.
   116  func (cf *SendMessagebyKafka) Validate(f *Funcs) (bool, error) {
   117  	startTime := time.Now()
   118  	defer func() {
   119  		elapsed := time.Since(startTime)
   120  		f.iLog.PerformanceWithDuration("engine.funcs.SendMessagebyKafka.Validate", elapsed)
   121  	}()
   122  	/*	defer func() {
   123  			if err := recover(); err != nil {
   124  				f.iLog.Error(fmt.Sprintf("There is error to engine.funcs.SendMessagebyKafka.Validate with error: %s", err))
   125  				f.ErrorMessage = fmt.Sprintf("There is error to engine.funcs.SendMessagebyKafka.Validate with error: %s", err)
   126  				return
   127  			}
   128  		}()
   129  	*/
   130  	f.iLog.Debug(fmt.Sprintf("SendMessagebyKafka validate: %v", f))
   131  	namelist, valuelist, _ := f.SetInputs()
   132  
   133  	if len(namelist) == 0 {
   134  		return false, fmt.Errorf("SendMessagebyKafka validate: %v", "namelist is empty")
   135  	}
   136  
   137  	if len(valuelist) == 0 {
   138  		return false, fmt.Errorf("SendMessagebyKafka validate: %v", "valuelist is empty")
   139  	}
   140  	found := false
   141  	for _, name := range namelist {
   142  		if name == "" {
   143  			return false, fmt.Errorf("SendMessagebyKafka validate: %v", "name is empty")
   144  		}
   145  
   146  		if name == "Topic" {
   147  			found = true
   148  		}
   149  	}
   150  	if !found {
   151  		return false, fmt.Errorf("SendMessagebyKafka validate: %v", "Topic is not found")
   152  	}
   153  
   154  	return true, nil
   155  }