mirror of https://github.com/aldy505/cheapcash.git
commit
5ee43946ea
12
README.md
12
README.md
|
@ -4,6 +4,12 @@
|
|||
|
||||
SSD is cheap. Why don't we use it for caching?
|
||||
|
||||
A simple library implementing filesystem I/O as a cache. Should be must useful when used again a Solid State Drive
|
||||
for maximum speed and to handle good amount of concurrent read/write.
|
||||
|
||||
The API itself is also pretty simple considering I don't want this to be a full-blown caching library like Redis,
|
||||
I just want it to be simple like Bigcache or similar caching library.
|
||||
|
||||
## Install
|
||||
|
||||
```go
|
||||
|
@ -55,3 +61,9 @@ func main() {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
See Godoc documentation (link above, beneath the title) for more complete documentation of the package.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
|
|
13
append.go
13
append.go
|
@ -2,6 +2,19 @@ package cheapcash
|
|||
|
||||
import "os"
|
||||
|
||||
// Directly append a value into an existing key.
|
||||
// If a key doesn't exists, it will return an error
|
||||
// with a type of ErrNotExists.
|
||||
//
|
||||
// c := cheapcash.Default()
|
||||
// err := c.Append("users", []byte("Someone\n"))
|
||||
// if err != nil {
|
||||
// if errors.Is(err, cheapcash.ErrNotExists) {
|
||||
// // Handle if file does not exists!
|
||||
// }
|
||||
// // Handle any other errors
|
||||
// }
|
||||
//
|
||||
func (c *Cache) Append(key string, value []byte) error {
|
||||
check, err := c.Exists(c.Path + key)
|
||||
if err != nil {
|
||||
|
|
27
cheapcash.go
27
cheapcash.go
|
@ -17,13 +17,40 @@ var ErrInvalidPath = errors.New("path supplied is invalid")
|
|||
var ErrDiskFull = errors.New("there was no space left on the device")
|
||||
var ErrExists = errors.New("key already exists")
|
||||
|
||||
// Creates default Cheapcash instance which defaults
|
||||
// the corresponding cache path to /tmp/cheapcash.
|
||||
//
|
||||
// The caveat of using this one is this will be most likely
|
||||
// only compatible with UNIX-like filesystem.
|
||||
// Windows devices will most likely happen to have
|
||||
// an error of the invalid path.
|
||||
//
|
||||
// This returns a Cheapcash instance, which method
|
||||
// ('Append', 'Exists', 'Write', 'Read') you can do
|
||||
// by just specifying the key, without supplying the
|
||||
// full path of the cached file.
|
||||
func Default() *Cache {
|
||||
return &Cache{
|
||||
Path: "/tmp/cheapcash/",
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new Cheapcash instance with the given
|
||||
// path from the argument provided.
|
||||
//
|
||||
// If path is empty (or an empty string), it will panic
|
||||
// with ErrInvalidPath error.
|
||||
//
|
||||
// The path provided might have '/' as the ending, so
|
||||
// these are valid and will return the same path:
|
||||
//
|
||||
// New("/tmp/box")
|
||||
// New("/tmp/box/")
|
||||
func New(path string) *Cache {
|
||||
if path == "" {
|
||||
panic(ErrInvalidPath)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, "/") {
|
||||
path += "/"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cheapcash_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -29,6 +30,19 @@ func TestNew(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNew_InvalidPath(t *testing.T) {
|
||||
defer func(){
|
||||
if e := recover().(error); e != nil {
|
||||
if !errors.Is(e, cheapcash.ErrInvalidPath) {
|
||||
t.Error("expected ErrInvalidPath, got:", e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
_ = cheapcash.New("")
|
||||
|
||||
}
|
||||
|
||||
func removeDirIfExists(path string) {
|
||||
dir, err := os.Stat(path)
|
||||
if err == nil {
|
||||
|
|
7
check.go
7
check.go
|
@ -31,6 +31,13 @@ func (c *Cache) Exists(key string) (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// Will validate the existance of a directory.
|
||||
// If the directory (including its' children) doesn't
|
||||
// exists, it will create the corresponding directory
|
||||
// tree from the given directory path.
|
||||
//
|
||||
// If the directory already exists, it will return
|
||||
// a nil value.
|
||||
func checkDir(path string) error {
|
||||
// Remove / from path
|
||||
path = strings.TrimSuffix(path, "/")
|
||||
|
|
10
delete.go
10
delete.go
|
@ -2,6 +2,16 @@ package cheapcash
|
|||
|
||||
import "os"
|
||||
|
||||
// Delete a key from the cache directory.
|
||||
// And of course would return an error of ErrNotExists
|
||||
// if the key doesn't exists.
|
||||
//
|
||||
// c := cheapcash.Default()
|
||||
// err := c.Write("users", []byte("Someone\n"))
|
||||
// // Handle error here
|
||||
// err = c.Delete("users")
|
||||
// // Handle error here
|
||||
//
|
||||
func (c *Cache) Delete(key string) error {
|
||||
check, err := c.Exists(c.Path + key)
|
||||
if err != nil {
|
||||
|
|
11
reader.go
11
reader.go
|
@ -5,6 +5,17 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
// Read the value of a given key.
|
||||
// Will return an error of ErrNotExists if the given
|
||||
// key does not exists.
|
||||
//
|
||||
// c := cheapcash.Default()
|
||||
// res, err := c.Read("users")
|
||||
// if err != nil {
|
||||
// // handle your error here!
|
||||
// }
|
||||
// log.Println(string(res))
|
||||
//
|
||||
func (c *Cache) Read(key string) ([]byte, error) {
|
||||
check, err := c.Exists(c.Path + key)
|
||||
if err != nil {
|
||||
|
|
11
rename.go
11
rename.go
|
@ -2,6 +2,17 @@ package cheapcash
|
|||
|
||||
import "os"
|
||||
|
||||
// Rename a key. It's that simple.
|
||||
// The contents of the cache stays the same, but the key
|
||||
// is renamed.
|
||||
//
|
||||
// It will return 2 different error in case of:
|
||||
//
|
||||
// 1. If the old key (first argument parameter) doesn't exists,
|
||||
// it will return an error of ErrNotExists
|
||||
//
|
||||
// 2. If the new key (second argument parameter) already exists,
|
||||
// it will return an error of ErrExists
|
||||
func (c *Cache) Rename(old, new string) error {
|
||||
err := checkDir(sanitizePath(c.Path))
|
||||
if err != nil {
|
||||
|
|
|
@ -7,6 +7,9 @@ type restriction struct {
|
|||
ReplaceWith string
|
||||
}
|
||||
|
||||
// Sanitize path that is a valid string when the user
|
||||
// submitted it, but it's invalid when it's written
|
||||
// as a file name on local filesystem.
|
||||
func sanitizePath(path string) string {
|
||||
restricted := []restriction{
|
||||
{Key: " ", ReplaceWith: "_s_"},
|
||||
|
|
11
writer.go
11
writer.go
|
@ -2,6 +2,17 @@ package cheapcash
|
|||
|
||||
import "os"
|
||||
|
||||
// Write a key with a value.
|
||||
// If the key already exists in the first place, it will
|
||||
// delete the existing key and replace it with the new
|
||||
// value.
|
||||
//
|
||||
// c := cheapcash.Default()
|
||||
// err := c.Write("users", []byte("Someone\n"))
|
||||
// if err != nil {
|
||||
// // handle your error
|
||||
// }
|
||||
//
|
||||
func (c *Cache) Write(key string, value []byte) error {
|
||||
err := checkDir(sanitizePath(c.Path))
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue