backstack: added saving of backstack to workspace

This commit is contained in:
Leon Mika 2022-08-11 22:23:39 +10:00
parent 96207821a2
commit 721d3abe5e
9 changed files with 214 additions and 11 deletions

View file

@ -0,0 +1,37 @@
package workspaces
import (
"github.com/asdine/storm"
"github.com/pkg/errors"
"os"
)
type MetaInfo struct {
Command string
}
type Manager struct {
metainfo MetaInfo
}
func New(metaInfo MetaInfo) *Manager {
return &Manager{metainfo: metaInfo}
}
func (m *Manager) Open(filename string) (*Workspace, error) {
db, err := storm.Open(filename)
if err != nil {
return nil, errors.Wrapf(err, "cannot open workspace at %v", filename)
}
return &Workspace{db: db}, nil
}
func (m *Manager) CreateTemp() (*Workspace, error) {
workspaceFile, err := os.CreateTemp("", m.metainfo.Command+"*.workspace")
if err != nil {
return nil, errors.Wrapf(err, "cannot create workspace file")
}
workspaceFile.Close() // We just need the filename
return m.Open(workspaceFile.Name())
}

View file

@ -0,0 +1,19 @@
package workspaces
import (
"github.com/asdine/storm"
"log"
)
type Workspace struct {
db *storm.DB
}
func (ws *Workspace) DB() *storm.DB {
return ws.db
}
func (ws *Workspace) Close() {
log.Printf("close workspace")
ws.db.Close()
}

View file

@ -7,14 +7,17 @@ import (
"github.com/lmika/audax/internal/common/ui/events"
"github.com/lmika/audax/internal/dynamo-browse/models"
"github.com/lmika/audax/internal/dynamo-browse/models/queryexpr"
"github.com/lmika/audax/internal/dynamo-browse/services/workspaces"
"github.com/pkg/errors"
"log"
"os"
"sync"
)
type TableReadController struct {
tableService TableReadService
tableName string
tableService TableReadService
workspaceService *workspaces.Service
tableName string
// state
mutex *sync.Mutex
@ -23,12 +26,13 @@ type TableReadController struct {
//filter string
}
func NewTableReadController(state *State, tableService TableReadService, tableName string) *TableReadController {
func NewTableReadController(state *State, tableService TableReadService, workspaceService *workspaces.Service, tableName string) *TableReadController {
return &TableReadController{
state: state,
tableService: tableService,
tableName: tableName,
mutex: new(sync.Mutex),
state: state,
tableService: tableService,
workspaceService: workspaceService,
tableName: tableName,
mutex: new(sync.Mutex),
}
}
@ -99,6 +103,9 @@ func (c *TableReadController) PromptForQuery() tea.Cmd {
return events.Error(err)
}
if err := c.workspaceService.PushSnapshot(resultSet); err != nil {
log.Printf("cannot push snapshot: %v", err)
}
return c.setResultSetAndFilter(newResultSet, "")
})
},

View file

@ -3,9 +3,8 @@ package models
import "sort"
type ResultSet struct {
TableInfo *TableInfo
Query Queryable
//Columns []string
TableInfo *TableInfo
Query Queryable
items []Item
attributes []ItemAttribute

View file

@ -0,0 +1,19 @@
package serialisable
import (
"github.com/lmika/audax/internal/dynamo-browse/models"
"time"
)
type ResultSetSnapshot struct {
ID int64 `storm:"id,increment"`
BackLink int64 `storm:"index"`
Time time.Time
TableInfo *models.TableInfo
Query Query
Filter string
}
type Query struct {
Expression string
}

View file

@ -0,0 +1,55 @@
package workspacestore
import (
"github.com/asdine/storm"
"github.com/lmika/audax/internal/common/workspaces"
"github.com/lmika/audax/internal/dynamo-browse/models/serialisable"
"github.com/pkg/errors"
"log"
)
const resultSetSnapshotsBucket = "ResultSetSnapshots"
type ResultSetSnapshotStore struct {
ws storm.Node
}
func NewResultSetSnapshotStore(ws *workspaces.Workspace) *ResultSetSnapshotStore {
return &ResultSetSnapshotStore{
ws: ws.DB().From(resultSetSnapshotsBucket),
}
}
func (s *ResultSetSnapshotStore) Save(rs *serialisable.ResultSetSnapshot) error {
if err := s.ws.Save(rs); err != nil {
return errors.Wrap(err, "cannot save result set")
}
log.Printf("saved result set")
return nil
}
func (s *ResultSetSnapshotStore) SetAsHead(resultSetID int64) error {
if err := s.ws.Set("head", "id", resultSetID); err != nil {
return errors.Wrap(err, "cannot set as head")
}
log.Printf("saved result set head")
return nil
}
func (s *ResultSetSnapshotStore) Head() (*serialisable.ResultSetSnapshot, error) {
var headResultSetID int64
if err := s.ws.Get("head", "id", &headResultSetID); err != nil && !errors.Is(err, storm.ErrNotFound) {
return nil, errors.Wrap(err, "cannot get head")
}
var rss serialisable.ResultSetSnapshot
if err := s.ws.One("ID", headResultSetID, &rss); err != nil {
if errors.Is(err, storm.ErrNotFound) {
return nil, nil
} else {
return nil, errors.Wrap(err, "cannot get head")
}
}
return &rss, nil
}

View file

@ -0,0 +1,9 @@
package workspaces
import "github.com/lmika/audax/internal/dynamo-browse/models/serialisable"
type ResultSetSnapshotStore interface {
Save(rs *serialisable.ResultSetSnapshot) error
SetAsHead(resultSetId int64) error
Head() (*serialisable.ResultSetSnapshot, error)
}

View file

@ -0,0 +1,43 @@
package workspaces
import (
"github.com/lmika/audax/internal/dynamo-browse/models"
"github.com/lmika/audax/internal/dynamo-browse/models/serialisable"
"github.com/pkg/errors"
"time"
)
type Service struct {
store ResultSetSnapshotStore
}
func NewService(store ResultSetSnapshotStore) *Service {
return &Service{
store: store,
}
}
func (s *Service) PushSnapshot(rs *models.ResultSet) error {
newSnapshot := &serialisable.ResultSetSnapshot{
Time: time.Now(),
TableInfo: rs.TableInfo,
}
if q := rs.Query; q != nil {
newSnapshot.Query.Expression = q.String()
}
if head, err := s.store.Head(); head != nil {
newSnapshot.BackLink = head.ID
} else if err != nil {
return errors.Wrap(err, "cannot get head result set")
}
if err := s.store.Save(newSnapshot); err != nil {
return errors.Wrap(err, "cannot save snapshot")
}
if err := s.store.SetAsHead(newSnapshot.ID); err != nil {
return errors.Wrap(err, "cannot set new snapshot as head")
}
return nil
}