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 }