From 6011123ab16a4d1b329e51c32cb51ba338a2edc0 Mon Sep 17 00:00:00 2001 From: Lukas SP Date: Sun, 23 Aug 2020 00:06:29 +0200 Subject: [PATCH] Implement file storage driver --- cmd/pasty/main.go | 23 ++++++++++- internal/storage/driver.go | 38 ++++++++++++++++++ internal/storage/file_driver.go | 69 +++++++++++++++++++++++++++++++++ internal/storage/storage.go | 14 ------- 4 files changed, 129 insertions(+), 15 deletions(-) create mode 100644 internal/storage/driver.go create mode 100644 internal/storage/file_driver.go delete mode 100644 internal/storage/storage.go diff --git a/cmd/pasty/main.go b/cmd/pasty/main.go index 7a3bb74..94d38dc 100644 --- a/cmd/pasty/main.go +++ b/cmd/pasty/main.go @@ -1,8 +1,29 @@ package main -import "github.com/Lukaesebrot/pasty/internal/env" +import ( + "github.com/Lukaesebrot/pasty/internal/env" + "github.com/Lukaesebrot/pasty/internal/storage" + "log" + "os" + "os/signal" + "syscall" +) func main() { // Load the optional .env file + log.Println("Loading the optional .env file...") env.Load() + + // Load the configured storage driver + log.Println("Loading the configured storage driver...") + err := storage.Load() + if err != nil { + panic(err) + } + + // Wait for the program to exit + // TODO: Replace this through blocking API server + sc := make(chan os.Signal, 1) + signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) + <-sc } diff --git a/internal/storage/driver.go b/internal/storage/driver.go new file mode 100644 index 0000000..014c725 --- /dev/null +++ b/internal/storage/driver.go @@ -0,0 +1,38 @@ +package storage + +import ( + "fmt" + "github.com/Lukaesebrot/pasty/internal/env" + "github.com/Lukaesebrot/pasty/internal/pastes" + "github.com/bwmarrin/snowflake" + "strings" +) + +// Current holds the current storage driver +var Current Driver + +// Driver represents a storage driver +type Driver interface { + Initialize() error + Terminate() error + Get(id snowflake.ID) (*pastes.Paste, error) + Save(paste *pastes.Paste) error + Delete(id snowflake.ID) error +} + +// Load loads the current storage driver +func Load() error { + storageType := strings.ToLower(env.Get("STORAGE_TYPE", "file")) + switch storageType { + case "file": + driver := new(FileDriver) + err := driver.Initialize() + if err != nil { + return err + } + Current = driver + return nil + default: + return fmt.Errorf("invalid storage type '%s'", storageType) + } +} diff --git a/internal/storage/file_driver.go b/internal/storage/file_driver.go new file mode 100644 index 0000000..310af97 --- /dev/null +++ b/internal/storage/file_driver.go @@ -0,0 +1,69 @@ +package storage + +import ( + "encoding/json" + "github.com/Lukaesebrot/pasty/internal/env" + "github.com/Lukaesebrot/pasty/internal/pastes" + "github.com/bwmarrin/snowflake" + "io/ioutil" + "os" + "path/filepath" +) + +// FileDriver represents the file storage driver +type FileDriver struct { + FilePath string +} + +// Initialize initializes the file storage driver +func (driver *FileDriver) Initialize() error { + driver.FilePath = env.Get("STORAGE_FILE_PATH", "./data") + return os.MkdirAll(driver.FilePath, os.ModePerm) +} + +// Terminate terminates the file storage driver (does nothing, because the file storage driver does not need any termination) +func (driver *FileDriver) Terminate() error { + return nil +} + +// Get loads a paste out of a file +func (driver *FileDriver) Get(id snowflake.ID) (*pastes.Paste, error) { + // Read the file + data, err := ioutil.ReadFile(filepath.Join(driver.FilePath, id.String()+".json")) + if err != nil { + return nil, err + } + + // Unmarshal the file into a paste + paste := new(pastes.Paste) + err = json.Unmarshal(data, &paste) + if err != nil { + return nil, err + } + return paste, nil +} + +// Save saves a paste into a file +func (driver *FileDriver) Save(paste *pastes.Paste) error { + // Marshal the paste + jsonBytes, err := json.Marshal(paste) + if err != nil { + return err + } + + // Create the file to save the paste to + file, err := os.Create(filepath.Join(driver.FilePath, paste.ID.String()+".json")) + if err != nil { + return err + } + defer file.Close() + + // Write the JSON data into the file + _, err = file.Write(jsonBytes) + return err +} + +// Delete deletes a paste +func (driver *FileDriver) Delete(id snowflake.ID) error { + return os.Remove(filepath.Join(driver.FilePath, id.String()+".json")) +} diff --git a/internal/storage/storage.go b/internal/storage/storage.go deleted file mode 100644 index 4b6d448..0000000 --- a/internal/storage/storage.go +++ /dev/null @@ -1,14 +0,0 @@ -package storage - -import ( - "github.com/Lukaesebrot/pasty/internal/pastes" - "github.com/bwmarrin/snowflake" -) - -// Storage represents a storage type -type Storage interface { - initialize() error - get(id snowflake.ID) (*pastes.Paste, error) - save(paste *pastes.Paste) error - delete(id snowflake.ID) error -}