Skip to content

Commit

Permalink
Add PostgreSQL metadata repository
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Shishkin <me@teran.dev>
  • Loading branch information
teran committed Jul 7, 2024
1 parent 423de2c commit 0ec5f1d
Show file tree
Hide file tree
Showing 13 changed files with 776 additions and 1 deletion.
2 changes: 1 addition & 1 deletion repositories/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Repository interface {
MarkVersionPublished(ctx context.Context, container, version string) error

CreateObject(ctx context.Context, container, version, key, casKey string) error
ListObjects(ctx context.Context, container, version, key string) ([]string, error)
ListObjects(ctx context.Context, container, version string, offset, limit uint64) ([]string, error)
DeleteObject(ctx context.Context, container, version, key string) error
RemapObject(ctx context.Context, container, version, key, newCASKey string) error

Expand Down
26 changes: 26 additions & 0 deletions repositories/metadata/postgresql/blobs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package postgresql

import (
"context"

"github.com/pkg/errors"

Check failure on line 6 in repositories/metadata/postgresql/blobs.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/pkg/errors; to add it:
)

func (r *repository) CreateBLOB(ctx context.Context, checksum string, size uint64, mimeType string) error {
_, err := psql.
Insert("blobs").
Columns(
"checksum",
"size",
"mime_type",
).
Values(
checksum,
size,
mimeType,
).
RunWith(r.db).
ExecContext(ctx)

return errors.Wrap(err, "error executing SQL query")
}
6 changes: 6 additions & 0 deletions repositories/metadata/postgresql/blobs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package postgresql

func (s *postgreSQLRepositoryTestSuite) TestBlobs() {
err := s.repo.CreateBLOB(s.ctx, "deadbeef", 15, "text/plain")
s.Require().NoError(err)
}
58 changes: 58 additions & 0 deletions repositories/metadata/postgresql/containers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package postgresql

import (
"context"

sq "github.com/Masterminds/squirrel"

Check failure on line 6 in repositories/metadata/postgresql/containers.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/Masterminds/squirrel; to add it:
"github.com/pkg/errors"
)

func (r *repository) CreateContainer(ctx context.Context, name string) error {
_, err := psql.
Insert("containers").
Columns(
"name",
).
Values(
name,
).
RunWith(r.db).
ExecContext(ctx)

return errors.Wrap(err, "error executing SQL query")
}

func (r *repository) ListContainers(ctx context.Context) ([]string, error) {
rows, err := psql.
Select("name").
From("containers").
OrderBy("id").
RunWith(r.db).
QueryContext(ctx)
if err != nil {
return nil, errors.Wrap(err, "error executing SQL query")
}
defer rows.Close()

result := []string{}
for rows.Next() {
var r string
if err := rows.Scan(&r); err != nil {
return nil, errors.Wrap(err, "error decoding database result")
}

result = append(result, r)
}

return result, nil
}

func (r *repository) DeleteContainer(ctx context.Context, name string) error {
_, err := psql.
Delete("containers").
Where(sq.Eq{"name": name}).
RunWith(r.db).
ExecContext(ctx)

return errors.Wrap(err, "error executing SQL query")
}
36 changes: 36 additions & 0 deletions repositories/metadata/postgresql/containers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package postgresql

func (s *postgreSQLRepositoryTestSuite) TestContainerOperations() {
list, err := s.repo.ListContainers(s.ctx)
s.Require().NoError(err)
s.Require().Equal([]string{}, list)

err = s.repo.CreateContainer(s.ctx, "test-container")
s.Require().NoError(err)

err = s.repo.CreateContainer(s.ctx, "test-container2")
s.Require().NoError(err)

err = s.repo.CreateContainer(s.ctx, "test-container")
s.Require().Error(err)
s.Require().Equal(
`error executing SQL query: pq: duplicate key value violates unique constraint "containers_name_key"`,
err.Error(),
)

list, err = s.repo.ListContainers(s.ctx)
s.Require().NoError(err)
s.Require().Equal([]string{
"test-container",
"test-container2",
}, list)

err = s.repo.DeleteContainer(s.ctx, "test-container")
s.Require().NoError(err)

list, err = s.repo.ListContainers(s.ctx)
s.Require().NoError(err)
s.Require().Equal([]string{
"test-container2",
}, list)
}
37 changes: 37 additions & 0 deletions repositories/metadata/postgresql/migrations/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package migrations

import (
"database/sql"

migrate "github.com/golang-migrate/migrate/v4"

Check failure on line 6 in repositories/metadata/postgresql/migrations/migrations.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/golang-migrate/migrate/v4; to add it:
"github.com/golang-migrate/migrate/v4/database/postgres"

Check failure on line 7 in repositories/metadata/postgresql/migrations/migrations.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/golang-migrate/migrate/v4/database/postgres; to add it:
_ "github.com/golang-migrate/migrate/v4/source/file"

Check failure on line 8 in repositories/metadata/postgresql/migrations/migrations.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/golang-migrate/migrate/v4/source/file; to add it:
_ "github.com/lib/pq"

Check failure on line 9 in repositories/metadata/postgresql/migrations/migrations.go

View workflow job for this annotation

GitHub Actions / unittests

no required module provides package github.com/lib/pq; to add it:
"github.com/pkg/errors"
)

func MigrateUp(dsn string) error {
db, err := sql.Open("postgres", dsn)
if err != nil {
return errors.Wrap(err, "error opening database connection")
}
defer db.Close()

if err := db.Ping(); err != nil {
return errors.Wrap(err, "error pinging database")
}

driver, err := postgres.WithInstance(db, &postgres.Config{})
if err != nil {
return errors.Wrap(err, "error creating database instance")
}

m, err := migrate.NewWithDatabaseInstance(
"file://migrations/sql",
"postgres", driver)
if err != nil {
return errors.Wrap(err, "error creating migrator instance")
}

return errors.Wrap(m.Up(), "error migrating database")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
BEGIN;

CREATE TABLE containers (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);

CREATE TABLE versions (
id SERIAL PRIMARY KEY,
container_id INT NOT NULL,
name VARCHAR(64) NOT NULL,
is_published BOOLEAN NOT NULL
);

CREATE TABLE blobs (
id SERIAL PRIMARY KEY,
checksum CHAR(64) NOT NULL,
size INT NOT NULL,
mime_type VARCHAR(64) NOT NULL
);

CREATE TABLE objects (
id SERIAL PRIMARY KEY,
version_id INT NOT NULL,
key VARCHAR(255) NOT NULL,
blob_id INT NOT NULL
);

CREATE UNIQUE INDEX containers_name_key ON containers (name);

ALTER TABLE versions ADD FOREIGN KEY (container_id) REFERENCES containers (id);
CREATE UNIQUE INDEX versions_container_id_name_key ON versions (container_id, name);
CREATE INDEX versions_is_published_idx ON versions (is_published);

ALTER TABLE objects ADD FOREIGN KEY (version_id) REFERENCES versions (id);
CREATE UNIQUE INDEX objects_version_id_key_key ON objects (version_id, key);
CREATE INDEX objects_key_idx ON objects (key);
ALTER TABLE objects ADD FOREIGN KEY (blob_id) REFERENCES blobs (id);

CREATE UNIQUE INDEX blobs_checksum_key ON blobs (checksum);

COMMIT;
Loading

0 comments on commit 0ec5f1d

Please sign in to comment.