mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
checkpoint
This commit is contained in:
parent
9e7e7af04a
commit
2317ce87f3
3
db/db.go
3
db/db.go
@ -7,3 +7,6 @@ import "embed"
|
||||
|
||||
//go:embed migrations-blockstore/*.sql
|
||||
var BlockstoreMigrationFS embed.FS
|
||||
|
||||
//go:embed migrations-wstore/*.sql
|
||||
var WStoreMigrationFS embed.FS
|
||||
|
@ -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
|
||||
);
|
||||
|
6
main.go
6
main.go
@ -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",
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
97
pkg/wstore/wstore_dbops.go
Normal file
97
pkg/wstore/wstore_dbops.go
Normal 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
|
||||
})
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user