Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

运行时增加端口检查;获取daemon时比较运行信息;增加--restart #18

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions cmd/kd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/Karmenzind/kd/internal/cache"
"github.com/Karmenzind/kd/internal/core"
"github.com/Karmenzind/kd/internal/daemon"
"github.com/Karmenzind/kd/internal/query"
"github.com/Karmenzind/kd/internal/run"
"github.com/Karmenzind/kd/internal/update"
"github.com/Karmenzind/kd/logger"
"github.com/Karmenzind/kd/pkg"
Expand Down Expand Up @@ -42,6 +44,7 @@ var um = map[string]string{
"server": "start server foreground 在前台启动服务端",
"daemon": "ensure/start the daemon process 启动守护进程",
"stop": "stop the daemon process 停止守护进程",
"restart": "restart the daemon process 重新启动守护进程",
"update": "check and update kd client 更新kd的可执行文件",
"generate-config": "generate config sample 生成配置文件,Linux/Mac默认地址为~/.config/kd.toml,Win为~\\kd.toml",
"edit-config": "edit configuration file with the default editor 用默认编辑器打开配置文件",
Expand All @@ -57,13 +60,13 @@ func flagServer(*cli.Context, bool) error {
if strings.Contains(err.Error(), "address already in use") {
return fmt.Errorf("端口已经被占用(%s)", err)
}
return nil
return err
}

func flagDaemon(*cli.Context, bool) error {
p, _ := daemon.FindServerProcess()
if p != nil {
d.EchoWrong(fmt.Sprintf("已存在运行中的守护进程,PID:%d。请先执行`kd --stop`停止该进程", p.Pid))
d.EchoWrong("已存在运行中的守护进程,PID:%d。请先执行`kd --stop`停止该进程", p.Pid)
return nil

}
Expand All @@ -79,7 +82,15 @@ func flagStop(*cli.Context, bool) error {
if err != nil {
d.EchoFatal(err.Error())
}
return nil
return err
}

func flagRestart(*cli.Context, bool) error {
err := daemon.KillDaemonIfRunning()
if err == nil {
err = daemon.StartDaemonProcess()
}
return err
}

func flagUpdate(ctx *cli.Context, _ bool) (err error) {
Expand Down Expand Up @@ -114,7 +125,7 @@ func flagUpdate(ctx *cli.Context, _ bool) (err error) {

if doUpdate {
emoji.Println(":lightning: Let's update now")
go daemon.KillDaemonIfRunning()
go daemon.KillDaemonIfRunning()
err = update.UpdateBinary(VERSION)
}
return err
Expand Down Expand Up @@ -175,7 +186,19 @@ func flagStatus(*cli.Context, bool) error {
fmt.Printf(" Binary地址:%s\n", kdpath)
}

return nil
return err
}

func checkAndNoticeUpdate() {
if ltag := update.GetCachedLatestTag(); ltag != "" {
if update.CompareVersions(ltag, VERSION) == 1 {
prompt := fmt.Sprintf("发现新版本%s,请执行`kd --update`更新", ltag)
if pkg.GetLinuxDistro() == "arch" {
prompt += "。ArchLinux推荐通过AUR安装/升级"
}
d.EchoWeakNotice(prompt)
}
}
}

func basicCheck() {
Expand Down Expand Up @@ -203,6 +226,8 @@ func main() {
cfg := config.Cfg
d.ApplyConfig(cfg.EnableEmoji)

run.Info.Version = VERSION

if cfg.Logging.Enable {
l, err := logger.InitLogger(&cfg.Logging)
if err != nil {
Expand Down Expand Up @@ -242,23 +267,26 @@ func main() {
&cli.BoolFlag{Name: "server", DisableDefaultText: true, Action: flagServer, Hidden: true, Usage: um["server"]},
&cli.BoolFlag{Name: "daemon", DisableDefaultText: true, Action: flagDaemon, Usage: um["daemon"]},
&cli.BoolFlag{Name: "stop", DisableDefaultText: true, Hidden: true, Action: flagStop, Usage: um["stop"]},
&cli.BoolFlag{Name: "restart", DisableDefaultText: true, Hidden: true, Action: flagRestart, Usage: um["restart"]},
&cli.BoolFlag{Name: "update", DisableDefaultText: true, Action: flagUpdate, Usage: um["update"]},
&cli.BoolFlag{Name: "generate-config", DisableDefaultText: true, Action: flagGenerateConfig, Usage: um["generate-config"]},
&cli.BoolFlag{Name: "edit-config", DisableDefaultText: true, Action: flagEditConfig, Usage: um["edit-config"]},
&cli.BoolFlag{Name: "status", DisableDefaultText: true, Hidden: true, Action: flagStatus, Usage: um["status"]},
},
Action: func(cCtx *cli.Context) error {
// 除了--text外,其他的BoolFlag都当subcommand用
for _, flag := range []string{"init", "server", "daemon", "stop", "update", "generate-config", "edit-config", "status"} {
if !cCtx.Bool("update") {
defer checkAndNoticeUpdate()
}
for _, flag := range []string{"init", "server", "daemon", "stop", "restart", "update", "generate-config", "edit-config", "status"} {
if cCtx.Bool(flag) {
return nil
}
}

if cfg.FileExists && cfg.ModTime > daemon.GetDaemonInfo().StartTime {
d.EchoWarn("检测到配置文件发生修改,正在重启守护进程")
flagStop(cCtx, true)
flagDaemon(cCtx, true)
flagRestart(cCtx, true)
}

if cCtx.String("theme") != "" {
Expand All @@ -268,10 +296,6 @@ func main() {

if cCtx.Args().Len() > 0 {
zap.S().Debugf("Recieved Arguments (len: %d): %+v \n", cCtx.Args().Len(), cCtx.Args().Slice())
// emoji.Printf(":eyes: Arguments are: %+v \n", cCtx.Args().Slice())
// emoji.Printf(":eyes: Flat --update %+v \n", cCtx.Bool("update"))
// emoji.Printf(":eyes: Flat --nocache %+v \n", cCtx.Bool("nocache"))
// emoji.Printf(":eyes: flags are: %+v \n", cCtx.App.VisibleFlags)
// emoji.Printf("Test emoji:\n:accept: :inbox_tray: :information: :us: :uk: 🗣 :lips: :eyes: :balloon: \n")

qstr := strings.Join(cCtx.Args().Slice(), " ")
Expand All @@ -284,7 +308,7 @@ func main() {
}
if err == nil {
if r.Found {
err = pkg.OutputResult(r.PrettyFormat(cfg.EnglishOnly), cfg.Paging, cfg.PagerCommand, cfg.ClearScreen)
err = pkg.OutputResult(query.PrettyFormat(r, cfg.EnglishOnly), cfg.Paging, cfg.PagerCommand, cfg.ClearScreen)
if err != nil {
d.EchoFatal(err.Error())
}
Expand All @@ -310,14 +334,4 @@ func main() {
zap.S().Errorf("APP stopped: %s", err)
d.EchoError(err.Error())
}

if ltag := update.GetCachedLatestTag(); ltag != "" {
if update.CompareVersions(ltag, VERSION) == 1 {
prompt := fmt.Sprintf("发现新版本%s,请执行`kd --update`更新", ltag)
if pkg.GetLinuxDistro() == "arch" {
prompt+= "。ArchLinux推荐通过AUR安装/升级"
}
d.EchoWeakNotice(prompt)
}
}
}
9 changes: 5 additions & 4 deletions internal/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"

"github.com/Karmenzind/kd/internal/model"
"github.com/Karmenzind/kd/pkg"
"go.uber.org/zap"
)

Expand All @@ -33,7 +34,7 @@ func GetCachedQuery(r *model.Result) (err error) {
}
c.Close()
j := jb.Bytes()
zap.S().Debugf("Got cached json %s", j)
zap.S().Debugf("Got cached json %s", j)

if len(j) > 0 {
err = json.Unmarshal(j, r)
Expand All @@ -55,9 +56,9 @@ func UpdateQueryCache(r *model.Result) (err error) {
j, err := json.Marshal(r)
if err != nil {
zap.S().Warnf("Failed to marshal %+v: %s", r, err)
return
return
}
zap.S().Debugf("Got marshalled json to save: %s", j)
zap.S().Debugf("Got marshalled json to save: %s", j)

var zb bytes.Buffer
jw := zlib.NewWriter(&zb)
Expand Down Expand Up @@ -104,7 +105,7 @@ func UpdateQueryCacheJson(r *model.Result) (err error) {
if !r.Found {
return
}
err = saveJson(getQueryCacheFilePath(r.Query), r)
err = pkg.SaveJson(getQueryCacheFilePath(r.Query), r)
if err != nil {
zap.S().Errorf("Failed to update cache for '%s'. Error: %s", r.Query, err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/cache/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func CounterIncr(query string, history chan int) {
c := make(MonthCounter)
counterPath := filepath.Join(CACHE_STAT_DIR_PATH, fmt.Sprintf("counter-%d%02d.json", n.Year(), int(n.Month())))
if pkg.IsPathExists(counterPath) {
err := loadJson(counterPath, &c)
err := pkg.LoadJson(counterPath, &c)
if err != nil {
zap.S().Warnf("Failed to load counter")
return
Expand All @@ -35,5 +35,5 @@ func CounterIncr(query string, history chan int) {
}
c[query] += 1
history <- c[query]
saveJson(counterPath, &c)
pkg.SaveJson(counterPath, &c)
}
54 changes: 18 additions & 36 deletions internal/cache/utils.go
Original file line number Diff line number Diff line change
@@ -1,46 +1,28 @@
package cache

import (
"fmt"
"os"
"path/filepath"
"runtime"

"github.com/Karmenzind/kd/pkg"
"github.com/Karmenzind/kd/internal/run"
d "github.com/Karmenzind/kd/pkg/decorate"
)

var CACHE_ROOT_DIRNAME = "kdcache"
var CACHE_ROOT_PATH string // kdCache目录完整路径
var CACHE_WORDS_PATH string // 放word缓存文件的目录完整路径
var CACHE_RUN_PATH string // 存放运行信息
var CACHE_STAT_DIR_PATH string

var saveJson = pkg.SaveJson
var loadJson = pkg.LoadJson

func ensureCacheDir() string {
userdir, _ := os.UserHomeDir()
var target string
switch runtime.GOOS {
case "linux":
target = filepath.Join(userdir, ".cache", CACHE_ROOT_DIRNAME)
case "darwin":
target = filepath.Join(userdir, "Library/Caches", CACHE_ROOT_DIRNAME)
case "windows":
target = filepath.Join(userdir, ".cache", CACHE_ROOT_DIRNAME)
}
err := os.MkdirAll(target, os.ModePerm)
if err != nil {
panic("Failed to create cache dir")
}
return target
}
var CACHE_ROOT_PATH = run.CACHE_ROOT_PATH
var CACHE_WORDS_PATH = run.CACHE_WORDS_PATH
var CACHE_RUN_PATH = run.CACHE_RUN_PATH
var CACHE_STAT_DIR_PATH = run.CACHE_STAT_DIR_PATH

func init() {
CACHE_ROOT_PATH = ensureCacheDir()
CACHE_WORDS_PATH = filepath.Join(CACHE_ROOT_PATH, "words")
CACHE_STAT_DIR_PATH = filepath.Join(CACHE_ROOT_PATH, "stat")
CACHE_RUN_PATH = filepath.Join(CACHE_ROOT_PATH, "run")
os.Mkdir(CACHE_WORDS_PATH, os.ModePerm)
os.Mkdir(CACHE_STAT_DIR_PATH, os.ModePerm)
os.Mkdir(CACHE_RUN_PATH, os.ModePerm)
for _, directory := range []string{
CACHE_ROOT_PATH,
CACHE_WORDS_PATH,
CACHE_STAT_DIR_PATH,
CACHE_RUN_PATH,
} {
err := os.MkdirAll(directory, os.ModePerm)
if err != nil {
d.EchoFatal(fmt.Sprintf("Failed to create %s", directory))
}
}
}
77 changes: 24 additions & 53 deletions internal/client.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
package internal

/*

功能:

- 查询
- 更新
*/

import (
"fmt"
"os"
"regexp"
"strings"

Expand All @@ -19,9 +10,8 @@ import (
"github.com/Karmenzind/kd/internal/daemon"
"github.com/Karmenzind/kd/internal/model"
q "github.com/Karmenzind/kd/internal/query"
"github.com/Karmenzind/kd/pkg"
"github.com/Karmenzind/kd/internal/run"
d "github.com/Karmenzind/kd/pkg/decorate"
"github.com/Karmenzind/kd/pkg/proc"
"github.com/Karmenzind/kd/pkg/str"
"go.uber.org/zap"
)
Expand All @@ -36,35 +26,30 @@ func ensureDaemon(running chan bool) {
d.EchoFatal(err.Error())
}
} else {
exename, err := pkg.GetExecutablePath()
if err == nil {
runningExename, _ := p.Exe()
// TODO (k): <2024-01-03> 增加检查版本
if exename != runningExename {
d.EchoWarn(fmt.Sprintf("正在运行的守护程序(%s)与当前程序(%s)文件信息或版本不一致,将尝试重新启动守护进程", runningExename, exename))
err := proc.KillProcess(p)
if err != nil {
cmd := proc.GetKillCMD(p.Pid)
d.EchoError(fmt.Sprintf("停止进程%v失败,请手动执行:", p.Pid))
fmt.Println(cmd.String())
os.Exit(1)
}
d.EchoRun("已终止,正在启动新的守护进程...")
err = daemon.StartDaemonProcess()
if err != nil {
d.EchoFatal(err.Error())
}
}
var warn string
// recorded daemon info
recDi := daemon.GetDaemonInfo()
if run.Info.Version != recDi.Version {
warn = fmt.Sprintf("正在运行的守护程序版本(%s)与当前程序(%s)不一致", recDi.Version, run.Info.Version)
} else if daemonExepath, _ := p.Exe(); run.Info.ExePath != daemonExepath {
warn = fmt.Sprintf("正在运行的守护程序(%s)与当前程序(%s)文件路径不一致", daemonExepath, run.Info.ExePath)
// err := proc.KillProcess(p)
// if err != nil {
// cmd := proc.GetKillCMD(p.Pid)
// d.EchoError("停止进程%v失败,请手动执行:", p.Pid)
// fmt.Println(cmd.String())
// os.Exit(1)
// }
// d.EchoRun("已终止,正在启动新的守护进程...")
// err = daemon.StartDaemonProcess()
// if err != nil {
// d.EchoFatal(err.Error())
// }
}
if warn != "" {
d.EchoWarn(warn + ",建议执行`kd --restart`重启")
}
}
// if !daemon.ServerIsRunning() {
// err := daemon.StartDaemonProcess()
// if err != nil {
// d.EchoRun("未找到守护进程,正在启动...")
// d.EchoFatal(err.Error())
// }
// running <- true
// }
running <- true
}

Expand All @@ -74,8 +59,6 @@ func Query(query string, noCache bool, longText bool) (r *model.Result, err erro
if !longText {
query = strings.ToLower(query)
}
// query = strings.ToLower(strings.Trim(query, " "))
// query = strings.ReplaceAll(query, "\n", " ")

r = buildResult(query, longText)
r.History = make(chan int, 1)
Expand All @@ -93,12 +76,6 @@ func Query(query string, noCache bool, longText bool) (r *model.Result, err erro
return
}

// if longText {
// r.Found = false
// r.Prompt = "暂不支持长句翻译"
// return
// }

var inNotFound bool
var line int
if !longText {
Expand Down Expand Up @@ -137,17 +114,11 @@ func Query(query string, noCache bool, longText bool) (r *model.Result, err erro
d.EchoFatal("守护进程未启动,请手动执行`kd --daemon`")
}

// FIXME move to server
// if !r.Found {
// err = q.FetchOnline(r)
// // 判断时间
// cache.UpdateQueryCache(r)
// }
return r, err
}

func QueryDaemon(r *model.Result) error {
addr := fmt.Sprintf("localhost:%d", SERVER_PORT)
addr := fmt.Sprintf("localhost:%d", run.SERVER_PORT)
err := q.QueryDaemon(addr, r)
return err
}
Loading