Skip to content
This repository has been archived by the owner on Sep 21, 2022. It is now read-only.

Commit

Permalink
Merge 0261ef3 into 9afa378
Browse files Browse the repository at this point in the history
  • Loading branch information
alejandro-carstens committed Mar 17, 2018
2 parents 9afa378 + 0261ef3 commit b422e2c
Show file tree
Hide file tree
Showing 16 changed files with 1,911 additions and 1 deletion.
11 changes: 10 additions & 1 deletion .travis.yml
Expand Up @@ -7,11 +7,20 @@ go:
- 1.9.x
- tip
services:
-postgresql
- postgresql
- redis-server
- memcached
before_script:
- psql -c 'create database utron;' -U postgres
before_install:
- go get -t -v
- go get github.com/mattn/goveralls

matrix:
allow_failures:
- go: 1.5.x
- go: 1.6.x
- go: tip

script:
- $HOME/gopath/bin/goveralls -v -service=travis-ci -repotoken=$COVERALLS
32 changes: 32 additions & 0 deletions cache/cache.go
@@ -0,0 +1,32 @@
package cache

import (
"strings"
)

// REDIS_DRIVER specifies the redis driver name
const REDIS_DRIVER = "redis"

// MEMCACHE_DRIVER specifies the memcache driver name
const MEMCACHE_DRIVER = "memcache"

// MAP_DRIVER specifies the map driver name
const MAP_DRIVER = "map"

// New new-ups an instance of StoreInterface
func New(driver string, params map[string]interface{}) (StoreInterface, error) {
switch strings.ToLower(driver) {
case REDIS_DRIVER:
return connect(new(RedisConnector), params)
case MEMCACHE_DRIVER:
return connect(new(MemcacheConnector), params)
case MAP_DRIVER:
return connect(new(MapConnector), params)
}

return connect(new(MapConnector), params)
}

func connect(connector CacheConnectorInterface, params map[string]interface{}) (StoreInterface, error) {
return connector.Connect(params)
}
81 changes: 81 additions & 0 deletions cache/connector_test.go
@@ -0,0 +1,81 @@
package cache

import (
"testing"
)

func TestMemcacheConnector(t *testing.T) {
memcacheConnector := new(MemcacheConnector)

memcacheStore, err := memcacheConnector.Connect(memcacheStore())

if err != nil {
panic(err)
}

_, ok := memcacheStore.(StoreInterface)

if !ok {
t.Error("Expected StoreInterface got", memcacheStore)
}
}

func TestRedisConnector(t *testing.T) {
redisConnector := new(RedisConnector)

redisStore, err := redisConnector.Connect(redisStore())

if err != nil {
panic(err)
}

_, ok := redisStore.(StoreInterface)

if !ok {
t.Error("Expected StoreInterface got", redisStore)
}
}

func TestArrayConnector(t *testing.T) {
mapConnector := new(MapConnector)

mapStore, err := mapConnector.Connect(mapStore())

if err != nil {
panic(err)
}

_, ok := mapStore.(StoreInterface)

if !ok {
t.Error("Expected StoreInterface got", mapStore)
}
}

func redisStore() map[string]interface{} {
params := make(map[string]interface{})

params["address"] = "localhost:6379"
params["password"] = ""
params["database"] = 0
params["prefix"] = "golavel:"

return params
}

func memcacheStore() map[string]interface{} {
params := make(map[string]interface{})

params["server 1"] = "127.0.0.1:11211"
params["prefix"] = "golavel:"

return params
}

func mapStore() map[string]interface{} {
params := make(map[string]interface{})

params["prefix"] = "golavel:"

return params
}
58 changes: 58 additions & 0 deletions cache/contracts.go
@@ -0,0 +1,58 @@
package cache

// CacheConnectorInterface represents the connector methods to be implemented
type CacheConnectorInterface interface {
Connect(params map[string]interface{}) (StoreInterface, error)

validate(params map[string]interface{}) (map[string]interface{}, error)
}

// CacheInterface represents the caching methods to be implemented
type CacheInterface interface {
Get(key string) (interface{}, error)

Put(key string, value interface{}, minutes int) error

Increment(key string, value int64) (int64, error)

Decrement(key string, value int64) (int64, error)

Forget(key string) (bool, error)

Forever(key string, value interface{}) error

Flush() (bool, error)

GetInt(key string) (int64, error)

GetFloat(key string) (float64, error)

GetPrefix() string

Many(keys []string) (map[string]interface{}, error)

PutMany(values map[string]interface{}, minutes int) error

GetStruct(key string, entity interface{}) (interface{}, error)
}

// TagsInterface represents the tagging methods to be implemented
type TagsInterface interface {
Tags(names ...string) TaggedStoreInterface
}

// StoreInterface represents the methods a caching store needs to implement
type StoreInterface interface {
CacheInterface

TagsInterface
}

// TaggedStoreInterface represents the methods a tagged-caching store needs to implement
type TaggedStoreInterface interface {
CacheInterface

TagFlush() error

GetTags() TagSet
}
84 changes: 84 additions & 0 deletions cache/helpers.go
@@ -0,0 +1,84 @@
package cache

import (
"bytes"
"encoding/json"
"math"
"strconv"
)

// Encode encodes json.Marshal to a string
func Encode(item interface{}) (string, error) {
value, err := json.Marshal(item)

return string(value), err
}

// SimpleDecode decodes json.Unmarshal to a string
func SimpleDecode(value string) (string, error) {
err := json.Unmarshal([]byte(value), &value)

return string(value), err
}

// Decode performs a json.Unmarshal
func Decode(value string, entity interface{}) (interface{}, error) {
err := json.Unmarshal([]byte(value), &entity)

return entity, err
}

// IsNumeric check if the provided value is numeric
func IsNumeric(s interface{}) bool {
switch s.(type) {
case int:
return true
case int32:
return true
case float32:
return true
case float64:
return true
default:
return false
}
}

// GetTaggedManyKey returns a tagged many key
func GetTaggedManyKey(prefix string, key string) string {
count := len(prefix) + 41

sub := ""
subs := []string{}

runs := bytes.Runes([]byte(key))

for i, run := range runs {
sub = sub + string(run)
if (i+1)%count == 0 {
subs = append(subs, sub)
sub = ""
} else if (i + 1) == len(runs) {
subs = append(subs, sub)
}
}

return subs[1]
}

// IsStringNumeric checks if a string is numeric
func IsStringNumeric(value string) bool {
_, err := strconv.ParseFloat(value, 64)

return err == nil
}

// StringToFloat64 converts a string to float64
func StringToFloat64(value string) (float64, error) {
return strconv.ParseFloat(value, 64)
}

// IsFloat checks if the provided value can be truncated to an int
func IsFloat(value float64) bool {
return value != math.Trunc(value)
}
34 changes: 34 additions & 0 deletions cache/map_connector.go
@@ -0,0 +1,34 @@
package cache

import (
"errors"
)

// MapConnector is a representation of the array store connector
type MapConnector struct{}

// Connect is responsible for connecting with the caching store
func (ac *MapConnector) Connect(params map[string]interface{}) (StoreInterface, error) {
params, err := ac.validate(params)

if err != nil {
return &MapStore{}, err
}

prefix := params["prefix"].(string)

delete(params, "prefix")

return &MapStore{
Client: make(map[string]interface{}),
Prefix: prefix,
}, nil
}

func (ac *MapConnector) validate(params map[string]interface{}) (map[string]interface{}, error) {
if _, ok := params["prefix"]; !ok {
return params, errors.New("You need to specify a caching prefix.")
}

return params, nil
}

0 comments on commit b422e2c

Please sign in to comment.