Compare commits
No commits in common. "aa340b732352d7a5525eb414d34d16ae8884092d" and "da5281ba0a18adb5884a9034ef6ed2b5d1b0e1ba" have entirely different histories.
aa340b7323
...
da5281ba0a
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,10 +22,6 @@ luajit/.git
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# Claude workspace files
|
||||
.claude
|
||||
CLAUDE.md
|
||||
|
||||
# Test directories and files
|
||||
/*.lua
|
||||
test_fs_dir
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Moonshark
|
||||
|
||||
```bash
|
||||
go build -trimpath -ldflags="-s -w" -o build/moonshark .
|
||||
go build -trimpath -ldflags="-s -w" -o moonshark .
|
||||
```
|
||||
|
||||
4
build.sh
4
build.sh
@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p build
|
||||
go build -trimpath -ldflags="-s -w" -o build/moonshark .
|
||||
4
go.mod
4
go.mod
@ -6,22 +6,22 @@ require git.sharkk.net/Sky/LuaJIT-to-Go v0.5.6
|
||||
|
||||
require (
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
github.com/goccy/go-json v0.10.5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.7.5
|
||||
golang.org/x/crypto v0.40.0
|
||||
zombiezen.com/go/sqlite v1.4.2
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
|
||||
24
go.sum
24
go.sum
@ -48,10 +48,12 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4=
|
||||
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=
|
||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -59,22 +61,22 @@ golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
||||
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
|
||||
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
||||
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
|
||||
modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM=
|
||||
modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
|
||||
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
|
||||
modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
|
||||
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
|
||||
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
@ -85,6 +87,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs=
|
||||
modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g=
|
||||
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
|
||||
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
|
||||
@ -140,7 +140,22 @@ func http_listen(s *luajit.State) int {
|
||||
}
|
||||
|
||||
func http_close_server(s *luajit.State) int {
|
||||
StopAllServers()
|
||||
globalMu.Lock()
|
||||
defer globalMu.Unlock()
|
||||
|
||||
if globalWorkerPool != nil {
|
||||
globalWorkerPool.Close()
|
||||
globalWorkerPool = nil
|
||||
}
|
||||
|
||||
if globalServer != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
globalServer.ShutdownWithContext(ctx)
|
||||
globalServer = nil
|
||||
}
|
||||
|
||||
serverRunning = false
|
||||
s.PushBoolean(true)
|
||||
return 1
|
||||
}
|
||||
@ -320,39 +335,17 @@ func StopAllServers() {
|
||||
globalMu.Lock()
|
||||
defer globalMu.Unlock()
|
||||
|
||||
// Start shutting down both in parallel
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Close worker pool in parallel
|
||||
if globalWorkerPool != nil {
|
||||
wg.Add(1)
|
||||
pool := globalWorkerPool
|
||||
globalWorkerPool.Close()
|
||||
globalWorkerPool = nil
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
pool.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// Shutdown server with 100ms timeout
|
||||
if globalServer != nil {
|
||||
wg.Add(1)
|
||||
server := globalServer
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
globalServer.ShutdownWithContext(ctx)
|
||||
globalServer = nil
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||
defer cancel()
|
||||
if err := server.ShutdownWithContext(ctx); err != nil {
|
||||
// Force close if graceful shutdown times out
|
||||
server.CloseOnShutdown = true
|
||||
_ = server.Shutdown()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
serverRunning = false
|
||||
|
||||
// Wait for both to complete
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@ -218,23 +218,10 @@ func (p *WorkerPool) Close() {
|
||||
}
|
||||
p.closed = true
|
||||
|
||||
// Collect all workers first
|
||||
workers := make([]*Worker, 0, len(p.workers))
|
||||
close(p.workers)
|
||||
for worker := range p.workers {
|
||||
workers = append(workers, worker)
|
||||
worker.Close()
|
||||
}
|
||||
|
||||
// Close all workers in parallel
|
||||
var wg sync.WaitGroup
|
||||
for _, worker := range workers {
|
||||
wg.Add(1)
|
||||
go func(w *Worker) {
|
||||
defer wg.Done()
|
||||
w.Close()
|
||||
}(worker)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (w *Worker) Close() {
|
||||
|
||||
@ -381,12 +381,13 @@ function sqlite.open(database_path)
|
||||
database_path = database_path or ":memory:"
|
||||
|
||||
if database_path ~= ":memory:" then
|
||||
database_path = string.trim(database_path)
|
||||
if string.is_blank(database_path) then
|
||||
database_path = ":memory:"
|
||||
end
|
||||
end
|
||||
|
||||
local conn_id = moonshark.sql_connect("sqlite", database_path:trim())
|
||||
local conn_id = moonshark.sql_connect("sqlite", database_path)
|
||||
if conn_id then
|
||||
local conn = {_id = conn_id}
|
||||
setmetatable(conn, Connection)
|
||||
|
||||
@ -779,26 +779,14 @@ function string.render(template_str, env)
|
||||
return table.concat(output_buffer)
|
||||
end
|
||||
|
||||
-- Helper to retrieve dot-notation table data
|
||||
local function get_nested_value(env, path)
|
||||
local current = env
|
||||
for part in path:gmatch("[^.]+") do
|
||||
if type(current) ~= "table" then
|
||||
return nil
|
||||
end
|
||||
current = current[part]
|
||||
end
|
||||
return current
|
||||
end
|
||||
|
||||
-- Named placeholder processing
|
||||
function string.parse(template_str, env)
|
||||
local pos, output = 1, {}
|
||||
env = env or {}
|
||||
|
||||
while pos <= #template_str do
|
||||
local unescaped_start, unescaped_end, unescaped_name = template_str:find("{{%s*([%w_.]+)%s*}}", pos)
|
||||
local escaped_start, escaped_end, escaped_name = template_str:find("{{{%s*([%w_.]+)%s*}}}", pos)
|
||||
local unescaped_start, unescaped_end, unescaped_name = template_str:find("{{{%s*([%w_]+)%s*}}}", pos)
|
||||
local escaped_start, escaped_end, escaped_name = template_str:find("{{%s*([%w_]+)%s*}}", pos)
|
||||
|
||||
local next_pos, placeholder_end, name, escaped
|
||||
if unescaped_start and (not escaped_start or unescaped_start <= escaped_start) then
|
||||
@ -818,10 +806,10 @@ function string.parse(template_str, env)
|
||||
table.insert(output, text)
|
||||
end
|
||||
|
||||
local value = get_nested_value(env, name)
|
||||
local value = env[name]
|
||||
local str = tostring(value or "")
|
||||
if escaped then
|
||||
str = str:html_special_chars()
|
||||
str:html_special_chars()
|
||||
end
|
||||
table.insert(output, str)
|
||||
|
||||
@ -837,8 +825,8 @@ function string.iparse(template_str, values)
|
||||
values = values or {}
|
||||
|
||||
while pos <= #template_str do
|
||||
local unescaped_start, unescaped_end = template_str:find("{{}}", pos, true)
|
||||
local escaped_start, escaped_end = template_str:find("{{{}}}", pos, true)
|
||||
local unescaped_start, unescaped_end = template_str:find("{{{}}}", pos, true)
|
||||
local escaped_start, escaped_end = template_str:find("{{}}", pos, true)
|
||||
|
||||
local next_pos, placeholder_end, escaped
|
||||
if unescaped_start and (not escaped_start or unescaped_start <= escaped_start) then
|
||||
|
||||
23
moonshark.go
23
moonshark.go
@ -90,26 +90,7 @@ func runWithWatcher(scriptPath string) {
|
||||
|
||||
fmt.Printf("Starting %s in watch mode...\n", scriptPath)
|
||||
|
||||
var hadError bool
|
||||
firstRun := true
|
||||
|
||||
for {
|
||||
// If we had an error on the last run and this isn't the first run,
|
||||
// wait for file changes before retrying
|
||||
if hadError && !firstRun {
|
||||
fmt.Println("Waiting for file changes before retrying...")
|
||||
select {
|
||||
case <-restartCh:
|
||||
fmt.Println("Files changed, retrying...")
|
||||
case <-sigChan:
|
||||
fmt.Println("\nExiting...")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
firstRun = false
|
||||
hadError = false
|
||||
|
||||
// Clear cache before each run
|
||||
state.ClearCache()
|
||||
|
||||
@ -117,14 +98,14 @@ func runWithWatcher(scriptPath string) {
|
||||
luaState, err := state.NewFromScript(scriptPath)
|
||||
if err != nil {
|
||||
log.Printf("Error creating state: %v", err)
|
||||
hadError = true
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := luaState.ExecuteFile(scriptPath); err != nil {
|
||||
log.Printf("Execution error: %v", err)
|
||||
luaState.Close()
|
||||
hadError = true
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
68
watcher.go
68
watcher.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -12,7 +13,6 @@ import (
|
||||
|
||||
type FileWatcher struct {
|
||||
files map[string]time.Time
|
||||
dirs map[string]bool // Track watched directories
|
||||
mu sync.RWMutex
|
||||
restartCh chan bool
|
||||
stopCh chan bool
|
||||
@ -24,7 +24,6 @@ type FileWatcher struct {
|
||||
func NewFileWatcher(debounceMs int) (*FileWatcher, error) {
|
||||
return &FileWatcher{
|
||||
files: make(map[string]time.Time),
|
||||
dirs: make(map[string]bool),
|
||||
restartCh: make(chan bool, 1),
|
||||
stopCh: make(chan bool, 1),
|
||||
debounceMs: debounceMs,
|
||||
@ -52,16 +51,7 @@ func (fw *FileWatcher) AddFile(path string) error {
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) AddDirectory(dir string) error {
|
||||
absDir, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fw.mu.Lock()
|
||||
fw.dirs[absDir] = true
|
||||
fw.mu.Unlock()
|
||||
|
||||
return filepath.Walk(absDir, func(path string, info os.FileInfo, err error) error {
|
||||
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -88,7 +78,6 @@ func (fw *FileWatcher) pollLoop() {
|
||||
return
|
||||
case <-ticker.C:
|
||||
fw.checkFiles()
|
||||
fw.scanForNewFiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +103,7 @@ func (fw *FileWatcher) checkFiles() {
|
||||
now := time.Now()
|
||||
if now.Sub(fw.lastEvent) > time.Duration(fw.debounceMs)*time.Millisecond {
|
||||
fw.lastEvent = now
|
||||
// log.Printf("File changed: %s", path)
|
||||
log.Printf("File changed: %s", path)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
@ -128,57 +117,6 @@ func (fw *FileWatcher) checkFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) scanForNewFiles() {
|
||||
fw.mu.RLock()
|
||||
dirs := make(map[string]bool, len(fw.dirs))
|
||||
maps.Copy(dirs, fw.dirs)
|
||||
existingFiles := make(map[string]bool, len(fw.files))
|
||||
for path := range fw.files {
|
||||
existingFiles[path] = true
|
||||
}
|
||||
fw.mu.RUnlock()
|
||||
|
||||
newFilesFound := false
|
||||
for dir := range dirs {
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".lua") {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !existingFiles[absPath] {
|
||||
fw.mu.Lock()
|
||||
fw.files[absPath] = info.ModTime()
|
||||
fw.mu.Unlock()
|
||||
|
||||
fmt.Printf("New file detected: %s\n", absPath)
|
||||
newFilesFound = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if newFilesFound {
|
||||
now := time.Now()
|
||||
if now.Sub(fw.lastEvent) > time.Duration(fw.debounceMs)*time.Millisecond {
|
||||
fw.lastEvent = now
|
||||
select {
|
||||
case fw.restartCh <- true:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (fw *FileWatcher) Close() error {
|
||||
select {
|
||||
case fw.stopCh <- true:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user