fix(cli): wait for db-worker exit on stop

This commit is contained in:
Mega Yu
2026-04-23 11:38:17 +08:00
parent 8554608722
commit a0feca6510
2 changed files with 85 additions and 9 deletions

View File

@@ -95,6 +95,10 @@
[pid]
(daemon/pid-status pid))
(defn- process-stopped?
[pid]
(not (contains? #{:alive :no-permission} (pid-status pid))))
(defn- read-lock
[path]
(daemon/read-lock path))
@@ -220,7 +224,8 @@
(p/resolved (owner-mismatch-error repo requester-owner lock-owner))
(-> (p/let [_ (shutdown! lock)]
(wait-for (fn []
(p/resolved (not (fs/existsSync path))))
(p/resolved (and (not (fs/existsSync path))
(process-stopped? (:pid lock)))))
{:timeout-ms 5000
:interval-ms 200})
{:ok? true
@@ -232,14 +237,16 @@
(.kill js/process (:pid lock) "SIGTERM")
(catch :default e
(log/warn :cli-server-stop-sigterm-failed e))))
(when (= :not-found (pid-status (:pid lock)))
(remove-lock! path))
(if (fs/existsSync path)
{:ok? false
:error {:code :server-stop-timeout
:message "timed out stopping server"}}
{:ok? true
:data {:repo repo}})))))))))
(let [pid-state (pid-status (:pid lock))]
(when (= :not-found pid-state)
(remove-lock! path))
(if (or (fs/existsSync path)
(= :alive pid-state))
{:ok? false
:error {:code :server-stop-timeout
:message "timed out stopping server"}}
{:ok? true
:data {:repo repo}}))))))))))
(defn start-server!
[config repo]

View File

@@ -166,6 +166,75 @@
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest stop-server-waits-for-process-exit-after-lock-removal
(async done
(let [data-dir (node-helper/create-tmp-dir "cli-server-stop-waits-pid")
repo (str "logseq_db_stop_waits_" (subs (str (random-uuid)) 0 8))
lock-file (cli-server/lock-path data-dir repo)
lock {:repo repo
:pid 424242
:host "127.0.0.1"
:port 9101
:owner-source :cli}
pid-state (atom :alive)]
(fs/mkdirSync (node-path/dirname lock-file) #js {:recursive true})
(fs/writeFileSync lock-file (js/JSON.stringify (clj->js lock)))
(-> (p/with-redefs [daemon/http-request (fn [_] (p/resolved {:status 200 :body ""}))
daemon/pid-status (fn [_] @pid-state)
daemon/wait-for (fn [pred _opts]
(fs/unlinkSync lock-file)
(p/let [first-result (pred)
_ (is (= false first-result))
_ (reset! pid-state :not-found)
second-result (pred)]
(is (= true second-result))
true))]
(cli-server/stop-server! {:data-dir data-dir
:owner-source :cli}
repo))
(p/then (fn [result]
(is (= true (:ok? result)))
(is (= repo (get-in result [:data :repo])))))
(p/catch (fn [e]
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest stop-server-times-out-when-lock-is-gone-but-process-is-still-alive
(async done
(let [data-dir (node-helper/create-tmp-dir "cli-server-stop-timeout-pid")
repo (str "logseq_db_stop_timeout_" (subs (str (random-uuid)) 0 8))
lock-file (cli-server/lock-path data-dir repo)
lock {:repo repo
:pid 424242
:host "127.0.0.1"
:port 9101
:owner-source :cli}
kill-calls (atom [])]
(fs/mkdirSync (node-path/dirname lock-file) #js {:recursive true})
(fs/writeFileSync lock-file (js/JSON.stringify (clj->js lock)))
(-> (test-helper/with-js-property-override
js/process
"kill"
(fn [pid signal]
(swap! kill-calls conj [pid signal])
true)
(fn []
(p/with-redefs [daemon/http-request (fn [_] (p/resolved {:status 200 :body ""}))
daemon/pid-status (fn [_] :alive)
daemon/wait-for (fn [_ _]
(fs/unlinkSync lock-file)
(p/rejected (ex-info "timeout" {:code :timeout})))]
(cli-server/stop-server! {:data-dir data-dir
:owner-source :cli}
repo))))
(p/then (fn [result]
(is (= false (:ok? result)))
(is (= :server-stop-timeout (get-in result [:error :code])))
(is (= [[424242 "SIGTERM"]] @kill-calls))))
(p/catch (fn [e]
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest restart-server-does-not-sigterm-external-owner-daemon
(async done
(let [data-dir (node-helper/create-tmp-dir "cli-server-owner-restart")