Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions pkg/datastore/memory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package datastore

import (
"context"
"fmt"
"log/slog"
"sync"
"time"

v1 "github.com/metal-stack/masterdata-api/api/v1"
)

type memoryDatastore[E Entity] struct {
lock sync.RWMutex
entities map[string]E
entity string
log *slog.Logger
}

func NewMemory[E Entity](log *slog.Logger, e E) Storage[E] {
entity := e.JSONField()
return &memoryDatastore[E]{
lock: sync.RWMutex{},
entities: make(map[string]E),
entity: entity,
log: log,
}
}

// Create implements Storage.
func (m *memoryDatastore[E]) Create(ctx context.Context, ve E) error {
m.log.Debug("create", "entity", m.entity, "value", ve)
meta := ve.GetMeta()
if meta == nil {
return fmt.Errorf("create of type:%s failed, meta is nil", m.entity)
}

id := ve.GetMeta().Id
m.lock.Lock()
defer m.lock.Unlock()

_, ok := m.entities[id]
if ok {
return NewDuplicateKeyError(fmt.Sprintf("an entity of type:%s with the id:%s already exists", m.entity, id))
}
m.entities[id] = ve
return nil
}

// Delete implements Storage.
func (m *memoryDatastore[E]) Delete(ctx context.Context, id string) error {
m.log.Debug("delete", "entity", m.entity, "id", id)

m.lock.Lock()
defer m.lock.Unlock()

_, ok := m.entities[id]
if !ok {
return NewNotFoundError(fmt.Sprintf("not found: delete of %s with id %s", m.entity, id))
}
delete(m.entities, id)

return nil
}

// DeleteAll implements Storage.
func (m *memoryDatastore[E]) DeleteAll(ctx context.Context, ids ...string) error {
panic("unimplemented")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to implement this? Should be fairly easy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

// Find implements Storage.
func (m *memoryDatastore[E]) Find(ctx context.Context, filter map[string]any, paging *v1.Paging) ([]E, *uint64, error) {
m.log.Debug("find", "entity", m.entity, "filter", filter)

m.lock.Lock()
defer m.lock.Unlock()

var result []E
for _, e := range m.entities {
// FIXME implement filtering
result = append(result, e)
}

return result, nil, nil
}

// Get implements Storage.
func (m *memoryDatastore[E]) Get(ctx context.Context, id string) (E, error) {
m.log.Debug("get", "entity", m.entity, "id", id)
var zero E
m.lock.Lock()
defer m.lock.Unlock()

e, ok := m.entities[id]
if !ok {
return zero, NewNotFoundError(fmt.Sprintf("not found: delete of %s with id %s", m.entity, id))
}

return e, nil
}

// GetHistory implements Storage.
func (m *memoryDatastore[E]) GetHistory(ctx context.Context, id string, at time.Time, ve E) error {
panic("unimplemented")
}

// GetHistoryCreated implements Storage.
func (m *memoryDatastore[E]) GetHistoryCreated(ctx context.Context, id string, ve E) error {
panic("unimplemented")
}

// Update implements Storage.
func (m *memoryDatastore[E]) Update(ctx context.Context, ve E) error {
m.log.Debug("update", "entity", m.entity)
meta := ve.GetMeta()
if meta == nil {
return fmt.Errorf("update of type:%s failed, meta is nil", m.entity)
}
id := ve.GetMeta().Id
m.lock.Lock()
defer m.lock.Unlock()

_, ok := m.entities[id]
if !ok {
return NewNotFoundError(fmt.Sprintf("not found: delete of %s with id %s", m.entity, id))
}

m.entities[id] = ve
return nil
}
12 changes: 4 additions & 8 deletions pkg/service/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"log/slog"

"github.com/jmoiron/sqlx"
v1 "github.com/metal-stack/masterdata-api/api/v1"
"github.com/metal-stack/masterdata-api/pkg/datastore"
"google.golang.org/grpc/codes"
Expand All @@ -19,14 +18,11 @@ type projectService struct {
log *slog.Logger
}

func NewProjectService(db *sqlx.DB, l *slog.Logger) *projectService {
ps := datastore.New(l, db, &v1.Project{})
ts := datastore.New(l, db, &v1.Tenant{})
pms := datastore.New(l, db, &v1.ProjectMember{})
func NewProjectService(l *slog.Logger, pds ProjectDataStore, pmds ProjectMemberDataStore, tds TenantDataStore) *projectService {
return &projectService{
projectStore: NewStorageStatusWrapper(ps),
projectMemberStore: NewStorageStatusWrapper(pms),
tenantStore: NewStorageStatusWrapper(ts),
projectStore: NewStorageStatusWrapper(pds),
projectMemberStore: NewStorageStatusWrapper(pmds),
tenantStore: NewStorageStatusWrapper(tds),
log: l,
}
}
Expand Down
12 changes: 4 additions & 8 deletions pkg/service/projectmember.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"log/slog"

"github.com/jmoiron/sqlx"
v1 "github.com/metal-stack/masterdata-api/api/v1"
"github.com/metal-stack/masterdata-api/pkg/datastore"
"google.golang.org/grpc/codes"
Expand All @@ -19,14 +18,11 @@ type projectMemberService struct {
log *slog.Logger
}

func NewProjectMemberService(db *sqlx.DB, l *slog.Logger) *projectMemberService {
pms := datastore.New(l, db, &v1.ProjectMember{})
ts := datastore.New(l, db, &v1.Tenant{})
ps := datastore.New(l, db, &v1.Project{})
func NewProjectMemberService(l *slog.Logger, pds ProjectDataStore, pmds ProjectMemberDataStore, tds TenantDataStore) *projectMemberService {
return &projectMemberService{
projectMemberStore: NewStorageStatusWrapper(pms),
tenantStore: NewStorageStatusWrapper(ts),
projectStore: NewStorageStatusWrapper(ps),
projectMemberStore: NewStorageStatusWrapper(pmds),
tenantStore: NewStorageStatusWrapper(tds),
projectStore: NewStorageStatusWrapper(pds),
log: l,
}
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import (
"google.golang.org/grpc/status"
)

type (
ProjectDataStore datastore.Storage[*v1.Project]
ProjectMemberDataStore datastore.Storage[*v1.ProjectMember]
TenantDataStore datastore.Storage[*v1.Tenant]
TenantMemberDataStore datastore.Storage[*v1.TenantMember]
)

type StorageStatusWrapper[E datastore.Entity] struct {
storage datastore.Storage[E]
}
Expand Down
12 changes: 5 additions & 7 deletions pkg/service/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (
)

type tenantService struct {
db *sqlx.DB
log *slog.Logger
tenantStore datastore.Storage[*v1.Tenant]
tenantMemberStore datastore.Storage[*v1.TenantMember]
log *slog.Logger
db *sqlx.DB
}

var (
Expand All @@ -26,13 +26,11 @@ var (
tenants = datastore.Entity(&v1.Tenant{})
)

func NewTenantService(db *sqlx.DB, l *slog.Logger) *tenantService {
ts := datastore.New(l, db, &v1.Tenant{})
tms := datastore.New(l, db, &v1.TenantMember{})
func NewTenantService(db *sqlx.DB, l *slog.Logger, tds TenantDataStore, tmds TenantMemberDataStore) *tenantService {
return &tenantService{
db: db,
tenantStore: NewStorageStatusWrapper(ts),
tenantMemberStore: NewStorageStatusWrapper(tms),
tenantStore: NewStorageStatusWrapper(tds),
tenantMemberStore: NewStorageStatusWrapper(tmds),
log: l,
}
}
Expand Down
9 changes: 3 additions & 6 deletions pkg/service/tenantmember.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"log/slog"

"github.com/jmoiron/sqlx"
v1 "github.com/metal-stack/masterdata-api/api/v1"
"github.com/metal-stack/masterdata-api/pkg/datastore"
"google.golang.org/grpc/codes"
Expand All @@ -18,12 +17,10 @@ type tenantMemberService struct {
log *slog.Logger
}

func NewTenantMemberService(db *sqlx.DB, l *slog.Logger) *tenantMemberService {
tms := datastore.New(l, db, &v1.TenantMember{})
ts := datastore.New(l, db, &v1.Tenant{})
func NewTenantMemberService(l *slog.Logger, tds TenantDataStore, tmds TenantMemberDataStore) *tenantMemberService {
return &tenantMemberService{
tenantMemberStore: NewStorageStatusWrapper(tms),
tenantStore: NewStorageStatusWrapper(ts),
tenantMemberStore: NewStorageStatusWrapper(tmds),
tenantStore: NewStorageStatusWrapper(tds),
log: l,
}
}
Expand Down
14 changes: 10 additions & 4 deletions server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,16 @@ func run() error {
logger.Error("unable to apply migrate db", "error", err)
}

projectService := service.NewProjectService(db, logger)
projectMemberService := service.NewProjectMemberService(db, logger)
tenantService := service.NewTenantService(db, logger)
tenantMemberService := service.NewTenantMemberService(db, logger)
ps := datastore.New(logger, db, &apiv1.Project{})
pms := datastore.New(logger, db, &apiv1.ProjectMember{})
ts := datastore.New(logger, db, &apiv1.Tenant{})
tms := datastore.New(logger, db, &apiv1.TenantMember{})

projectService := service.NewProjectService(logger, ps, pms, ts)
projectMemberService := service.NewProjectMemberService(logger, ps, pms, ts)
// FIXME db should not be required here
tenantService := service.NewTenantService(db, logger, ts, tms)
tenantMemberService := service.NewTenantMemberService(logger, ts, tms)

apiv1.RegisterProjectServiceServer(grpcServer, projectService)
apiv1.RegisterProjectMemberServiceServer(grpcServer, projectMemberService)
Expand Down
Loading