mirror of
https://github.com/penpot/penpot.git
synced 2025-05-14 10:56:44 +02:00
✨ Improve websockets impl
Make it more extensible and move all the websocket unrelated stuff to the new hooks API. Also adds observability from repl.
This commit is contained in:
parent
935639411c
commit
cbc5811290
8 changed files with 429 additions and 265 deletions
|
@ -173,8 +173,7 @@
|
|||
(when (is-authenticated? profile)
|
||||
(->> (rx/of (profile-fetched profile)
|
||||
(fetch-teams)
|
||||
(get-redirect-event)
|
||||
(ws/initialize))
|
||||
(get-redirect-event))
|
||||
(rx/observe-on :async)))))))
|
||||
|
||||
(s/def ::invitation-token ::us/not-empty-string)
|
||||
|
|
|
@ -7,14 +7,19 @@
|
|||
(ns app.main.data.websocket
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as l]
|
||||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.util.websocket :as ws]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(l/set-level! :error)
|
||||
|
||||
(dm/export ws/send!)
|
||||
|
||||
(defonce ws-conn (volatile! nil))
|
||||
|
||||
(defn- prepare-uri
|
||||
[params]
|
||||
(let [base (-> (u/join cf/public-uri "ws/notifications")
|
||||
|
@ -30,35 +35,34 @@
|
|||
[message]
|
||||
(ptk/reify ::send-message
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [ws-conn (:ws-conn state)]
|
||||
(ws/send! ws-conn message)))))
|
||||
(effect [_ _ _]
|
||||
(some-> @ws-conn (ws/send! message)))))
|
||||
|
||||
(defn initialize
|
||||
[]
|
||||
(ptk/reify ::initialize
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [sid (:session-id state)
|
||||
uri (prepare-uri {:session-id sid})]
|
||||
(assoc state :ws-conn (ws/create uri))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [ws-conn (:ws-conn state)
|
||||
stoper (rx/merge
|
||||
(rx/filter (ptk/type? ::finalize) stream)
|
||||
(rx/filter (ptk/type? ::initialize) stream))]
|
||||
(l/trace :hint "event:initialize" :fn "watch")
|
||||
(let [sid (:session-id state)
|
||||
uri (prepare-uri {:session-id sid})
|
||||
ws (ws/create uri)]
|
||||
|
||||
(->> (rx/merge
|
||||
(->> (ws/get-rcv-stream ws-conn)
|
||||
(rx/filter ws/message-event?)
|
||||
(rx/map :payload)
|
||||
(rx/map #(ptk/data-event ::message %)))
|
||||
(->> (ws/get-rcv-stream ws-conn)
|
||||
(rx/filter ws/opened-event?)
|
||||
(rx/map (fn [_] (ptk/data-event ::opened {})))))
|
||||
(rx/take-until stoper))))))
|
||||
(vreset! ws-conn ws)
|
||||
|
||||
(let [stoper (rx/merge
|
||||
(rx/filter (ptk/type? ::finalize) stream)
|
||||
(rx/filter (ptk/type? ::initialize) stream))]
|
||||
|
||||
(->> (rx/merge
|
||||
(->> (ws/get-rcv-stream ws)
|
||||
(rx/filter ws/message-event?)
|
||||
(rx/map :payload)
|
||||
(rx/map #(ptk/data-event ::message %)))
|
||||
(->> (ws/get-rcv-stream ws)
|
||||
(rx/filter ws/opened-event?)
|
||||
(rx/map (fn [_] (ptk/data-event ::opened {})))))
|
||||
(rx/take-until stoper)))))))
|
||||
|
||||
;; --- Finalize Websocket
|
||||
|
||||
|
@ -66,5 +70,6 @@
|
|||
[]
|
||||
(ptk/reify ::finalize
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(some-> (:ws-conn state) ws/close!))))
|
||||
(effect [_ _ _]
|
||||
(l/trace :hint "event:finalize" :fn "effect")
|
||||
(some-> @ws-conn ws/close!))))
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.pages.changes-spec :as pcs]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.websocket :as dws]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -34,51 +33,53 @@
|
|||
(ptk/reify ::initialize
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [subs-id (uuid/next)
|
||||
stoper (rx/filter (ptk/type? ::finalize) stream)
|
||||
(let [stoper (rx/filter (ptk/type? ::finalize) stream)
|
||||
profile-id (:profile-id state)
|
||||
|
||||
initmsg [{:type :subscribe-file
|
||||
:subs-id subs-id
|
||||
:file-id file-id}
|
||||
{:type :subscribe-team
|
||||
:team-id team-id}]
|
||||
initmsg [{:type :subscribe-file
|
||||
:file-id file-id}
|
||||
{:type :subscribe-team
|
||||
:team-id team-id}]
|
||||
|
||||
endmsg {:type :unsubscribe-file
|
||||
:subs-id subs-id}
|
||||
endmsg {:type :unsubscribe-file
|
||||
:file-id file-id}
|
||||
|
||||
stream (->> (rx/merge
|
||||
;; Send the subscription message
|
||||
(->> (rx/from initmsg)
|
||||
(rx/map dws/send))
|
||||
stream (->> (rx/merge
|
||||
;; Send the subscription message
|
||||
(->> (rx/from initmsg)
|
||||
(rx/map dws/send))
|
||||
|
||||
;; Subscribe to notifications of the subscription
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dws/message))
|
||||
(rx/map deref) ;; :library-change events occur in a different file, but need to be processed anyway
|
||||
(rx/filter #(or (= subs-id (:subs-id %)) (= (:type %) :library-change)))
|
||||
(rx/map process-message))
|
||||
;; Subscribe to notifications of the subscription
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dws/message))
|
||||
(rx/map deref)
|
||||
(rx/filter (fn [{:keys [subs-id] :as msg}]
|
||||
(or (= subs-id team-id)
|
||||
(= subs-id profile-id)
|
||||
(= subs-id file-id))))
|
||||
(rx/map process-message))
|
||||
|
||||
;; On reconnect, send again the subscription messages
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dws/opened))
|
||||
(rx/mapcat #(->> (rx/from initmsg)
|
||||
(rx/map dws/send))))
|
||||
;; On reconnect, send again the subscription messages
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dws/opened))
|
||||
(rx/mapcat #(->> (rx/from initmsg)
|
||||
(rx/map dws/send))))
|
||||
|
||||
;; Emit presence event for current user;
|
||||
;; this is because websocket server don't
|
||||
;; emits this for the same user.
|
||||
(rx/of (handle-presence {:type :connect
|
||||
:session-id (:session-id state)
|
||||
:profile-id (:profile-id state)}))
|
||||
;; Emit presence event for current user;
|
||||
;; this is because websocket server don't
|
||||
;; emits this for the same user.
|
||||
(rx/of (handle-presence {:type :connect
|
||||
:session-id (:session-id state)
|
||||
:profile-id (:profile-id state)}))
|
||||
|
||||
;; Emit to all other connected users the current pointer
|
||||
;; position changes.
|
||||
(->> stream
|
||||
(rx/filter ms/pointer-event?)
|
||||
(rx/sample 50)
|
||||
(rx/map #(handle-pointer-send subs-id file-id (:pt %)))))
|
||||
;; Emit to all other connected users the current pointer
|
||||
;; position changes.
|
||||
(->> stream
|
||||
(rx/filter ms/pointer-event?)
|
||||
(rx/sample 50)
|
||||
(rx/map #(handle-pointer-send file-id (:pt %)))))
|
||||
|
||||
(rx/take-until stoper))]
|
||||
(rx/take-until stoper))]
|
||||
|
||||
(rx/concat stream (rx/of (dws/send endmsg)))))))
|
||||
|
||||
|
@ -95,13 +96,12 @@
|
|||
nil))
|
||||
|
||||
(defn- handle-pointer-send
|
||||
[subs-id file-id point]
|
||||
[file-id point]
|
||||
(ptk/reify ::handle-pointer-send
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
message {:type :pointer-update
|
||||
:subs-id subs-id
|
||||
:file-id file-id
|
||||
:page-id page-id
|
||||
:position point}]
|
||||
|
|
|
@ -163,7 +163,9 @@
|
|||
(rx/map #(shapes-changes-persisted file-id %)))))))
|
||||
(rx/catch (fn [cause]
|
||||
(rx/concat
|
||||
(rx/of (rt/assign-exception cause))
|
||||
(if (= :authentication (:type cause))
|
||||
(rx/empty)
|
||||
(rx/of (rt/assign-exception cause)))
|
||||
(rx/throw cause))))))))))
|
||||
|
||||
|
||||
|
|
|
@ -106,7 +106,6 @@
|
|||
|
||||
(js/console.groupEnd msg)))
|
||||
|
||||
|
||||
;; Error on parsing an SVG
|
||||
;; TODO: looks unused and deprecated
|
||||
(defmethod ptk/handle-error :svg-parser
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue