I have a go-fiber app that tries to publish messages to RabbitMQ. And here is the simplified version of the app:
// main.go
type custom_handler struct {
RMQConn *rabbitmq.Connection
}
func newHandler(conn *rabbitmq.Connection) custom_handler {
return custom_handler{
RMQConn: conn,
}
}
func main() {
var hndlr custom_handler
if !fiber.IsChild() {
messageq.ConnectMQ()
hndlr = newHandler(messageq.RMQConn)
log.Println(messageq.RMQConn) // not nil
}
engine := html.New("./static", ".html")
app := fiber.New(fiber.Config{
Views: engine,
Prefork: true, // ATTENTION!!!
})
app.Use(cors.New())
app.Get("/", func(c *fiber.Ctx) error {
return c.Render("index", fiber.Map{})
})
app.Post("/", hndlr.handleFileupload)
log.Fatal(app.Listen(":8080"))
}
func (hndlr custom_handler) handleFileupload(c *fiber.Ctx) error {
log.Println(hndlr.RMQConn) // nil
RMQChan, err := hndlr.RMQConn.Channel()
if err != nil {
return err
}
defer RMQChan.Close()
}
And messageq
package looks like this:
// messageq.go
var RMQConn *rabbitmq.Connection
func ConnectMQ() {
var err error
amqpServerURL := os.Getenv("RABBITMQ_SERVER_URL")
RMQConn, err = rabbitmq.Dial(amqpServerURL)
if err != nil {
panic(err)
}
}
afaik, RabbitMQ Connections can be shared between goroutines.
But when I run the app, I get this segmentation violation
error:
producer_1 | panic: runtime error: invalid memory address or nil pointer dereference
producer_1 | [signal SIGSEGV: segmentation violation code=0x1 addr=0x14 pc=0x8ef6db]
imgress-producer_1 |
producer_1 | goroutine 7 [running]:
producer_1 | github.com/rabbitmq/amqp091-go.(*Connection).allocateChannel(0x0)
producer_1 | /go/pkg/mod/github.com/rabbitmq/amqp091-go@v1.5.0/connection.go:679 +0x5b
producer_1 | github.com/rabbitmq/amqp091-go.(*Connection).openChannel(0x4f46c8?)
producer_1 | /go/pkg/mod/github.com/rabbitmq/amqp091-go@v1.5.0/connection.go:709 +0x25
producer_1 | github.com/rabbitmq/amqp091-go.(*Connection).Channel(...)
producer_1 | /go/pkg/mod/github.com/rabbitmq/amqp091-go@v1.5.0/connection.go:736
producer_1 | main.ValidateAndPublish({0xc0000120c8, 0x1, 0xb7aeff?}, 0x1?, {0xc0000e7f38, 0x8}, 0xffffffffffffffff?)
producer_1 | /app/validate.go:14 +0x8a
producer_1 | main.custom_handler.handleFileupload({0x0?, 0x0?}, 0xc00015f080?)
producer_1 | /app/main.go:94 +0x4bb
producer_1 | github.com/gofiber/fiber/v2.(*App).next(0xc000221b80, 0xc00009e000)
producer_1 | /go/pkg/mod/github.com/gofiber/fiber/v2@v2.39.0/router.go:132 +0x1c2
producer_1 | github.com/gofiber/fiber/v2.(*Ctx).Next(0xc0001bcf18?)
producer_1 | /go/pkg/mod/github.com/gofiber/fiber/v2@v2.39.0/ctx.go:945 +0x53
producer_1 | github.com/gofiber/fiber/v2/middleware/cors.New.func1(0xc00009e000)
producer_1 | /go/pkg/mod/github.com/gofiber/fiber/v2@v2.39.0/middleware/cors/cors.go:141 +0x286
producer_1 | github.com/gofiber/fiber/v2.(*App).next(0xc000221b80, 0xc00009e000)
producer_1 | /go/pkg/mod/github.com/gofiber/fiber/v2@v2.39.0/router.go:132 +0x1c2
producer_1 | github.com/gofiber/fiber/v2.(*App).handler(0xc000221b80, 0x485df7?)
producer_1 | /go/pkg/mod/github.com/gofiber/fiber/v2@v2.39.0/router.go:159 +0x45
producer_1 | github.com/valyala/fasthttp.(*Server).serveConn(0xc0001478c0, {0xc8dd90?, 0xc000012070})
producer_1 | /go/pkg/mod/github.com/valyala/fasthttp@v1.40.0/server.go:2311 +0x1268
producer_1 | github.com/valyala/fasthttp.(*workerPool).workerFunc(0xc0000000a0, 0xc0000400a0)
producer_1 | /go/pkg/mod/github.com/valyala/fasthttp@v1.40.0/workerpool.go:224 +0xa9
producer_1 | github.com/valyala/fasthttp.(*workerPool).getCh.func1()
producer_1 | /go/pkg/mod/github.com/valyala/fasthttp@v1.40.0/workerpool.go:196 +0x38
producer_1 | created by github.com/valyala/fasthttp.(*workerPool).getCh
producer_1 | /go/pkg/mod/github.com/valyala/fasthttp@v1.40.0/workerpool.go:195 +0x1b0
I am assuming because I do Prefork: true
while creating the app, every request will be handled in a separate goroutine, and it seems that at the moment handler can not access the connection.
So, can somebody point to something that I am missing? How can I make the RabbitMQ connection available for the handler?