Files
llink/go/internal/depot/repository.go
T
2026-02-21 08:48:34 -08:00

113 lines
3.0 KiB
Go

package depot
import (
"context"
"errors"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"go.jetify.com/typeid"
)
var errNotFound = errors.New("not found")
type depotIDPrefix struct{}
func (depotIDPrefix) Prefix() string { return "dpo" }
type depotID struct {
typeid.TypeID[depotIDPrefix]
}
func newDepotID() (depotID, error) {
return typeid.New[depotID]()
}
type repository interface {
create(ctx context.Context, obj *Object) (*Object, error)
getByID(ctx context.Context, id string) (*Object, error)
setContainsContent(ctx context.Context, id string, containsContent bool) error
delete(ctx context.Context, id string) error
exists(ctx context.Context, id string) (bool, error)
}
type repositoryImpl struct {
pool *pgxpool.Pool
}
func newRepository(pool *pgxpool.Pool) repository {
return &repositoryImpl{pool: pool}
}
func (r *repositoryImpl) create(ctx context.Context, obj *Object) (*Object, error) {
id, err := newDepotID()
if err != nil {
return nil, err
}
var result Object
err = r.pool.QueryRow(ctx,
`INSERT INTO depot_objects (id, name, content_type, content_length, bucket_name, object_key, contains_content)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, name, content_type, content_length, bucket_name, object_key, contains_content, created_at`,
id.String(), obj.Name, obj.ContentType, obj.ContentLength, obj.BucketName, obj.ObjectKey, obj.ContainsContent,
).Scan(&result.ID, &result.Name, &result.ContentType, &result.ContentLength,
&result.BucketName, &result.ObjectKey, &result.ContainsContent, &result.CreatedAt)
if err != nil {
return nil, err
}
return &result, nil
}
func (r *repositoryImpl) getByID(ctx context.Context, id string) (*Object, error) {
var obj Object
err := r.pool.QueryRow(ctx,
`SELECT id, name, content_type, content_length, bucket_name, object_key, contains_content, created_at
FROM depot_objects WHERE id = $1`,
id,
).Scan(&obj.ID, &obj.Name, &obj.ContentType, &obj.ContentLength,
&obj.BucketName, &obj.ObjectKey, &obj.ContainsContent, &obj.CreatedAt)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, errNotFound
}
return nil, err
}
return &obj, nil
}
func (r *repositoryImpl) setContainsContent(ctx context.Context, id string, containsContent bool) error {
result, err := r.pool.Exec(ctx,
`UPDATE depot_objects SET contains_content = $1 WHERE id = $2`,
containsContent, id,
)
if err != nil {
return err
}
if result.RowsAffected() == 0 {
return errNotFound
}
return nil
}
func (r *repositoryImpl) delete(ctx context.Context, id string) error {
result, err := r.pool.Exec(ctx, `DELETE FROM depot_objects WHERE id = $1`, id)
if err != nil {
return err
}
if result.RowsAffected() == 0 {
return errNotFound
}
return nil
}
func (r *repositoryImpl) exists(ctx context.Context, id string) (bool, error) {
var exists bool
err := r.pool.QueryRow(ctx,
`SELECT EXISTS(SELECT 1 FROM depot_objects WHERE id = $1)`,
id,
).Scan(&exists)
return exists, err
}