Add a publisher in broker service and make everything work
This commit is contained in:
		
							
								
								
									
										53
									
								
								broker-service/cmd/api/event/emitter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								broker-service/cmd/api/event/emitter.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					package event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amqp "github.com/rabbitmq/amqp091-go"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Emitter struct {
 | 
				
			||||||
 | 
						conn *amqp.Connection
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewEmitter(conn *amqp.Connection) (Emitter, error) {
 | 
				
			||||||
 | 
						emitter := Emitter{
 | 
				
			||||||
 | 
							conn: conn,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := emitter.setup()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return Emitter{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return emitter, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (emitter *Emitter) setup() error {
 | 
				
			||||||
 | 
						channel, err := emitter.conn.Channel()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer channel.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return declaireExchange(channel)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (emitter *Emitter) Push(event string, severity string) error {
 | 
				
			||||||
 | 
						ch, err := emitter.conn.Channel()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer ch.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Println("Pushing to channel")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = ch.Publish("logs_topic", severity, false, false, amqp.Publishing{
 | 
				
			||||||
 | 
							ContentType: "text/plain",
 | 
				
			||||||
 | 
							Body:        []byte(event),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								broker-service/cmd/api/event/event.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								broker-service/cmd/api/event/event.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						amqp "github.com/rabbitmq/amqp091-go"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func declaireExchange(ch *amqp.Channel) error {
 | 
				
			||||||
 | 
						return ch.ExchangeDeclare(
 | 
				
			||||||
 | 
							"logs_topic", // name
 | 
				
			||||||
 | 
							"topic",      // type
 | 
				
			||||||
 | 
							true,         // durable?
 | 
				
			||||||
 | 
							false,        // auto-deleted?
 | 
				
			||||||
 | 
							false,        // internal?
 | 
				
			||||||
 | 
							false,        // no-wait?
 | 
				
			||||||
 | 
							nil,          // arguments?
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func declaireRandomQueue(ch *amqp.Channel) (amqp.Queue, error) {
 | 
				
			||||||
 | 
						return ch.QueueDeclare(
 | 
				
			||||||
 | 
							"",    // name
 | 
				
			||||||
 | 
							false, // durable
 | 
				
			||||||
 | 
							false, // delete when unused
 | 
				
			||||||
 | 
							true,  // exclusive
 | 
				
			||||||
 | 
							false, // nowait
 | 
				
			||||||
 | 
							nil,   // table
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"broker/cmd/api/event"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
@ -54,7 +55,8 @@ func (app *Config) HandleSubmission(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	case "auth":
 | 
						case "auth":
 | 
				
			||||||
		app.authenticate(w, requestPayload.Auth)
 | 
							app.authenticate(w, requestPayload.Auth)
 | 
				
			||||||
	case "log":
 | 
						case "log":
 | 
				
			||||||
		app.LogItem(w, requestPayload.Log)
 | 
							// app.LogItem(w, requestPayload.Log)
 | 
				
			||||||
 | 
							app.logEventViaRabbit(w, requestPayload.Log)
 | 
				
			||||||
	case "mail":
 | 
						case "mail":
 | 
				
			||||||
		app.SendMail(w, requestPayload.Mail)
 | 
							app.SendMail(w, requestPayload.Mail)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
@ -176,3 +178,37 @@ func (app *Config) callService(w http.ResponseWriter, ms Microservice) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	app.writeJSON(w, http.StatusOK, payload)
 | 
						app.writeJSON(w, http.StatusOK, payload)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *Config) logEventViaRabbit(w http.ResponseWriter, l LogPayload) {
 | 
				
			||||||
 | 
						err := app.pushToQueue(l.Name, l.Data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							app.errorJSON(w, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var payload jsonResponse
 | 
				
			||||||
 | 
						payload.Error = false
 | 
				
			||||||
 | 
						payload.Message = "logged via RabbitMQ"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						app.writeJSON(w, http.StatusOK, payload)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *Config) pushToQueue(name, msg string) error {
 | 
				
			||||||
 | 
						emitter, err := event.NewEmitter(app.Rabbit)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						payload := LogPayload{
 | 
				
			||||||
 | 
							Name: name,
 | 
				
			||||||
 | 
							Data: msg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						j, _ := json.MarshalIndent(&payload, "", "\t")
 | 
				
			||||||
 | 
						err = emitter.Push(string(j), "log.INFO")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,15 +3,32 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amqp "github.com/rabbitmq/amqp091-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const webPort = "80"
 | 
					const webPort = "80"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Config struct{}
 | 
					type Config struct {
 | 
				
			||||||
 | 
						Rabbit *amqp.Connection
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	app := Config{}
 | 
						// try to connect to rabbitmq
 | 
				
			||||||
 | 
						rabbitConn, err := connect()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
							os.Exit(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer rabbitConn.Close()
 | 
				
			||||||
 | 
						log.Println("Connected to RabbitMQ")
 | 
				
			||||||
 | 
						app := Config{
 | 
				
			||||||
 | 
							Rabbit: rabbitConn,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Printf("Starting broker service on port %s\n", webPort)
 | 
						log.Printf("Starting broker service on port %s\n", webPort)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,8 +38,36 @@ func main() {
 | 
				
			|||||||
		Handler: app.routes(),
 | 
							Handler: app.routes(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := srv.ListenAndServe()
 | 
						err = srv.ListenAndServe()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Panic(err)
 | 
							log.Panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func connect() (*amqp.Connection, error) {
 | 
				
			||||||
 | 
						var counts int64
 | 
				
			||||||
 | 
						var connection *amqp.Connection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// don't continue until rabbit is ready
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							c, err := amqp.Dial("amqp://guest:guest@rabbitmq") // XXX: credentials
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Println("RabbitMQ not yet ready...")
 | 
				
			||||||
 | 
								counts++
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								connection = c
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if counts > 5 {
 | 
				
			||||||
 | 
								fmt.Println(err)
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							backOff := time.Duration(math.Pow(float64(counts), 2) * float64(time.Second))
 | 
				
			||||||
 | 
							log.Println("backing off...")
 | 
				
			||||||
 | 
							time.Sleep(backOff)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return connection, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,3 +6,5 @@ require (
 | 
				
			|||||||
	github.com/go-chi/chi/v5 v5.1.0
 | 
						github.com/go-chi/chi/v5 v5.1.0
 | 
				
			||||||
	github.com/go-chi/cors v1.2.1
 | 
						github.com/go-chi/cors v1.2.1
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require github.com/rabbitmq/amqp091-go v1.10.0
 | 
				
			||||||
 | 
				
			|||||||
@ -2,3 +2,7 @@ github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
 | 
				
			|||||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
 | 
					github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
 | 
				
			||||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
 | 
					github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
 | 
				
			||||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
 | 
					github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
 | 
				
			||||||
 | 
					github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
 | 
				
			||||||
 | 
					github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
 | 
				
			||||||
 | 
					go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 | 
				
			||||||
 | 
					go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ func (consumer *Consumer) setup() error {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						defer channel.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return declaireExchange(channel)
 | 
						return declaireExchange(channel)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user