Merge remote-tracking branch 'origin/master' into feat/cliable

This commit is contained in:
rcmerci
2026-04-28 22:59:59 +08:00
77 changed files with 4549 additions and 1133 deletions

View File

@@ -534,6 +534,16 @@
[value]
(contains? #{"true" "1"} value))
(defn- sqlite-too-big-error?
[error]
(let [message (-> (or (ex-message error)
(some-> error .-message)
(str error))
string/lower-case)]
(or (string/includes? message "sqlite_toobig")
(string/includes? message "string or blob too big")
(string/includes? message "statement too long"))))
(defn- handle-sync-snapshot-upload
[^js self request url]
(let [graph-id (graph-id-from-request request)
@@ -556,27 +566,27 @@
(if (and (= encoding snapshot-content-encoding)
(not (exists? js/DecompressionStream)))
(http/error-response "gzip not supported" 500)
(p/let [_ (ensure-schema! self)
_ (when reset?
(storage/set-meta! (.-sql self) snapshot-uploading-meta-key true))
_ (when reset?
(<set-graph-ready-for-use! self graph-id false))
stream (maybe-decompress-stream stream encoding)
count (import-snapshot-stream! self stream reset?)
_ (when finished?
(storage/set-meta! (.-sql self) snapshot-uploading-meta-key false))
_ (when finished?
(when (seq checksum-param)
(storage/set-checksum! (.-sql self) checksum-param)))
_ (when finished?
(<set-graph-ready-for-use! self graph-id true))
_ (when finished?
;; Snapshot replacement resets tx history (`t` may drop to 0).
;; Broadcast current `t` so connected clients can recover.
(ws/broadcast! self nil {:type "changed"
:t (t-now self)}))]
(http/json-response :sync/snapshot-upload {:ok true
:count count})))))))
(p/catch
(p/let [_ (ensure-schema! self)
_ (when reset?
(storage/set-meta! (.-sql self) snapshot-uploading-meta-key true))
_ (when reset?
(<set-graph-ready-for-use! self graph-id false))
stream (maybe-decompress-stream stream encoding)
count (import-snapshot-stream! self stream reset?)
_ (when finished?
(storage/set-meta! (.-sql self) snapshot-uploading-meta-key false))
_ (when finished?
(when (seq checksum-param)
(storage/set-checksum! (.-sql self) checksum-param)))
_ (when finished?
(<set-graph-ready-for-use! self graph-id true))]
(http/json-response :sync/snapshot-upload {:ok true
:count count}))
(fn [error]
(if (sqlite-too-big-error? error)
(http/error-response "snapshot row too large" 413)
(throw error)))))))))
(defn handle [{:keys [^js self request url route]}]
(case (:handler route)

View File

@@ -661,11 +661,10 @@
(is false (str error))
(done)))))))
(deftest finished-snapshot-upload-broadcasts-changed-test
(deftest snapshot-upload-returns-413-when-sqlite-row-is-too-large-test
(async done
(let [sql (test-sql/make-sql)
conn (d/create-conn db-schema/schema)
changed-messages (atom [])
self #js {:sql sql
:conn conn
:schema-ready true
@@ -674,19 +673,17 @@
#js {:method "POST"
:body (js/Uint8Array. 0)})]
(-> (p/with-redefs [sync-handler/import-snapshot-stream! (fn [_self _stream _reset?]
(p/resolved 0))
(p/rejected (js/Error. "string or blob too big: SQLITE_TOOBIG")))
sync-handler/<set-graph-ready-for-use! (fn [_self _graph-id _graph-ready-for-use?]
(p/resolved true))
ws/broadcast! (fn [_self _sender payload]
(swap! changed-messages conj payload))]
(p/resolved true))]
(p/let [resp (sync-handler/handle {:self self
:request request
:url (js/URL. (.-url request))
:route {:handler :sync/snapshot-upload}})]
(is (= 200 (.-status resp)))
(is (= [{:type "changed"
:t (storage/get-t sql)}]
@changed-messages))))
:route {:handler :sync/snapshot-upload}})
text (.text resp)
body (js->clj (js/JSON.parse text) :keywordize-keys true)]
(is (= 413 (.-status resp)))
(is (= {:error "snapshot row too large"} body))))
(p/then (fn []
(done)))
(p/catch (fn [error]