Fiber version
v1.14.4
Issue description
fiber web server, fiber cookie handling and the LRU algorithm.fiber web server is the problem.Code snippet
Please take a look at
https://github.com/suntong/fiber_demo/blob/master/app/lru_demo.go
also included below:
package main
import (
"fmt"
"log"
"github.com/gofiber/fiber"
"github.com/hashicorp/golang-lru/simplelru"
)
func main() {
app := fiber.New()
evictCounter := 0
onEvicted := func(k interface{}, v interface{}) {
evictCounter++
}
// https://godoc.org/github.com/hashicorp/golang-lru/simplelru
l, err := simplelru.NewLRU(12, onEvicted)
if err != nil {
log.Fatalf("err: %v", err)
}
// http://localhost:3000/q?p=something
app.Get("/q", func(c *fiber.Ctx) {
l.Add(c.Query("p"), nil)
r := fmt.Sprintln(l.Keys())
c.Send(r)
})
app.Listen(3000)
}
$ go run lru_demo.go
_______ __
____ / ____(_) /_ ___ _____ HOST 0.0.0.0 OS LINUX
_____ / /_ / / __ \/ _ \/ ___/ PORT 3000 THREADS 12
__ / __/ / / /_/ / __/ / TLS FALSE PREFORK FALSE
/_/ /_/_.___/\___/_/1.14.4 HANDLERS 1 PID 35311
Here is what I got on my first run (duplicated the problem on first attempt that I wanted to duplicate with the LRU algorithm alone for days):
$ curl http://localhost:3000/q?p=AAAAAAAAAAAAA
[AAAAAAAAAAAAA]
$ curl http://localhost:3000/q?p=BBBBBBBBBBBBB
[AAAAAAAAAAAAA BBBBBBBBBBBBB]
$ curl http://localhost:3000/q?p=CCCCCCCCCCCCC
[CCCCCCCCCCCCC BBBBBBBBBBBBB CCCCCCCCCCCCC]
$ curl http://localhost:3000/q?p=DDDDDDDDDDDDD
[CCCCCCCCCCCCC BBBBBBBBBBBBB CCCCCCCCCCCCC DDDDDDDDDDDDD]
$ curl http://localhost:3000/q?p=EEEEEEEEEEEEE
[CCCCCCCCCCCCC EEEEEEEEEEEEE CCCCCCCCCCCCC DDDDDDDDDDDDD EEEEEEEEEEEEE]
$ curl http://localhost:3000/q?p=CCCCCCCCCCCCC
[CCCCCCCCCCCCC CCCCCCCCCCCCC DDDDDDDDDDDDD CCCCCCCCCCCCC CCCCCCCCCCCCC]
What's being printed is the LRU entries, which should has been [AA..., BB..., CC..., DD..., EE...] up to the second last step, and the last step should just shuffle the priorities / listing order.
I've been spending days and days on duplicating the problem with the LRU algorithm alone, covering a huge amount of test cases, but all are just fine. I'm not going to list them all here, but this is the most convincing one for me to believe that the LRU algorithm alone is not the problem:
https://play.golang.org/p/5rEGKtiuiO1
Please double check. Might the fiber being multi-threaded be the root cause?
Thanks a lot!
Hi @suntong, this is expected because of the returned value from c.Query() is only valid within the handler.
// Query returns the query string parameter in the url.
// Defaults to empty string "" if the query doesn't exist.
// If a default value is given, it will return that value if the query doesn't exist.
// Returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting to use the value outside the Handler.
func (ctx *Ctx) Query(key string, defaultValue ...string) string
_Returned value is only valid within the handler. Do not store any references.
Make copies or use the Immutable setting to use the value outside the Handler._
app.Get("/q", func(c *fiber.Ctx) {
p := utils.ImmutableString(c.Query("p"))
l.Add(p, nil)
c.Send(l.Keys())
})
Read more about Fiber's zero allocation model here https://docs.gofiber.io/#zero-allocation
Aha!!! No wonder!
Thanks a lot for the fast response!
Most helpful comment
Hi @suntong, this is expected because of the returned value from
c.Query()is only valid within the handler._Returned value is only valid within the handler. Do not store any references.
Make copies or use the Immutable setting to use the value outside the Handler._
Read more about Fiber's zero allocation model here https://docs.gofiber.io/#zero-allocation