new directory structure and oldmigrate (#327)

This commit is contained in:
Mike Sawka 2024-09-05 14:05:42 -07:00 committed by GitHub
parent debbed7003
commit a5f563b52d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 197 additions and 24 deletions

View File

@ -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 {

View File

@ -0,0 +1 @@
DROP TABLE history_migrated;

View 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
);

View File

@ -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());

View 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

View File

@ -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 {

View File

@ -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 (

View File

@ -36,6 +36,7 @@ declare global {
type Client = WaveObj & {
windowids: string[];
tosagreed?: number;
historymigrated?: boolean;
};
// wshrpc.CommandAppendIJsonData

View File

@ -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) {

View File

@ -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 = `

View File

@ -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]

View File

@ -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 {

View 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
}

View File

@ -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) {