package storage import ( "bytes" "io/ioutil" "net/url" "sort" "strings" minio "github.com/minio/minio-go/v6" ) type Minio struct { db *minio.Client } func NewMinio(addr, user, pass string) (*Minio, error) { url, err := url.Parse(addr) if err != nil { return nil, err } addr = strings.TrimPrefix(addr, url.Scheme+"://") db, err := minio.New(addr, user, pass, url.Scheme == "https") return &Minio{db: db}, err } func (m *Minio) List(ns []string, limits ...string) ([]string, error) { namespace := resolveNamespace(ns) limits = resolveLimits(limits) done := make(chan struct{}) defer close(done) keys := []string{} prefix := commonSubstr(limits[:2]) for resp := range m.db.ListObjects(namespace, prefix, true, done) { if resp.Err != nil { return keys, resp.Err } if resp.Key < limits[0] { continue } else if resp.Key > limits[1] { break } keys = append(keys, resp.Key) } return keys, nil } func (m *Minio) Get(key string, ns ...string) ([]byte, error) { namespace := resolveNamespace(ns) obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{}) if err == nil { var stat minio.ObjectInfo if stat, err = obj.Stat(); err == nil { err = stat.Err } } if isNotExistErr(err) { return nil, ErrNotFound } else if err != nil { return nil, err } return ioutil.ReadAll(obj) } func (m *Minio) Set(key string, value []byte, ns ...string) error { namespace := resolveNamespace(ns) if ok, err := m.db.BucketExists(namespace); err != nil { return err } else if !ok { if err := m.db.MakeBucket(namespace, ""); err != nil { return err } } _, err := m.db.PutObject(namespace, key, bytes.NewBuffer(value), int64(len(value)), minio.PutObjectOptions{}) return err } func (m *Minio) Close() error { m.db = nil return nil } func isNotExistErr(err error) bool { return err != nil && strings.Contains(err.Error(), "does not exist") } func commonSubstr(items []string) string { if len(items) == 0 { return "" } else if len(items) == 1 { return items[0] } sort.Strings(items) min := items[0] max := items[len(items)-1] if len(min) == 0 || len(max) == 0 { return "" } if min[0] != max[0] { return "" } for i := 1; i < len(min) && i < len(max); i++ { if min[i] != max[i] { return min[:i-1] } } return min }