mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 18:37:05 +00:00
reorganization of _examples and add some new examples such as iris+groupcache+mysql+docker
Former-commit-id: ed635ee95de7160cde11eaabc0c1dcb0e460a620
This commit is contained in:
120
_examples/database/mysql/cache/groupcache.go
vendored
Normal file
120
_examples/database/mysql/cache/groupcache.go
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"myapp/entity"
|
||||
"myapp/sql"
|
||||
|
||||
"github.com/mailgun/groupcache/v2"
|
||||
)
|
||||
|
||||
// Service that cache will use to retrieve data.
|
||||
type Service interface {
|
||||
RecordInfo() sql.Record
|
||||
GetByID(ctx context.Context, dest interface{}, id int64) error
|
||||
List(ctx context.Context, dest interface{}, opts sql.ListOptions) error
|
||||
}
|
||||
|
||||
// Cache is a simple structure which holds the groupcache and the database service, exposes
|
||||
// `GetByID` and `List` which returns cached (or stores new) items.
|
||||
type Cache struct {
|
||||
service Service
|
||||
maxAge time.Duration
|
||||
group *groupcache.Group
|
||||
}
|
||||
|
||||
// Size default size to use on groupcache, defaults to 3MB.
|
||||
var Size int64 = 3 << (10 * 3)
|
||||
|
||||
// New returns a new cache service which exposes `GetByID` and `List` methods to work with.
|
||||
// The "name" should be unique, "maxAge" for cache expiration.
|
||||
func New(service Service, name string, maxAge time.Duration) *Cache {
|
||||
c := new(Cache)
|
||||
c.service = service
|
||||
c.maxAge = maxAge
|
||||
c.group = groupcache.NewGroup(name, Size, c)
|
||||
return c
|
||||
}
|
||||
|
||||
const (
|
||||
prefixID = "#"
|
||||
prefixList = "["
|
||||
)
|
||||
|
||||
// Get implements the groupcache.Getter interface.
|
||||
// Use `GetByID` and `List` instead.
|
||||
func (c *Cache) Get(ctx context.Context, key string, dest groupcache.Sink) error {
|
||||
if len(key) < 2 { // empty or missing prefix+key, should never happen.
|
||||
return sql.ErrUnprocessable
|
||||
}
|
||||
|
||||
var v interface{}
|
||||
|
||||
prefix := key[0:1]
|
||||
key = key[1:]
|
||||
switch prefix {
|
||||
case prefixID:
|
||||
// Get by ID.
|
||||
id, err := strconv.ParseInt(key, 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.service.RecordInfo().(type) {
|
||||
case *entity.Category:
|
||||
v = new(entity.Category)
|
||||
case *entity.Product:
|
||||
v = new(entity.Product)
|
||||
}
|
||||
|
||||
err = c.service.GetByID(ctx, v, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case prefixList:
|
||||
// Get a set of records, list.
|
||||
q, err := url.ParseQuery(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts := sql.ParseListOptions(q)
|
||||
|
||||
switch c.service.RecordInfo().(type) {
|
||||
case *entity.Category:
|
||||
v = new(entity.Categories)
|
||||
case *entity.Product:
|
||||
v = new(entity.Products)
|
||||
}
|
||||
|
||||
err = c.service.List(ctx, v, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return sql.ErrUnprocessable
|
||||
}
|
||||
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dest.SetBytes(b, time.Now().Add(c.maxAge))
|
||||
}
|
||||
|
||||
// GetByID binds an item to "dest" an item based on its "id".
|
||||
func (c *Cache) GetByID(ctx context.Context, id string, dest *[]byte) error {
|
||||
return c.group.Get(ctx, prefixID+id, groupcache.AllocatingByteSliceSink(dest))
|
||||
}
|
||||
|
||||
// List binds item to "dest" based on the "rawQuery" of `url.Values` for `ListOptions`.
|
||||
func (c *Cache) List(ctx context.Context, rawQuery string, dest *[]byte) error {
|
||||
return c.group.Get(ctx, prefixList+rawQuery, groupcache.AllocatingByteSliceSink(dest))
|
||||
}
|
||||
Reference in New Issue
Block a user