mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
new directory structure and oldmigrate (#327)
This commit is contained in:
parent
debbed7003
commit
a5f563b52d
@ -175,7 +175,6 @@ func main() {
|
||||
log.Printf("error setting auth key: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = service.ValidateServiceMap()
|
||||
if err != nil {
|
||||
log.Printf("error validating service map: %v\n", err)
|
||||
@ -186,6 +185,11 @@ func main() {
|
||||
log.Printf("error ensuring wave home dir: %v\n", err)
|
||||
return
|
||||
}
|
||||
err = wavebase.EnsureWaveDBDir()
|
||||
if err != nil {
|
||||
log.Printf("error ensuring wave db dir: %v\n", err)
|
||||
return
|
||||
}
|
||||
waveLock, err := wavebase.AcquireWaveLock()
|
||||
if err != nil {
|
||||
log.Printf("error acquiring wave lock (another instance of Wave is likely running): %v\n", err)
|
||||
@ -197,7 +201,6 @@ func main() {
|
||||
log.Printf("error releasing wave lock: %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("wave version: %s (%s)\n", WaveVersion, BuildTime)
|
||||
log.Printf("wave home dir: %s\n", wavebase.GetWaveHomeDir())
|
||||
err = filestore.InitFilestore()
|
||||
@ -210,6 +213,10 @@ func main() {
|
||||
log.Printf("error initializing wstore: %v\n", err)
|
||||
return
|
||||
}
|
||||
migrateErr := wstore.TryMigrateOldHistory()
|
||||
if migrateErr != nil {
|
||||
log.Printf("error migrating old history: %v\n", migrateErr)
|
||||
}
|
||||
go func() {
|
||||
err := shellutil.InitCustomShellStartupFiles()
|
||||
if err != nil {
|
||||
|
1
db/migrations-wstore/000004_history.down.sql
Normal file
1
db/migrations-wstore/000004_history.down.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE history_migrated;
|
9
db/migrations-wstore/000004_history.up.sql
Normal file
9
db/migrations-wstore/000004_history.up.sql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE history_migrated (
|
||||
historyid varchar(36) PRIMARY KEY,
|
||||
ts bigint NOT NULL,
|
||||
remotename varchar(200) NOT NULL,
|
||||
haderror boolean NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
exitcode int NULL DEFAULT NULL,
|
||||
durationms int NULL DEFAULT NULL
|
||||
);
|
@ -65,7 +65,7 @@ const waveHome = getWaveHomeDir();
|
||||
const oldConsoleLog = console.log;
|
||||
|
||||
const loggerTransports: winston.transport[] = [
|
||||
new winston.transports.File({ filename: path.join(getWaveHomeDir(), "waveterm-app.log"), level: "info" }),
|
||||
new winston.transports.File({ filename: path.join(getWaveHomeDir(), "waveapp.log"), level: "info" }),
|
||||
];
|
||||
if (isDev) {
|
||||
loggerTransports.push(new winston.transports.Console());
|
||||
|
18
frontend/app/asset/dots-anim-4.svg
Normal file
18
frontend/app/asset/dots-anim-4.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="12" width="12" viewBox="0 0 16 16">
|
||||
<title>dots anim 4</title>
|
||||
<g class="nc-icon-wrapper">
|
||||
<g class="nc-loop-dots-4-16-icon-f">
|
||||
<circle cx="3" cy="8" r="2"></circle>
|
||||
<circle cx="8" cy="8" r="2" data-color="color-2"></circle>
|
||||
<circle cx="13" cy="8" r="2"></circle>
|
||||
</g>
|
||||
<style>
|
||||
.nc-loop-dots-4-16-icon-f{--animation-duration:0.8s}
|
||||
.nc-loop-dots-4-16-icon-f *{opacity:.4;transform:scale(.75);animation:nc-loop-dots-4-anim var(--animation-duration) infinite}
|
||||
.nc-loop-dots-4-16-icon-f :nth-child(1){transform-origin:3px 8px;animation-delay:-.3s;animation-delay:calc(var(--animation-duration)/-2.666)}
|
||||
.nc-loop-dots-4-16-icon-f :nth-child(2){transform-origin:8px 8px;animation-delay:-.15s;animation-delay:calc(var(--animation-duration)/-5.333)}
|
||||
.nc-loop-dots-4-16-icon-f :nth-child(3){transform-origin:13px 8px}
|
||||
@keyframes nc-loop-dots-4-anim{0%,100%{opacity:.4;transform:scale(.75)}50%{opacity:1;transform:scale(1)}}
|
||||
</style>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 982 B |
@ -174,6 +174,15 @@
|
||||
overflow: hidden;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.connecting-svg {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
left: 9px;
|
||||
svg {
|
||||
fill: var(--warning-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.block-frame-textelems-wrapper {
|
||||
|
@ -9,6 +9,7 @@ import * as util from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import * as jotai from "jotai";
|
||||
import * as React from "react";
|
||||
import DotsSvg from "../asset/dots-anim-4.svg";
|
||||
|
||||
export const colorRegex = /^((#[0-9a-f]{6,8})|([a-z]+))$/;
|
||||
|
||||
@ -225,11 +226,16 @@ export const ConnectionButton = React.memo(
|
||||
} else {
|
||||
titleText = "Connected to " + connection;
|
||||
let iconName = "arrow-right-arrow-left";
|
||||
let iconSvg = null;
|
||||
if (connStatus?.status == "connecting") {
|
||||
color = "var(--warning-color)";
|
||||
titleText = "Connecting to " + connection;
|
||||
iconName = "rotate";
|
||||
shouldSpin = true;
|
||||
shouldSpin = false;
|
||||
iconSvg = (
|
||||
<div className="connecting-svg">
|
||||
<DotsSvg />
|
||||
</div>
|
||||
);
|
||||
} else if (connStatus?.status == "error") {
|
||||
color = "var(--error-color)";
|
||||
titleText = "Error connecting to " + connection;
|
||||
@ -242,12 +248,16 @@ export const ConnectionButton = React.memo(
|
||||
titleText = "Disconnected from " + connection;
|
||||
showDisconnectedSlash = true;
|
||||
}
|
||||
connIconElem = (
|
||||
<i
|
||||
className={clsx(util.makeIconClass(iconName, false), "fa-stack-1x")}
|
||||
style={{ color: color, marginRight: 2 }}
|
||||
/>
|
||||
);
|
||||
if (iconSvg != null) {
|
||||
connIconElem = iconSvg;
|
||||
} else {
|
||||
connIconElem = (
|
||||
<i
|
||||
className={clsx(util.makeIconClass(iconName, false), "fa-stack-1x")}
|
||||
style={{ color: color, marginRight: 2 }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
1
frontend/types/gotypes.d.ts
vendored
1
frontend/types/gotypes.d.ts
vendored
@ -36,6 +36,7 @@ declare global {
|
||||
type Client = WaveObj & {
|
||||
windowids: string[];
|
||||
tosagreed?: number;
|
||||
historymigrated?: boolean;
|
||||
};
|
||||
|
||||
// wshrpc.CommandAppendIJsonData
|
||||
|
@ -51,7 +51,7 @@ func InitFilestore() error {
|
||||
|
||||
func GetDBName() string {
|
||||
waveHome := wavebase.GetWaveHomeDir()
|
||||
return filepath.Join(waveHome, FilestoreDBName)
|
||||
return filepath.Join(waveHome, wavebase.WaveDBDir, FilestoreDBName)
|
||||
}
|
||||
|
||||
func MakeDB(ctx context.Context) (*sqlx.DB, error) {
|
||||
|
@ -36,9 +36,9 @@ const WaveAppPathVarName = "WAVETERM_APP_PATH"
|
||||
const AppPathBinDir = "bin"
|
||||
|
||||
const (
|
||||
ZshIntegrationDir = "zsh-integration"
|
||||
BashIntegrationDir = "bash-integration"
|
||||
PwshIntegrationDir = "pwsh-integration"
|
||||
ZshIntegrationDir = "shell/zsh"
|
||||
BashIntegrationDir = "shell/bash"
|
||||
PwshIntegrationDir = "shell/pwsh"
|
||||
WaveHomeBinDir = "bin"
|
||||
|
||||
ZshStartup_Zprofile = `
|
||||
|
@ -25,12 +25,13 @@ import (
|
||||
var WaveVersion = "0.0.0"
|
||||
var BuildTime = "0"
|
||||
|
||||
const DefaultWaveHome = "~/.w2"
|
||||
const DevWaveHome = "~/.w2-dev"
|
||||
const DefaultWaveHome = "~/.waveterm"
|
||||
const DevWaveHome = "~/.waveterm-dev"
|
||||
const WaveHomeVarName = "WAVETERM_HOME"
|
||||
const WaveDevVarName = "WAVETERM_DEV"
|
||||
const WaveLockFile = "waveterm.lock"
|
||||
const WaveLockFile = "wave.lock"
|
||||
const DomainSocketBaseName = "wave.sock"
|
||||
const WaveDBDir = "db"
|
||||
const JwtSecret = "waveterm" // TODO generate and store this
|
||||
|
||||
var baseLock = &sync.Mutex{}
|
||||
@ -90,6 +91,10 @@ func EnsureWaveHomeDir() error {
|
||||
return CacheEnsureDir(GetWaveHomeDir(), "wavehome", 0700, "wave home directory")
|
||||
}
|
||||
|
||||
func EnsureWaveDBDir() error {
|
||||
return CacheEnsureDir(filepath.Join(GetWaveHomeDir(), WaveDBDir), "wavedb", 0700, "wave db directory")
|
||||
}
|
||||
|
||||
func CacheEnsureDir(dirName string, cacheKey string, perm os.FileMode, dirDesc string) error {
|
||||
baseLock.Lock()
|
||||
ok := ensureDirCache[cacheKey]
|
||||
|
@ -112,11 +112,12 @@ func (update *WaveObjUpdate) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
OID string `json:"oid"`
|
||||
Version int `json:"version"`
|
||||
WindowIds []string `json:"windowids"`
|
||||
Meta MetaMapType `json:"meta"`
|
||||
TosAgreed int64 `json:"tosagreed,omitempty"`
|
||||
OID string `json:"oid"`
|
||||
Version int `json:"version"`
|
||||
WindowIds []string `json:"windowids"`
|
||||
Meta MetaMapType `json:"meta"`
|
||||
TosAgreed int64 `json:"tosagreed,omitempty"`
|
||||
HistoryMigrated bool `json:"historymigrated,omitempty"`
|
||||
}
|
||||
|
||||
func (*Client) GetOType() string {
|
||||
|
112
pkg/wstore/wstore_dboldmigration.go
Normal file
112
pkg/wstore/wstore_dboldmigration.go
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wavebase"
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
)
|
||||
|
||||
const OldDBName = "~/.waveterm/waveterm.db"
|
||||
|
||||
func GetOldDBName() string {
|
||||
return wavebase.ExpandHomeDir(OldDBName)
|
||||
}
|
||||
|
||||
func MakeOldDB(ctx context.Context) (*sqlx.DB, error) {
|
||||
dbName := GetOldDBName()
|
||||
rtn, err := sqlx.Open("sqlite3", fmt.Sprintf("file:%s?mode=ro&_busy_timeout=5000", dbName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rtn.DB.SetMaxOpenConns(1)
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
type OldHistoryType struct {
|
||||
HistoryId string
|
||||
Ts int64
|
||||
RemoteName string
|
||||
HadError bool
|
||||
CmdStr string
|
||||
ExitCode int
|
||||
DurationMs int64
|
||||
}
|
||||
|
||||
func GetAllOldHistory() ([]*OldHistoryType, error) {
|
||||
query := `
|
||||
SELECT
|
||||
h.historyid,
|
||||
h.ts,
|
||||
COALESCE(r.remotecanonicalname, '') as remotename,
|
||||
h.haderror,
|
||||
h.cmdstr,
|
||||
COALESCE(h.exitcode, 0) as exitcode,
|
||||
COALESCE(h.durationms, 0) as durationms
|
||||
FROM history h, remote r
|
||||
WHERE h.remoteid = r.remoteid
|
||||
AND NOT h.ismetacmd
|
||||
`
|
||||
db, err := MakeOldDB(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer db.Close()
|
||||
var rtn []*OldHistoryType
|
||||
err = db.Select(&rtn, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
func ReplaceOldHistory(ctx context.Context, hist []*OldHistoryType) error {
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `DELETE FROM history_migrated`
|
||||
tx.Exec(query)
|
||||
query = `INSERT INTO history_migrated (historyid, ts, remotename, haderror, cmdstr, exitcode, durationms)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
for _, hobj := range hist {
|
||||
tx.Exec(query, hobj.HistoryId, hobj.Ts, hobj.RemoteName, hobj.HadError, hobj.CmdStr, hobj.ExitCode, hobj.DurationMs)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TryMigrateOldHistory() error {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancelFn()
|
||||
client, err := DBGetSingleton[*waveobj.Client](ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if client.HistoryMigrated {
|
||||
return nil
|
||||
}
|
||||
log.Printf("trying to migrate old wave history\n")
|
||||
client.HistoryMigrated = true
|
||||
err = DBUpdate(ctx, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hist, err := GetAllOldHistory()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(hist) == 0 {
|
||||
return nil
|
||||
}
|
||||
err = ReplaceOldHistory(ctx, hist)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("migrated %d old wave history records\n", len(hist))
|
||||
return nil
|
||||
}
|
@ -43,7 +43,7 @@ func InitWStore() error {
|
||||
|
||||
func GetDBName() string {
|
||||
waveHome := wavebase.GetWaveHomeDir()
|
||||
return filepath.Join(waveHome, WStoreDBName)
|
||||
return filepath.Join(waveHome, wavebase.WaveDBDir, WStoreDBName)
|
||||
}
|
||||
|
||||
func MakeDB(ctx context.Context) (*sqlx.DB, error) {
|
||||
|
Loading…
Reference in New Issue
Block a user