gocodecache

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2022 License: MIT Imports: 9 Imported by: 1

README

gocodecache

GoDoc MIT License CI

An in-memory cache library for code master in Golang.

Installation

go get github.com/takuoki/gocodecache

Get started

Create YAML file
# ./sample/codes.yaml
VERSION: 0.1.0

CODES:
  account_type:
    1: Anonymous account
    2: General account
    3: Administrator account
  visibility_level:
    1: Private
    2: Public
Code
package main

import (
  "context"

  cache "github.com/takuoki/gocodecache"
)

func main() {
  ctx := context.Background()

  if err := cache.InitializeGlobalCache(ctx, cache.YAMLSource("./sample/codes.yaml", "CODES"), 2); err != nil {
    // handle error
  }

  accType1Str, err := cache.GetValue(ctx, "account_type", "1")
  if err != nil {
    // handle error
  }

  vLevel2Str := cache.MustGetValue(ctx, "visibility_level", "2")
}

Datasource

Raw

Define a datasource as Golang code.

datasource := cache.RawSource(cache.Codes{
  {"account_type", "1"}:     "Anonymous account",
  {"account_type", "2"}:     "General account",
  {"account_type", "3"}:     "Administrator account",
  {"visibility_level", "1"}: "Private",
  {"visibility_level", "2"}: "Public",
})
YAML
datasource := cache.YAMLSource("./sample/codes.yaml", "CODES")
VERSION: 0.1.0

CODES:
  account_type:
    1: Anonymous account
    2: General account
    3: Administrator account
  visibility_level:
    1: Private
    2: Public
Relational database

!!! WARNING !!! Tested only with PostgreSQL.

datasource := cache.RdbSource(db, "codes", []string{"key1", "key2"}, "value")

table: codes

key1 key2 value
account_type 1 Anonymous account
account_type 2 General account
account_type 3 Administrator account
visibility_level 1 Private
visibility_level 2 Public

Tips

Partial loading

By specifying first keys, you can load a part of the code master.

package main

import (
  "context"

  cache "github.com/takuoki/gocodecache"
)

func main() {
  ctx := context.Background()

  // ...

  c, err := cache.New(ctx, datasource, 2, cache.WithLoadFirstKeys("account_type"))
  if err != nil {
    // handle error
  }

  // found
  accType1Str, err := c.GetValue(ctx, "account_type", "1")
  if err != nil {
    // handle error
  }

  // not found
  vLevel2Str, err := c.GetValue(ctx, "visibility_level", "2")
  if err != nil {
    // handle error
  }
}
Automatic reloading

By implementing the reloading process in goroutine, automatic reloading can be achieved. (sample)

package main

import (
  "context"
  "time"

  cache "github.com/takuoki/gocodecache"
)

const reloadInterval = 1 * time.Hour

func main() {

  // ...

  c, err := cache.New(ctx, datasource, 2)
  if err != nil {
    // handle error
  }
  go reload(ctx, c)

  // ...

}

func reload(ctx context.Context, c *cache.Cache) {
  for {
    select {
    case <-ctx.Done():
      return
    default:
    }

    time.Sleep(reloadInterval)
    if err := c.Reload(ctx); err != nil {
      // handle error
    }
  }
}
Internationalization (I18n)

I18n can be supported by adding language codes to the keys.

# ./sample/codes_lang.yaml
VERSION: 0.1.0

CODES:
  account_type:
    1:
      en-US: Anonymous account
      ja-JP: 匿名アカウント
    2:
      en-US: General account
      ja-JP: 一般アカウント
    3:
      en-US: Administrator account
      ja-JP: 管理者アカウント
  visibility_level:
    1:
      en-US: Private
      ja-JP: 非公開
    2:
      en-US: Public
      ja-JP: 公開

Documentation

Overview

Example
package main

import (
	"context"
	"fmt"

	_ "github.com/lib/pq"
	cache "github.com/takuoki/gocodecache"
)

func main() {
	ctx := context.Background()

	// -- How to initialize --

	if err := cache.InitializeGlobalCache(ctx, cache.YAMLSource("./sample/codes.yaml", "CODES"), 2); err != nil {
		// handle error
	}

	// -- How to get value --

	accType1Str, err := cache.GetValue(ctx, "account_type", "1")
	if err != nil {
		// handle error
	}

	fmt.Println(accType1Str)
	fmt.Println(cache.MustGetValue(ctx, "visibility_level", "2"))

}
Output:

Anonymous account
Public

Index

Examples

Constants

View Source
const MaxKeyLength = 5

Variables

View Source
var (
	ErrNotInitialized = errors.New("cache is not initialized")
	ErrCodeNotFound   = errors.New("code not found")
)

Functions

func GetValue

func GetValue(ctx context.Context, keys ...string) (string, error)

func InitializeGlobalCache

func InitializeGlobalCache(ctx context.Context, ds Datasource, keyLength int, opts ...InitializeOption) error

func MustGetValue

func MustGetValue(ctx context.Context, keys ...string) string

func Reload

func Reload(ctx context.Context) error

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"context"
	"fmt"

	_ "github.com/lib/pq"
	cache "github.com/takuoki/gocodecache"
)

func main() {
	ctx := context.Background()

	// -- How to initialize --

	c, err := cache.New(ctx, cache.YAMLSource("./sample/codes_lang.yaml", "CODES"), 3)
	if err != nil {
		// handle error
	}

	// -- How to get value --

	accType1jaStr, err := c.GetValue(ctx, "account_type", "1", "ja-JP")
	if err != nil {
		// handle error
	}

	fmt.Println(accType1jaStr)
	fmt.Println(c.MustGetValue(ctx, "visibility_level", "2", "en-US"))

}
Output:

匿名アカウント
Public

func New

func New(ctx context.Context, ds Datasource, keyLength int, opts ...InitializeOption) (*Cache, error)

func (*Cache) GetValue

func (c *Cache) GetValue(ctx context.Context, keys ...string) (string, error)

func (*Cache) MustGetValue

func (c *Cache) MustGetValue(ctx context.Context, keys ...string) string

func (*Cache) Reload

func (c *Cache) Reload(ctx context.Context) error

type CodeLists added in v0.2.0

type CodeLists map[[MaxKeyLength - 1]string][]string

type Codes added in v0.2.0

type Codes map[[MaxKeyLength]string]string

type Datasource

type Datasource interface {
	ReadAll(ctx context.Context, keyLength int) (Codes, error)
	ReadFirstKeys(ctx context.Context, keyLength int, firstKeys map[string]struct{}) (Codes, error)
}

func RawSource

func RawSource(data Codes) Datasource

func RdbSource

func RdbSource(db *sql.DB, tableName string,
	keyColumnNames []string, valueColumnName string,
) Datasource
Example
ctx := context.Background()

// -- How to initialize --

db, err := sql.Open(
	"postgres",
	fmt.Sprintf(
		"host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
		"localhost",
		"5432",
		"root",
		"root",
		"postgres",
		"disable",
	),
)
if err != nil {
	// handle error
}
defer db.Close()

for i := 0; ; i++ {
	if i >= dbPingRetryLimit {
		// handle error
	}
	if err = db.Ping(); err == nil {
		break
	}
	time.Sleep(dbPingRetryInterval)
}

c, err := cache.New(ctx, cache.RdbSource(db, "codes", []string{"key1", "key2"}, "value"), 2)
if err != nil {
	// handle error
}

// -- How to get value --

accType1jaStr, err := c.GetValue(ctx, "account_type", "1")
if err != nil {
	// handle error
}

fmt.Println(accType1jaStr)
fmt.Println(c.MustGetValue(ctx, "visibility_level", "2"))
Output:

Anonymous account
Public

func YAMLSource

func YAMLSource(filepath, rootKey string) Datasource

type InitializeOption added in v0.2.0

type InitializeOption interface {
	// contains filtered or unexported methods
}

func WithLoadFirstKeys added in v0.2.0

func WithLoadFirstKeys(firstKeys ...string) InitializeOption

Directories

Path Synopsis
sample module

Jump to

Keyboard shortcuts

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