// Basic in-memory object store // // Licensed under CC0 1.0 Universal: // https://creativecommons.org/publicdomain/zero/1.0/legalcode package objectstore import ( "errors" "fmt" "io/ioutil" "os" "path" "sync" ) type FileObjectStore struct { sync.Mutex dataPath string } func NewFileBackend(dataPath string) *FileObjectStore { err := os.MkdirAll(dataPath, 0755) if err != nil { panic(err) } fos := &FileObjectStore{dataPath: dataPath} return fos } func (fos *FileObjectStore) CreateObject(bucketId string, objectId string, payload []byte) error { fos.Lock() defer fos.Unlock() // Check if the bucket exists buckets, err := ioutil.ReadDir(fos.dataPath) if err != nil { return fmt.Errorf("Error reading data directory") } bucketFound := false for _, f := range buckets { if f.Name() == bucketId && f.IsDir() { bucketFound = true break } } // Create bucket if it doesn't exist if !bucketFound { err := os.Mkdir(path.Join(fos.dataPath, bucketId), 0755) if err != nil { return fmt.Errorf("Error creating bucket directory: %v", bucketId) } } // Store the object err = os.WriteFile(path.Join(fos.dataPath, bucketId, objectId), payload, 0644) if err != nil { return fmt.Errorf("Error creating the object file %v", bucketId) } return nil } func (fos *FileObjectStore) GetObject(bucketId string, objectId string) (string, error) { fos.Lock() defer fos.Unlock() objectPath := path.Join(fos.dataPath, bucketId, objectId) object, err := os.ReadFile(objectPath) if err != nil { return "", os.ErrNotExist } return string(object), nil } func (fos *FileObjectStore) DeleteObject(bucketId string, objectId string) error { fos.Lock() defer fos.Unlock() objectPath := path.Join(fos.dataPath, bucketId, objectId) // Check whether the file exists _, err := os.Stat(objectPath) if errors.Is(err, os.ErrNotExist) { return err } // Delete file err = os.Remove(objectPath) if err != nil { return err } // Delete the bucket directory if it's empty bucketPath := path.Join(fos.dataPath, bucketId) entries, err := ioutil.ReadDir(bucketPath) if err != nil { fmt.Println(err) } if len(entries) == 0 { err := os.Remove(bucketPath) if err != nil { fmt.Println(err) } } return nil }