Skip to main content
Glama

Storyden

by Southclaws
Mozilla Public License 2.0
227
s3.go2.59 kB
package object import ( "context" "io" "log" "github.com/Southclaws/fault" "github.com/Southclaws/fault/fctx" "github.com/Southclaws/fault/ftag" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/Southclaws/storyden/internal/config" ) // DefaultPartSize is the default part size for multipart uploads to S3. This is // used only when the content size is unknown and is a low value for small VMs. const DefaultPartSize = 1024 * 1024 * 8 type s3Storer struct { bucket string minioClient *minio.Client } func NewS3Storer(ctx context.Context, cfg config.Config) (Storer, error) { minioClient, err := minio.New(cfg.S3Endpoint, &minio.Options{ Creds: credentials.NewStaticV4(cfg.S3AccessKey, cfg.S3SecretKey, ""), Region: cfg.S3Region, Secure: cfg.S3Secure, }) if err != nil { log.Fatalln(err) } exists, err := minioClient.BucketExists(ctx, cfg.S3Bucket) if err != nil { return nil, err } if !exists { err := minioClient.MakeBucket(ctx, cfg.S3Bucket, minio.MakeBucketOptions{}) if err != nil { return nil, err } } return &s3Storer{ bucket: cfg.S3Bucket, minioClient: minioClient, }, nil } func (s *s3Storer) Exists(ctx context.Context, path string) (bool, error) { _, err := s.minioClient.StatObject(ctx, s.bucket, path, minio.GetObjectOptions{}) if err != nil { // TODO: figure out if there's a way to differentiate between an error // and an item just not existing. Ideally we want to treat actual // transport errors and such as actual errors and non-existence as nil. return false, fault.Wrap(err, fctx.With(ctx)) } return true, nil } func (s *s3Storer) Read(ctx context.Context, path string) (io.Reader, int64, error) { obj, err := s.minioClient.GetObject(ctx, s.bucket, path, minio.GetObjectOptions{}) if err != nil { return nil, 0, fault.Wrap(err, fctx.With(ctx)) } info, err := obj.Stat() if err != nil { if minio.ToErrorResponse(err).StatusCode == 404 { return nil, 0, fault.Wrap(err, fctx.With(ctx), ftag.With(ftag.NotFound)) } return nil, 0, fault.Wrap(err, fctx.With(ctx)) } return obj, info.Size, nil } func (s *s3Storer) Write(ctx context.Context, path string, stream io.Reader, size int64) error { opts := minio.PutObjectOptions{} if size <= 0 { // If size is unknown Minio needs to compute an md5 hash of the content. opts.SendContentMd5 = true opts.PartSize = DefaultPartSize } _, err := s.minioClient.PutObject(ctx, s.bucket, path, stream, size, opts) if err != nil { return fault.Wrap(err, fctx.With(ctx)) } return nil }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Southclaws/storyden'

If you have feedback or need assistance with the MCP directory API, please join our Discord server