checkpoint

This commit is contained in:
sawka 2024-05-21 21:15:11 -07:00
parent 9e7e7af04a
commit 2317ce87f3
7 changed files with 212 additions and 2 deletions

View File

@ -7,3 +7,6 @@ import "embed"
//go:embed migrations-blockstore/*.sql
var BlockstoreMigrationFS embed.FS
//go:embed migrations-wstore/*.sql
var WStoreMigrationFS embed.FS

View File

@ -15,6 +15,5 @@ CREATE TABLE db_tab (
CREATE TABLE db_block (
blockid varchar(36) PRIMARY KEY,
tabid varchar(36) NOT NULL, -- the tab this block belongs to
data json NOT NULL
);

View File

@ -17,6 +17,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/service/blockservice"
"github.com/wavetermdev/thenextwave/pkg/service/fileservice"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/wstore"
"github.com/wailsapp/wails/v3/pkg/application"
"github.com/wailsapp/wails/v3/pkg/events"
@ -104,6 +105,11 @@ func main() {
log.Printf("error initializing blockstore: %v\n", err)
return
}
err = wstore.InitWStore()
if err != nil {
log.Printf("error initializing wstore: %v\n", err)
return
}
app := application.New(application.Options{
Name: "NextWave",

View File

@ -4,8 +4,10 @@
package blockservice
import (
"context"
"fmt"
"strings"
"time"
"github.com/wavetermdev/thenextwave/pkg/blockcontroller"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
@ -41,7 +43,12 @@ func (bs *BlockService) CloseBlock(blockId string) {
}
func (bs *BlockService) GetBlockData(blockId string) (map[string]any, error) {
blockData := wstore.BlockMap.Get(blockId)
ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
defer cancelFn()
blockData, err := wstore.BlockGet(ctx, blockId)
if err != nil {
return nil, fmt.Errorf("error getting block data: %w", err)
}
if blockData == nil {
return nil, nil
}

View File

@ -4,6 +4,7 @@
package wstore
import (
"context"
"fmt"
"sync"
@ -23,6 +24,7 @@ type Client struct {
type Workspace struct {
Lock *sync.Mutex `json:"-"`
WorkspaceId string `json:"workspaceid"`
Name string `json:"name"`
TabIds []string `json:"tabids"`
}
@ -118,3 +120,33 @@ func CreateWorkspace() (*Workspace, error) {
}
return ws, nil
}
func EnsureWorkspace(ctx context.Context) error {
wsCount, err := WorkspaceCount(ctx)
if err != nil {
return fmt.Errorf("error getting workspace count: %w", err)
}
if wsCount > 0 {
return nil
}
ws := &Workspace{
Lock: &sync.Mutex{},
WorkspaceId: uuid.New().String(),
Name: "default",
}
err = WorkspaceInsert(ctx, ws)
if err != nil {
return fmt.Errorf("error inserting workspace: %w", err)
}
tab := &Tab{
Lock: &sync.Mutex{},
TabId: uuid.New().String(),
Name: "Tab 1",
BlockIds: []string{},
}
err = TabInsert(ctx, tab, ws.WorkspaceId)
if err != nil {
return fmt.Errorf("error inserting tab: %w", err)
}
return nil
}

View File

@ -0,0 +1,97 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package wstore
import (
"context"
"fmt"
"github.com/google/uuid"
)
func WorkspaceCount(ctx context.Context) (int, error) {
return WithTxRtn(ctx, func(tx *TxWrap) (int, error) {
query := "SELECT count(*) FROM workspace"
return tx.GetInt(query), nil
})
}
func WorkspaceInsert(ctx context.Context, ws *Workspace) error {
if ws.WorkspaceId == "" {
ws.WorkspaceId = uuid.New().String()
}
return WithTx(ctx, func(tx *TxWrap) error {
query := "INSERT INTO workspace (workspaceid, data) VALUES (?, ?)"
tx.Exec(query, ws.WorkspaceId, TxJson(tx, ws))
return nil
})
}
func WorkspaceGet(ctx context.Context, workspaceId string) (*Workspace, error) {
return WithTxRtn(ctx, func(tx *TxWrap) (*Workspace, error) {
query := "SELECT data FROM workspace WHERE workspaceid = ?"
jsonData := tx.GetString(query, workspaceId)
return TxReadJson[Workspace](tx, jsonData), nil
})
}
func WorkspaceUpdate(ctx context.Context, ws *Workspace) error {
return WithTx(ctx, func(tx *TxWrap) error {
query := "UPDATE workspace SET data = ? WHERE workspaceid = ?"
tx.Exec(query, TxJson(tx, ws), ws.WorkspaceId)
return nil
})
}
func addTabToWorkspace(ctx context.Context, workspaceId string, tabId string) error {
return WithTx(ctx, func(tx *TxWrap) error {
ws, err := WorkspaceGet(tx.Context(), workspaceId)
if err != nil {
return err
}
if ws == nil {
return fmt.Errorf("workspace not found: %s", workspaceId)
}
ws.TabIds = append(ws.TabIds, tabId)
return WorkspaceUpdate(tx.Context(), ws)
})
}
func TabInsert(ctx context.Context, tab *Tab, workspaceId string) error {
if tab.TabId == "" {
tab.TabId = uuid.New().String()
}
return WithTx(ctx, func(tx *TxWrap) error {
query := "INSERT INTO tab (tabid, data) VALUES (?, ?)"
tx.Exec(query, tab.TabId, TxJson(tx, tab))
return addTabToWorkspace(tx.Context(), workspaceId, tab.TabId)
})
}
func BlockGet(ctx context.Context, blockId string) (*Block, error) {
return WithTxRtn(ctx, func(tx *TxWrap) (*Block, error) {
query := "SELECT data FROM block WHERE blockid = ?"
jsonData := tx.GetString(query, blockId)
return TxReadJson[Block](tx, jsonData), nil
})
}
func BlockDelete(ctx context.Context, blockId string) error {
return WithTx(ctx, func(tx *TxWrap) error {
query := "DELETE FROM block WHERE blockid = ?"
tx.Exec(query, blockId)
return nil
})
}
func BlockInsert(ctx context.Context, block *Block) error {
if block.BlockId == "" {
block.BlockId = uuid.New().String()
}
return WithTx(ctx, func(tx *TxWrap) error {
query := "INSERT INTO block (blockid, data) VALUES (?, ?)"
tx.Exec(query, block.BlockId, TxJson(tx, block))
return nil
})
}

View File

@ -5,14 +5,20 @@ package wstore
import (
"context"
"encoding/json"
"fmt"
"log"
"path"
"time"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/jmoiron/sqlx"
"github.com/sawka/txwrap"
"github.com/wavetermdev/thenextwave/pkg/wavebase"
sqlite3migrate "github.com/golang-migrate/migrate/v4/database/sqlite3"
dbfs "github.com/wavetermdev/thenextwave/db"
)
const WStoreDBName = "waveterm.db"
@ -55,3 +61,63 @@ func MakeDB(ctx context.Context) (*sqlx.DB, error) {
func MigrateWStore() error {
return nil
}
func MakeWStoreMigrate() (*migrate.Migrate, error) {
fsVar, err := iofs.New(dbfs.WStoreMigrationFS, "migrations-wstore")
if err != nil {
return nil, fmt.Errorf("opening iofs: %w", err)
}
mdriver, err := sqlite3migrate.WithInstance(globalDB.DB, &sqlite3migrate.Config{})
if err != nil {
return nil, fmt.Errorf("making blockstore migration driver: %w", err)
}
m, err := migrate.NewWithInstance("iofs", fsVar, "sqlite3", mdriver)
if err != nil {
return nil, fmt.Errorf("making blockstore migration db[%s]: %w", GetDBName(), err)
}
return m, nil
}
func GetMigrateVersion(m *migrate.Migrate) (uint, bool, error) {
if m == nil {
var err error
m, err = MakeWStoreMigrate()
if err != nil {
return 0, false, err
}
}
curVersion, dirty, err := m.Version()
if err == migrate.ErrNilVersion {
return 0, false, nil
}
return curVersion, dirty, err
}
func WithTx(ctx context.Context, fn func(tx *TxWrap) error) error {
return txwrap.WithTx(ctx, globalDB, fn)
}
func WithTxRtn[RT any](ctx context.Context, fn func(tx *TxWrap) (RT, error)) (RT, error) {
return txwrap.WithTxRtn(ctx, globalDB, fn)
}
func TxJson(tx *TxWrap, v any) string {
barr, err := json.Marshal(v)
if err != nil {
tx.SetErr(fmt.Errorf("json marshal (%T): %w", v, err))
return ""
}
return string(barr)
}
func TxReadJson[T any](tx *TxWrap, jsonData string) *T {
if jsonData == "" {
return nil
}
var v T
err := json.Unmarshal([]byte(jsonData), &v)
if err != nil {
tx.SetErr(fmt.Errorf("json unmarshal (%T): %w", v, err))
}
return &v
}