Skip to content

Instantly share code, notes, and snippets.

@adhocore
Last active April 30, 2024 09:51
Show Gist options
  • Save adhocore/6bce87515c045d046583983f8fc51e93 to your computer and use it in GitHub Desktop.
Save adhocore/6bce87515c045d046583983f8fc51e93 to your computer and use it in GitHub Desktop.
BigCache Server using fasthttp
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
"github.com/adhocore/fasthttp"
"github.com/allegro/bigcache/v3"
)
const (
// server version.
version = "1.0.0"
)
var (
port int
logfile string
ver bool
// cache-specific settings.
cache *bigcache.BigCache
config = bigcache.Config{}
)
func init() {
flag.BoolVar(&config.Verbose, "v", false, "Verbose logging.")
flag.IntVar(&config.Shards, "shards", 1024, "Number of shards for the cache.")
flag.IntVar(&config.MaxEntriesInWindow, "maxInWindow", 1000*10*60, "Used only in initial memory allocation.")
flag.DurationVar(&config.LifeWindow, "lifetime", 100000*100000*60, "Lifetime of each cache object.")
flag.IntVar(&config.HardMaxCacheSize, "max", 8192, "Maximum amount of data in the cache in MB.")
flag.IntVar(&config.MaxEntrySize, "maxShardEntrySize", 500, "The maximum size of each object stored in a shard. Used only in initial memory allocation.")
flag.IntVar(&port, "port", 9090, "The port to listen on.")
flag.StringVar(&logfile, "logfile", "", "Location of the logfile.")
flag.BoolVar(&ver, "version", false, "Print server version.")
}
func main() {
flag.Parse()
if ver {
fmt.Printf("BigCache HTTP Server v%s", version)
os.Exit(0)
}
var logger *log.Logger
if logfile == "" {
logger = log.New(os.Stdout, "", log.LstdFlags)
} else {
f, err := os.OpenFile(logfile, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
logger = log.New(f, "", log.LstdFlags)
}
var err error
cache, err = bigcache.New(context.Background(), config)
if err != nil {
logger.Fatal(err)
}
logger.Print("cache initialised.")
app := fasthttp.New()
sub := app.Group("/c")
sub.Get("/:key", func(c *fasthttp.Ctx) error {
entry, err := cache.Get(c.Params("key"))
if err != nil {
if strings.Contains(err.Error(), "not found") {
return c.SendStatus(fasthttp.StatusNotFound)
} else {
return c.SendStatus(fasthttp.StatusInternalServerError)
}
}
return c.Send(entry)
})
sub.Post("/:key", func(c *fasthttp.Ctx) error {
body := c.BodyRaw()
entry := make([]byte, len(body))
copy(entry, body)
if err := cache.Set(c.Params("key"), entry); err != nil {
return c.SendStatus(fasthttp.StatusInternalServerError)
}
return c.SendStatus(fasthttp.StatusCreated)
})
sub.Delete("/:key", func(c *fasthttp.Ctx) error {
if err := cache.Delete(c.Params("key")); err != nil {
return c.SendStatus(fasthttp.StatusInternalServerError)
}
return c.SendStatus(fasthttp.StatusOK)
})
app.Get("/stats", func(c *fasthttp.Ctx) error {
return c.JSON(cache.Stats())
})
logger.Printf("starting server on :%d", port)
strPort := ":" + strconv.Itoa(port)
log.Fatal("serve: ", app.Serve(strPort))
}
// run:
// go run bigcache.go
//
// set cache with key 'xyz'
// curl 0:9090/c/xyz -d'{"val":"value"}'
//
// get cache with key 'xyz'
// curl 0:9090/c/xyz
//
// del cache with key 'xyz'
// curl -XDELETE 0:9090/c/xyz
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment