1
0
mirror of https://github.com/lus/pasty.git synced 2023-08-10 21:13:09 +03:00

Implement working postgres driver

This commit is contained in:
Lukas Schulte Pelkum
2021-04-15 21:30:37 +02:00
parent ce9794b2c6
commit a1d037801c
6 changed files with 914 additions and 11 deletions

View File

@ -1,13 +1,13 @@
package storage
import (
"errors"
"fmt"
"github.com/lus/pasty/internal/config"
"github.com/lus/pasty/internal/shared"
"github.com/lus/pasty/internal/storage/file"
"github.com/lus/pasty/internal/storage/mongodb"
"github.com/lus/pasty/internal/storage/postgres"
"github.com/lus/pasty/internal/storage/s3"
)
@ -48,8 +48,7 @@ func GetDriver(storageType shared.StorageType) (Driver, error) {
case shared.StorageTypeFile:
return new(file.FileDriver), nil
case shared.StorageTypePostgres:
// TODO: Implement Postgres driver
return nil, errors.New("TODO")
return new(postgres.PostgresDriver), nil
case shared.StorageTypeMongoDB:
return new(mongodb.MongoDBDriver), nil
case shared.StorageTypeS3:

View File

@ -0,0 +1,5 @@
begin;
drop table if exists "pastes";
commit;

View File

@ -0,0 +1,12 @@
begin;
create table if not exists "pastes" (
"id" text not null,
"content" text not null,
"deletionToken" text not null,
"created" bigint not null,
"autoDelete" boolean not null,
primary key ("id")
);
commit;

View File

@ -0,0 +1,119 @@
package postgres
import (
"context"
"embed"
"errors"
"time"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/johejo/golang-migrate-extra/source/iofs"
"github.com/lus/pasty/internal/config"
"github.com/lus/pasty/internal/shared"
)
//go:embed migrations/*.sql
var migrations embed.FS
// PostgresDriver represents the Postgres storage driver
type PostgresDriver struct {
pool *pgxpool.Pool
}
// Initialize initializes the Postgres storage driver
func (driver *PostgresDriver) Initialize() error {
pool, err := pgxpool.Connect(context.Background(), config.Current.Postgres.DSN)
if err != nil {
return err
}
source, err := iofs.New(migrations, "migrations")
if err != nil {
return err
}
migrator, err := migrate.NewWithSourceInstance("iofs", source, config.Current.Postgres.DSN)
if err != nil {
return err
}
if err := migrator.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return err
}
driver.pool = pool
return nil
}
// Terminate terminates the Postgres storage driver
func (driver *PostgresDriver) Terminate() error {
driver.pool.Close()
return nil
}
// ListIDs returns a list of all existing paste IDs
func (driver *PostgresDriver) ListIDs() ([]string, error) {
query := "SELECT id FROM pastes"
rows, err := driver.pool.Query(context.Background(), query)
if err != nil {
return []string{}, err
}
var ids []string
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
return []string{}, err
}
ids = append(ids, id)
}
return ids, nil
}
// Get loads a paste
func (driver *PostgresDriver) Get(id string) (*shared.Paste, error) {
query := "SELECT * FROM pastes WHERE id = $1"
row := driver.pool.QueryRow(context.Background(), query, id)
paste := new(shared.Paste)
if err := row.Scan(&paste.ID, &paste.Content, &paste.DeletionToken, &paste.Created, &paste.AutoDelete); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
return nil, err
}
return paste, nil
}
// Save saves a paste
func (driver *PostgresDriver) Save(paste *shared.Paste) error {
query := "INSERT INTO pastes VALUES ($1, $2, $3, $4, $5)"
_, err := driver.pool.Exec(context.Background(), query, paste.ID, paste.Content, paste.DeletionToken, paste.Created, paste.AutoDelete)
return err
}
// Delete deletes a paste
func (driver *PostgresDriver) Delete(id string) error {
query := "DELETE FROM pastes WHERE id = $1"
_, err := driver.pool.Exec(context.Background(), query, id)
return err
}
// Cleanup cleans up the expired pastes
func (driver *PostgresDriver) Cleanup() (int, error) {
query := "DELETE FROM pastes WHERE autoDelete = true AND created < $2"
tag, err := driver.pool.Exec(context.Background(), query, time.Now().Add(-config.Current.AutoDelete.Lifetime).Unix())
if err != nil {
return 0, err
}
return int(tag.RowsAffected()), nil
}