From a533c965513fe4af58a876b187208025a21af310 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Fri, 19 Nov 2021 17:55:31 +0700 Subject: [PATCH 1/2] docs: added documentations --- README.md | 12 ++++++++++++ append.go | 13 +++++++++++++ cheapcash.go | 27 +++++++++++++++++++++++++++ check.go | 7 +++++++ delete.go | 10 ++++++++++ reader.go | 11 +++++++++++ rename.go | 11 +++++++++++ sanitize.go | 3 +++ writer.go | 11 +++++++++++ 9 files changed, 105 insertions(+) diff --git a/README.md b/README.md index 7c69041..22897be 100644 --- a/README.md +++ b/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) diff --git a/append.go b/append.go index 2f18c14..74f8b49 100644 --- a/append.go +++ b/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 { diff --git a/cheapcash.go b/cheapcash.go index f7b36e6..956d8ef 100644 --- a/cheapcash.go +++ b/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 += "/" } diff --git a/check.go b/check.go index 1916623..f9e7563 100644 --- a/check.go +++ b/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, "/") diff --git a/delete.go b/delete.go index f5e2c7f..c82d467 100644 --- a/delete.go +++ b/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 { diff --git a/reader.go b/reader.go index 43c861d..97c55b3 100644 --- a/reader.go +++ b/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 { diff --git a/rename.go b/rename.go index 31e3717..c85b29b 100644 --- a/rename.go +++ b/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 { diff --git a/sanitize.go b/sanitize.go index c981c5c..cb6bf6a 100644 --- a/sanitize.go +++ b/sanitize.go @@ -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_"}, diff --git a/writer.go b/writer.go index 69787d1..2438dd9 100644 --- a/writer.go +++ b/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 { From f199ca0c86a2aca80883bb461999222ddf5e7784 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Fri, 19 Nov 2021 18:00:40 +0700 Subject: [PATCH 2/2] test: panic on new --- cheapcash_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cheapcash_test.go b/cheapcash_test.go index e257fec..7c5760b 100644 --- a/cheapcash_test.go +++ b/cheapcash_test.go @@ -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 {