You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bog/infrastructure/sqlite/namespace/repository.go

205 lines
4.4 KiB
Go

package namespace
import (
"caj-larsson/bog/dataswamp/namespace"
"context"
"database/sql"
"github.com/mattn/go-sqlite3"
"time"
)
var _ = sqlite3.ErrError
type Repository struct {
db *sql.DB
}
func (r *Repository) migrate() error {
query := `
CREATE TABLE IF NOT EXISTS file_stats(
id INTEGER PRIMARY KEY,
num BIGINT NOT NULL,
size_b BIGINT NOT NULL
);`
_, err := r.db.Exec(query)
if err != nil {
return err
}
query = `
CREATE TABLE IF NOT EXISTS namespace(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
lastseen TEXT,
allowance_time BIGINT,
quota_kb BIGINT,
quota_usage_kb BIGINT,
usage_id BIGINT NOT NULL REFERENCES file_stats(Id),
download_id BIGINT NOT NULL REFERENCES file_stats(Id),
upload_id BIGINT NOT NULL REFERENCES file_stats(Id)
);`
_, err = r.db.Exec(query)
return err
}
func NewRepository(filename string) namespace.Repository {
db, err := sql.Open("sqlite3", filename)
if err != nil {
panic(err)
}
repo := Repository{
db: db,
}
repo.migrate()
return &repo
}
func (q *Queries) createFileStats(ctx context.Context, fstat namespace.FileStat) (int64, error) {
return q.CreateFileStats(ctx, CreateFileStatsParams{fstat.Num, fstat.SizeB})
}
func (r *Repository) Create(ns namespace.Namespace) (*namespace.Namespace, error) {
ctx := context.Background()
q := New(r.db)
u_id, err := q.createFileStats(ctx, ns.Usage)
if err != nil {
return nil, err
}
dl_id, err := q.createFileStats(ctx, ns.Download)
if err != nil {
return nil, err
}
ul_id, err := q.createFileStats(ctx, ns.Upload)
if err != nil {
return nil, err
}
ns.LastSeen = ns.LastSeen.Round(time.Microsecond)
p := CreateNamespaceParams{
Name: ns.Name,
Lastseen: ns.LastSeen.UnixMicro(),
AllowanceTime: sql.NullInt64{int64(ns.AllowanceDuration.Seconds()), true},
QuotaKb: sql.NullInt64{int64(ns.FileQuota.AllowanceKB), true},
QuotaUsageKb: sql.NullInt64{int64(ns.FileQuota.CurrentUsage), true},
UsageID: u_id,
DownloadID: dl_id,
UploadID: ul_id,
}
id, err := q.CreateNamespace(ctx, p)
if err != nil {
return nil, err
}
ns.ID = id
return &ns, nil
}
func (r *Repository) All() ([]namespace.Namespace, error) {
ctx := context.Background()
q := New(r.db)
rows, err := q.AllNamespaces(ctx)
if err != nil {
return nil, err
}
var all []namespace.Namespace
for _, row := range rows {
ns := namespace.Namespace{
row.ID,
row.Name,
time.UnixMicro(row.Lastseen),
time.Duration(row.AllowanceTime.Int64 * int64(time.Second)),
namespace.FileSizeQuota{row.QuotaKb.Int64, row.QuotaUsageKb.Int64},
namespace.FileStat{row.UNum, row.USizeB},
namespace.FileStat{row.DNum, row.DSizeB},
namespace.FileStat{row.UlNum, row.UlSizeB},
}
all = append(all, ns)
}
return all, nil
}
func (r *Repository) GetByName(name string) (*namespace.Namespace, error) {
ctx := context.Background()
q := New(r.db)
row, err := q.GetNamespaceByName(ctx, name)
if err != nil {
return nil, namespace.ErrNotExists
}
ns := namespace.Namespace{
row.ID,
row.Name,
time.UnixMicro(row.Lastseen),
time.Duration(row.AllowanceTime.Int64 * int64(time.Second)),
namespace.FileSizeQuota{row.QuotaKb.Int64, row.QuotaUsageKb.Int64},
namespace.FileStat{row.UNum, row.USizeB},
namespace.FileStat{row.DNum, row.DSizeB},
namespace.FileStat{row.UlNum, row.UlSizeB},
}
return &ns, nil
}
func (q *Queries) updateFileStat(ctx context.Context, id int64, fstat namespace.FileStat) error {
return q.UpdateFileStat(ctx, UpdateFileStatParams{fstat.Num, fstat.SizeB, id})
}
func (r *Repository) Update(id int64, ns namespace.Namespace) (*namespace.Namespace, error) {
ctx := context.Background()
q := New(r.db)
ids, err := q.UpdateNamespace(ctx, UpdateNamespaceParams{
ns.Name,
ns.LastSeen.Round(time.Microsecond).UnixMicro(),
sql.NullInt64{int64(ns.AllowanceDuration.Seconds()), true},
sql.NullInt64{int64(ns.FileQuota.AllowanceKB), true},
sql.NullInt64{int64(ns.FileQuota.CurrentUsage), true},
ns.ID,
})
err = q.updateFileStat(ctx, ids.UsageID, ns.Usage)
if err != nil {
return nil, err
}
err = q.updateFileStat(ctx, ids.DownloadID, ns.Download)
if err != nil {
return nil, err
}
err = q.updateFileStat(ctx, ids.UploadID, ns.Upload)
if err != nil {
return nil, err
}
return &ns, nil
}
func (r *Repository) Delete(id int64) error {
ctx := context.Background()
q := New(r.db)
err := q.DeleteNameSpace(ctx, id)
if err != nil {
return namespace.ErrDeleteFailed
}
return nil
}