cache

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2022 License: MIT Imports: 1 Imported by: 4

README

cache

GoDoc Go Report Card MIT License discord

This go module provides a very simple in-memory key/value cache. It uses no mutex locks; utilizing only 1 go routine, 2 channels, and 1 or 2 tickers depending on if you enable the pruner. The module also exports git/miss statistics that you can plug into expvar, or other metrics modules.

This module has a concept of pruning. Items can be marked prunable, or not prunable. Those marked prunable are deleted after they have not had a get requst within a specified duration. Those marked not-prunable have a different configurable maximum unused age.

I wrote this to cache data from mysql queries for an nginx auth proxy. See a simple example in cache_test.go.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache provides methods to get a user and delete a user from cache. If the user is not in cache it is fetched using the userinfo module.

func New

func New(config Config) *Cache

New starts the cache routine and returns a struct to get data from the cache. You do not need to call Start() after calling New(); it's already started.

Example
package main

import (
	"fmt"

	"golift.io/cache"
)

func main() {
	users := cache.New(cache.Config{})
	defer users.Stop(true) // stop the processor go routine.

	// This example just saves a string.
	// The input is an interface{} so you can save more than strings.
	users.Save("admin", "Super Dooper", cache.Options{})
	users.Save("luser", "Under Dawggy", cache.Options{})

	user := users.Get("luser")
	fmt.Println("User Name:", user.Data)

	users.Delete("luser")

	stats := users.Stats()
	fmt.Println("Gets:", stats.Gets)
	fmt.Println("Hits:", stats.Hits)
	fmt.Println("Miss:", stats.Misses)
	fmt.Println("Save:", stats.Saves)
	fmt.Println("Del:", stats.Deletes)
	fmt.Println("Size:", stats.Size)
}
Output:

User Name: Under Dawggy
Gets: 1
Hits: 1
Miss: 0
Save: 2
Del: 1
Size: 1

func (*Cache) Delete

func (c *Cache) Delete(requestKey string) bool

Delete removes an item and returns true if it existed.

func (*Cache) ExpStats

func (c *Cache) ExpStats() any

ExpStats returns the stats inside of an interface{} so expvar can consume it. Use it in your app like this:

myCache := cache.New(cache.Config{})
expvar.Publish("Cache", expvar.Func(myCache.ExpStats))
/* or put it inside your own expvar map. */
myMap := expvar.NewMap("myMap")
myMap.Set("Cache", expvar.Func(myCache.ExpStats))

This will never be nil, and concurrent access is OK.

func (*Cache) Get

func (c *Cache) Get(requestKey string) *Item

Get returns a pointer to a copy of an item, or nil if it doesn't exist. Because it's a copy, concurrent access is OK.

func (*Cache) List

func (c *Cache) List() map[string]*Item

List returns a copy of the in-memory cache. This will never be nil, and concurrent access is OK. The map Items will also never be nil, and because they are copies, concurrent access to Items is also OK. This method will double the memory footprint until release, and garbage collection runs. If the data stored in cache is large and not pointers, then you may not want to call this method much, or at all.

func (*Cache) Save

func (c *Cache) Save(requestKey string, data any, opts Options) bool

Save saves an item, and returns true if it already existed (got updated).

func (*Cache) Start

func (c *Cache) Start(clean bool)

Starts sets up the cache and starts the go routine. Call this only if you already called Stop() and wish to turn it back on. Setting clean will clear the existing cache before restarting.

func (*Cache) Stats

func (c *Cache) Stats() *Stats

Stats returns the cache statistics. This will never be nil, and concurrent access is OK.

func (*Cache) Stop

func (c *Cache) Stop(clean bool)

Stop stops the go routine and closes the channels. If clean is true it will clean up memory usage and delete the cache. Pass clean if the app will continue to run, and you don't need to re-use the cache data.

type Config

type Config struct {
	// Prune enables the pruner routine.
	// This must be enabled to use Expire time on Items.
	// If you don't want other prunes to happen,
	// set really long durations for PruneAfter and MaxUnused.
	// @ recommend 3 minutes - 5 minutes
	PruneInterval time.Duration
	// PruneAfter causes the pruner routine to prune keys marked prunable
	// after they have not been used for this duration.
	// @default 18 minutes
	PruneAfter time.Duration
	// Keys not marked prunable are pruned by the pruner routine
	// after they have not been used for this duration.
	// @default 25 hours
	MaxUnused time.Duration
	// RequestAccuracy can be set between 100 milliseconds and 1 minute.
	// This sets the ticker interval that updates our time.Now() variable.
	// Generally, the default of 1 second should be fine for most apps.
	// If accuracy about when an item was saved isn't important, you can raise
	// this to a few seconds quite safely and the cache will use fewer cpu cycles.
	RequestAccuracy time.Duration
}

Config provides the input options for a new cache. All the fields are optional.

type Duration

type Duration struct {
	time.Duration
}

Duration is used to format time duration(s) in stats output.

func (*Duration) MarshalJSON

func (d *Duration) MarshalJSON() ([]byte, error)

MarshalJSON turns a Duration into a string for json or expvar.

type Item

type Item struct {
	Data any       `json:"data"`
	Time time.Time `json:"created"`
	Last time.Time `json:"lastAccess"`
	Hits int64     `json:"hits"`
	// contains filtered or unexported fields
}

Item is what's returned from a cache Get.

  • Data is the input data. Type-check it back to what it should be.
  • Time is when the item was saved (or updated) in cache.
  • Last is the time when the last cache get for this item occurred.
  • Hits is the number of cache gets for this key.

type Options

type Options struct {
	// Setting Prune true will allow the pruning routine to prune this item.
	// Items are pruned when they have not been retreived in the PruneAfter duration.
	Prune bool
	// You may set a specific eviction time for an item. This only works if the
	// pruner is running. The item will be removed from cache after this date/time.
	// This works independently from setting Prune to true, and follows different logic.
	// Not setting this, or setting it to zero time will never expire the item.
	Expire time.Time
}

Options are optional, and may be provided when saving a cached item.

type Stats

type Stats struct {
	Size    int64    // derived. Count of items in cache.
	Gets    int64    // derived. Cache gets issued.
	Hits    int64    // Gets for cached keys.
	Misses  int64    // Gets for missing keys.
	Saves   int64    // Saves for a new key.
	Updates int64    // Saves that caused an update.
	Deletes int64    // Delete hits.
	DelMiss int64    // Delete misses.
	Pruned  int64    // Total items pruned.
	Prunes  int64    // Number of times pruner has run.
	Pruning Duration // How much time has been spent pruning.
}

Stats contains the exported cache statistics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL