fix 9394 select mailserver based on ping

- if not mailserver was actively selected by user,
use rpc call to get latency for known mailservers
and use the best one
- this happens when `set-current-mailserver` is called which happens
in `change-mailserver` when user unpins his preferred mailserver and when
there's been too many failed attemps to fetch messages or to connect to
then current mailserverm as well as when user logs in.

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2019-11-18 16:46:08 +01:00
parent 67e6ab6055
commit 572e028f32
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
6 changed files with 370 additions and 280 deletions

View File

@ -76,6 +76,7 @@
"settings_saveNodeConfig" {} "settings_saveNodeConfig" {}
"accounts_getAccounts" {} "accounts_getAccounts" {}
"accounts_saveAccounts" {} "accounts_saveAccounts" {}
"mailservers_ping" {}
"mailservers_addMailserver" {} "mailservers_addMailserver" {}
"mailservers_getMailservers" {} "mailservers_getMailservers" {}
"mailservers_deleteMailserver" {} "mailservers_deleteMailserver" {}

View File

@ -245,11 +245,6 @@
(fn [cofx [_ current-fleet mailserver-id]] (fn [cofx [_ current-fleet mailserver-id]]
(mailserver/save-settings cofx current-fleet mailserver-id))) (mailserver/save-settings cofx current-fleet mailserver-id)))
(handlers/register-handler-fx
:mailserver.ui/reconnect-mailserver-pressed
(fn [cofx _]
(mailserver/connect-to-mailserver cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:mailserver.ui/unpin-pressed :mailserver.ui/unpin-pressed
(fn [cofx _] (fn [cofx _]

View File

@ -40,57 +40,42 @@
(def limit (atom constants/default-limit)) (def limit (atom constants/default-limit))
(def success-counter (atom 0)) (def success-counter (atom 0))
(defn connected? [{:keys [db]} id] (defn connected? [db id]
(= (:mailserver/current-id db) id)) (= (:mailserver/current-id db) id))
(defn fetch [{:keys [db] :as cofx} id] (defn fetch [db id]
(get-in db [:mailserver/mailservers (node/current-fleet-key db) id])) (get-in db [:mailserver/mailservers (node/current-fleet-key db) id]))
(defn fetch-current [{:keys [db] :as cofx}] (defn fetch-current [db]
(fetch cofx (:mailserver/current-id db))) (fetch db (:mailserver/current-id db)))
(defn preferred-mailserver-id [{:keys [db] :as cofx}] (defn preferred-mailserver-id [db]
(get-in db [:multiaccount :settings :mailserver (node/current-fleet-key db)])) (get-in db [:multiaccount :settings :mailserver (node/current-fleet-key db)]))
(defn- round-robin (defn mailserver-address->id [db address]
"Find the choice and pick the next one, default to first if not found" (let [current-fleet (node/current-fleet-key db)]
[choices current-id] (:id (some #(when (= address (:address %))
(let [next-index (reduce %)
(fn [index choice] (-> db
(if (= current-id choice) :mailserver/mailservers
(reduced (inc index)) current-fleet
(inc index))) vals)))))
0
choices)]
(nth choices
(mod
next-index
(count choices)))))
(defn selected-or-random-id (defn get-selected-mailserver
"Use the preferred mailserver if set & exists, otherwise picks one randomly "Use the preferred mailserver if set & exists"
if current-id is not set, else round-robin" [db]
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db) (let [current-fleet (node/current-fleet-key db)
current-id (:mailserver/current-id db) current-id (:mailserver/current-id db)
preference (preferred-mailserver-id cofx) preference (preferred-mailserver-id db)]
choices (-> db :mailserver/mailservers current-fleet keys)] (when (and preference
(if (and preference (fetch db preference))
(fetch cofx preference)) preference)))
preference
(if current-id
(round-robin choices current-id)
(rand-nth choices)))))
(fx/defn set-current-mailserver
[{:keys [db] :as cofx}]
{:db (assoc db :mailserver/current-id
(selected-or-random-id cofx))})
(defn add-peer! [enode] (defn add-peer! [enode]
(status/add-peer enode (status/add-peer enode
(handlers/response-handler #(log/debug "mailserver: add-peer success" %) (handlers/response-handler
#(log/error "mailserver: add-peer error" %)))) #(log/debug "mailserver: add-peer success" %)
#(log/error "mailserver: add-peer error" %))))
;; We now wait for a confirmation from the mailserver before marking the message ;; We now wait for a confirmation from the mailserver before marking the message
;; as sent. ;; as sent.
@ -98,8 +83,9 @@
(defn update-mailservers! [enodes] (defn update-mailservers! [enodes]
(status/update-mailservers (status/update-mailservers
(.stringify js/JSON (clj->js enodes)) (.stringify js/JSON (clj->js enodes))
(handlers/response-handler #(log/debug "mailserver: update-mailservers success" %) (handlers/response-handler
#(log/error "mailserver: update-mailservers error" %)))) #(log/debug "mailserver: update-mailservers success" %)
#(log/error "mailserver: update-mailservers error" %))))
(defn remove-peer! [enode] (defn remove-peer! [enode]
(let [args {:jsonrpc "2.0" (let [args {:jsonrpc "2.0"
@ -108,8 +94,9 @@
:params [enode]} :params [enode]}
payload (.stringify js/JSON (clj->js args))] payload (.stringify js/JSON (clj->js args))]
(status/call-private-rpc payload (status/call-private-rpc payload
(handlers/response-handler #(log/debug "mailserver: remove-peer success" %) (handlers/response-handler
#(log/error "mailserver: remove-peer error" %))))) #(log/debug "mailserver: remove-peer success" %)
#(log/error "mailserver: remove-peer error" %)))))
(re-frame/reg-fx (re-frame/reg-fx
:mailserver/add-peer :mailserver/add-peer
@ -151,10 +138,13 @@
(reset! success-counter 0))) (reset! success-counter 0)))
(defn mark-trusted-peer! [enode] (defn mark-trusted-peer! [enode]
(json-rpc/call {:method "shh_markTrustedPeer" (json-rpc/call
:params [enode] {:method "shh_markTrustedPeer"
:on-success #(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-success %]) :params [enode]
:on-error #(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-error %])})) :on-success
#(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-success %])
:on-error
#(re-frame/dispatch [:mailserver.callback/mark-trusted-peer-error %])}))
(re-frame/reg-fx (re-frame/reg-fx
:mailserver/mark-trusted-peer :mailserver/mark-trusted-peer
@ -163,11 +153,16 @@
(fx/defn generate-mailserver-symkey (fx/defn generate-mailserver-symkey
[{:keys [db] :as cofx} {:keys [password id] :as mailserver}] [{:keys [db] :as cofx} {:keys [password id] :as mailserver}]
(let [current-fleet (node/current-fleet-key db)] (let [current-fleet (node/current-fleet-key db)]
{:db (assoc-in db [:mailserver/mailservers current-fleet id :generating-sym-key?] true) {:db (assoc-in db [:mailserver/mailservers current-fleet id
:generating-sym-key?]
true)
:shh/generate-sym-key-from-password :shh/generate-sym-key-from-password
[{:password password [{:password password
:on-success (fn [_ sym-key-id] :on-success
(re-frame/dispatch [:mailserver.callback/generate-mailserver-symkey-success mailserver sym-key-id])) (fn [_ sym-key-id]
(re-frame/dispatch
[:mailserver.callback/generate-mailserver-symkey-success
mailserver sym-key-id]))
:on-error #(log/error "mailserver: get-sym-key error" %)}]})) :on-error #(log/error "mailserver: get-sym-key error" %)}]}))
(defn registered-peer? (defn registered-peer?
@ -181,7 +176,8 @@
(fx/defn mark-trusted-peer (fx/defn mark-trusted-peer
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as mailserver} (fetch-current cofx)] (let [{:keys [address sym-key-id generating-sym-key?] :as mailserver}
(fetch-current db)]
(fx/merge cofx (fx/merge cofx
{:db (update-mailserver-state db :added) {:db (update-mailserver-state db :added)
:mailserver/mark-trusted-peer address} :mailserver/mark-trusted-peer address}
@ -190,19 +186,22 @@
(fx/defn add-peer (fx/defn add-peer
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [address sym-key-id generating-sym-key?] :as mailserver} (fetch-current cofx)] (let [{:keys [address sym-key-id generating-sym-key?] :as mailserver}
(fx/merge cofx (fetch-current db)]
{:db (-> db (fx/merge
(update-mailserver-state :connecting) cofx
(update :mailserver/connection-checks inc)) {:db (-> db
:mailserver/add-peer address (update-mailserver-state :connecting)
;; Any message sent before this takes effect will not be marked as sent (update :mailserver/connection-checks inc))
;; probably we should improve the UX so that is more transparent to the user :mailserver/add-peer address
:mailserver/update-mailservers [address] ;; Any message sent before this takes effect will not be marked as sent
:utils/dispatch-later [{:ms constants/connection-timeout ;; probably we should improve the UX so that is more transparent to the
:dispatch [:mailserver/check-connection-timeout]}]} ;; user
(when-not (or sym-key-id generating-sym-key?) :mailserver/update-mailservers [address]
(generate-mailserver-symkey mailserver))))) :utils/dispatch-later [{:ms constants/connection-timeout
:dispatch [:mailserver/check-connection-timeout]}]}
(when-not (or sym-key-id generating-sym-key?)
(generate-mailserver-symkey mailserver)))))
(defn executing-gap-request? (defn executing-gap-request?
[{:mailserver/keys [current-request fetching-gaps-in-progress]}] [{:mailserver/keys [current-request fetching-gaps-in-progress]}]
@ -218,8 +217,9 @@
this is successful this is successful
A connection-check is made after `connection timeout` is reached and A connection-check is made after `connection timeout` is reached and
mailserver-state is changed to error if it is not connected by then" mailserver-state is changed to error if it is not connected by then"
{:events [:mailserver.ui/reconnect-mailserver-pressed]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [address]} (fetch-current cofx) (let [{:keys [address]} (fetch-current db)
{:keys [peers-summary]} db {:keys [peers-summary]} db
added? (registered-peer? peers-summary address) added? (registered-peer? peers-summary address)
gap-request? (executing-gap-request? db)] gap-request? (executing-gap-request? db)]
@ -232,6 +232,47 @@
(mark-trusted-peer) (mark-trusted-peer)
(add-peer))))) (add-peer)))))
(defn pool-size [fleet-size]
(.ceil js/Math (/ fleet-size 4)))
(fx/defn get-mailservers-latency
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
addresses (mapv :address (-> db
:mailserver/mailservers
current-fleet
vals))]
{::json-rpc/call [{:method "mailservers_ping"
:params [{:addresses addresses
:timeoutMs 500}]
:on-success
#(re-frame/dispatch [::get-latency-callback %])}]}))
(fx/defn set-current-mailserver-with-lowest-latency
"Picks a random mailserver amongs the ones with the lowest latency
The results with error are ignored
The pool size is 1/4 of the mailservers were pinged successfully"
{:events [::get-latency-callback]}
[{:keys [db] :as cofx} latency-results]
(let [successful-pings (remove :error latency-results)]
(when (seq successful-pings)
(let [address (-> (take (pool-size (count successful-pings))
(sort-by :rttMs successful-pings))
rand-nth
:address)
mailserver-id (mailserver-address->id db address)]
(fx/merge cofx
{:db (assoc db :mailserver/current-id mailserver-id)}
(connect-to-mailserver))))))
(fx/defn set-current-mailserver
[{:keys [db] :as cofx}]
(if-let [mailserver-id (get-selected-mailserver db)]
(fx/merge cofx
{:db (assoc db :mailserver/current-id mailserver-id)}
(connect-to-mailserver))
(get-mailservers-latency cofx)))
(fx/defn peers-summary-change (fx/defn peers-summary-change
"There is only 2 summary changes that require mailserver action: "There is only 2 summary changes that require mailserver action:
- mailserver disconnected: we try to reconnect - mailserver disconnected: we try to reconnect
@ -239,7 +280,7 @@
[{:keys [db] :as cofx} previous-summary] [{:keys [db] :as cofx} previous-summary]
(when (:multiaccount db) (when (:multiaccount db)
(let [{:keys [peers-summary peers-count]} db (let [{:keys [peers-summary peers-count]} db
{:keys [address sym-key-id] :as mailserver} (fetch-current cofx) {:keys [address sym-key-id] :as mailserver} (fetch-current db)
mailserver-was-registered? (registered-peer? previous-summary mailserver-was-registered? (registered-peer? previous-summary
address) address)
mailserver-is-registered? (registered-peer? peers-summary mailserver-is-registered? (registered-peer? peers-summary
@ -260,7 +301,8 @@
whisper-tolerance (:whisper-drift-tolerance protocol/whisper-opts) whisper-tolerance (:whisper-drift-tolerance protocol/whisper-opts)
adjustment (+ whisper-tolerance ttl) adjustment (+ whisper-tolerance ttl)
adjusted-from (- (max from adjustment) adjustment)] adjusted-from (- (max from adjustment) adjustment)]
(log/debug "Adjusting mailserver request" "from:" from "adjusted-from:" adjusted-from) (log/debug "Adjusting mailserver request" "from:" from
"adjusted-from:" adjusted-from)
adjusted-from)) adjusted-from))
(defn chats->never-synced-public-chats [chats] (defn chats->never-synced-public-chats [chats]
@ -269,25 +311,33 @@
(fx/defn handle-request-success [{{:keys [chats] :as db} :db} (fx/defn handle-request-success [{{:keys [chats] :as db} :db}
{:keys [request-id topics]}] {:keys [request-id topics]}]
(when (:mailserver/current-request db) (when (:mailserver/current-request db)
(let [by-topic-never-synced-chats (reduce-kv (let [by-topic-never-synced-chats
#(assoc %1 (transport.utils/get-topic %2) %3) (reduce-kv
{} #(assoc %1 (transport.utils/get-topic %2) %3)
(chats->never-synced-public-chats chats)) {}
never-synced-chats-in-this-request (select-keys by-topic-never-synced-chats (vec topics))] (chats->never-synced-public-chats chats))
never-synced-chats-in-this-request
(select-keys by-topic-never-synced-chats (vec topics))]
(if (seq never-synced-chats-in-this-request) (if (seq never-synced-chats-in-this-request)
{:db (-> db {:db
((fn [db] (reduce (-> db
(fn [db chat] ((fn [db]
(assoc-in db [:chats (:chat-id chat) :join-time-mail-request-id] request-id)) (reduce
db (fn [db chat]
(vals never-synced-chats-in-this-request)))) (assoc-in db [:chats (:chat-id chat)
(assoc-in [:mailserver/current-request :request-id] request-id))} :join-time-mail-request-id] request-id))
{:db (assoc-in db [:mailserver/current-request :request-id] request-id)})))) db
(vals never-synced-chats-in-this-request))))
(assoc-in [:mailserver/current-request :request-id]
request-id))}
{:db (assoc-in db [:mailserver/current-request :request-id]
request-id)}))))
(defn request-messages! (defn request-messages!
[{:keys [sym-key-id address]} {:keys [topics cursor to from force-to?] :as request}] [{:keys [sym-key-id address]}
;; Add some room to from, unless we break day boundaries so that messages that have {:keys [topics cursor to from force-to?] :as request}]
;; been received after the last request are also fetched ;; Add some room to from, unless we break day boundaries so that
;; messages that have been received after the last request are also fetched
(let [actual-from (adjust-request-for-transit-time from) (let [actual-from (adjust-request-for-transit-time from)
actual-limit (or (:limit request) actual-limit (or (:limit request)
@limit)] @limit)]
@ -299,23 +349,30 @@
" range " (- to from) " range " (- to from)
" cursor " cursor " cursor " cursor
" limit " actual-limit) " limit " actual-limit)
(json-rpc/call {:method "shhext_requestMessages" (json-rpc/call
:params [(cond-> {:topics topics {:method "shhext_requestMessages"
:mailServerPeer address :params [(cond-> {:topics topics
:symKeyID sym-key-id :mailServerPeer address
:timeout constants/request-timeout :symKeyID sym-key-id
:limit actual-limit :timeout constants/request-timeout
:cursor cursor :limit actual-limit
:from actual-from} :cursor cursor
force-to? :from actual-from}
(assoc :to to))] force-to?
:on-success (fn [request-id] (assoc :to to))]
(log/info "mailserver: messages request success for topic " topics "from" from "to" to) :on-success (fn [request-id]
(re-frame/dispatch [:mailserver.callback/request-success {:request-id request-id :topics topics}])) (log/info "mailserver: messages request success for topic "
:on-error (fn [error] topics "from" from "to" to)
(log/error "mailserver: messages request error for topic " topics ": " error) (re-frame/dispatch
(utils/set-timeout #(re-frame/dispatch [:mailserver.callback/resend-request {:request-id nil}]) [:mailserver.callback/request-success
constants/backoff-interval-ms))}))) {:request-id request-id :topics topics}]))
:on-error (fn [error]
(log/error "mailserver: messages request error for topic "
topics ": " error)
(utils/set-timeout
#(re-frame/dispatch
[:mailserver.callback/resend-request {:request-id nil}])
constants/backoff-interval-ms))})))
(re-frame/reg-fx (re-frame/reg-fx
:mailserver/request-messages :mailserver/request-messages
@ -325,7 +382,7 @@
(defn get-mailserver-when-ready (defn get-mailserver-when-ready
"return the mailserver if the mailserver is ready" "return the mailserver if the mailserver is ready"
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{:keys [sym-key-id] :as mailserver} (fetch-current cofx) (let [{:keys [sym-key-id] :as mailserver} (fetch-current db)
mailserver-state (:mailserver/state db)] mailserver-state (:mailserver/state db)]
(when (and (= :connected mailserver-state) (when (and (= :connected mailserver-state)
sym-key-id) sym-key-id)
@ -388,10 +445,10 @@
requests (prepare-messages-requests cofx request-to)] requests (prepare-messages-requests cofx request-to)]
(log/debug "Mailserver: planned requests " requests) (log/debug "Mailserver: planned requests " requests)
(if-let [request (first requests)] (if-let [request (first requests)]
{:db (assoc db {:db (assoc db
:mailserver/pending-requests (count requests) :mailserver/pending-requests (count requests)
:mailserver/current-request request :mailserver/current-request request
:mailserver/request-to request-to) :mailserver/request-to request-to)
:mailserver/request-messages {:mailserver mailserver :mailserver/request-messages {:mailserver mailserver
:request request}} :request request}}
{:db (dissoc db {:db (dissoc db
@ -415,18 +472,21 @@
mailserver is ready" mailserver is ready"
[{:keys [db] :as cofx} {:keys [id]} sym-key-id] [{:keys [db] :as cofx} {:keys [id]} sym-key-id]
(let [current-fleet (node/current-fleet-key db)] (let [current-fleet (node/current-fleet-key db)]
(fx/merge cofx (fx/merge
{:db (-> db cofx
(assoc-in [:mailserver/mailservers current-fleet id :sym-key-id] sym-key-id) {:db (-> db
(update-in [:mailserver/mailservers current-fleet id] dissoc :generating-sym-key?))} (assoc-in [:mailserver/mailservers current-fleet id :sym-key-id]
(process-next-messages-request)))) sym-key-id)
(update-in [:mailserver/mailservers current-fleet id]
dissoc :generating-sym-key?))}
(process-next-messages-request))))
(fx/defn change-mailserver (fx/defn change-mailserver
"mark mailserver status as `:error` if custom mailserver is used "mark mailserver status as `:error` if custom mailserver is used
otherwise try to reconnect to another mailserver" otherwise try to reconnect to another mailserver"
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(when-not (zero? (:peers-count db)) (when-not (zero? (:peers-count db))
(if-let [preferred-mailserver (preferred-mailserver-id cofx)] (if-let [preferred-mailserver (preferred-mailserver-id db)]
(let [current-fleet (node/current-fleet-key db)] (let [current-fleet (node/current-fleet-key db)]
{:db {:db
(update-mailserver-state db :error) (update-mailserver-state db :error)
@ -444,11 +504,10 @@
current-fleet current-fleet
preferred-mailserver]) preferred-mailserver])
:style "default"}]}}) :style "default"}]}})
(let [{:keys [address]} (fetch-current cofx)] (let [{:keys [address]} (fetch-current db)]
(fx/merge cofx (fx/merge cofx
{:mailserver/remove-peer address} {:mailserver/remove-peer address}
(set-current-mailserver) (set-current-mailserver))))))
(connect-to-mailserver))))))
(fx/defn check-connection (fx/defn check-connection
"connection-checks counter is used to prevent changing "connection-checks counter is used to prevent changing
@ -659,22 +718,23 @@
ranges (:mailserver/ranges db) ranges (:mailserver/ranges db)
prepared-new-gaps (prepare-new-gaps new-gaps ranges request chat-ids)] prepared-new-gaps (prepare-new-gaps new-gaps ranges request chat-ids)]
(fx/merge cofx (fx/merge
{:db cofx
(reduce (fn [db chat-id] {:db
(let [chats-deleted-gaps (get deleted-gaps chat-id) (reduce (fn [db chat-id]
chats-updated-gaps (merge (get updated-gaps chat-id) (let [chats-deleted-gaps (get deleted-gaps chat-id)
(get prepared-new-gaps chat-id))] chats-updated-gaps (merge (get updated-gaps chat-id)
(update-in db [:mailserver/gaps chat-id] (get prepared-new-gaps chat-id))]
(fn [chat-gaps] (update-in db [:mailserver/gaps chat-id]
(-> (apply dissoc chat-gaps chats-deleted-gaps) (fn [chat-gaps]
(merge chats-updated-gaps)))))) (-> (apply dissoc chat-gaps chats-deleted-gaps)
db (merge chats-updated-gaps))))))
chat-ids)} db
(data-store.mailservers/delete-gaps (mapcat val deleted-gaps)) chat-ids)}
(data-store.mailservers/save-gaps (data-store.mailservers/delete-gaps (mapcat val deleted-gaps))
(concat (mapcat vals (vals updated-gaps)) (data-store.mailservers/save-gaps
(mapcat vals (vals prepared-new-gaps))))))) (concat (mapcat vals (vals updated-gaps))
(mapcat vals (vals prepared-new-gaps)))))))
(fx/defn update-chats-and-gaps (fx/defn update-chats-and-gaps
[cofx cursor] [cofx cursor]
@ -714,33 +774,36 @@
(if (seq cursor) (if (seq cursor)
(when-let [mailserver (get-mailserver-when-ready cofx)] (when-let [mailserver (get-mailserver-when-ready cofx)]
(let [request-with-cursor (assoc request :cursor cursor)] (let [request-with-cursor (assoc request :cursor cursor)]
{:db (assoc db :mailserver/current-request request-with-cursor) {:db (assoc db :mailserver/current-request request-with-cursor)
:mailserver/request-messages {:mailserver mailserver :mailserver/request-messages {:mailserver mailserver
:request request-with-cursor}})) :request request-with-cursor}}))
(let [{:keys [gap chat-id]} request] (let [{:keys [gap chat-id]} request]
(fx/merge cofx (fx/merge
{:db (-> db cofx
(dissoc :mailserver/current-request) {:db (-> db
(update :mailserver/requests-from (dissoc :mailserver/current-request)
#(apply dissoc % topics)) (update :mailserver/requests-from
(update :mailserver/requests-to #(apply dissoc % topics))
#(apply dissoc % topics)) (update :mailserver/requests-to
(update :mailserver/topics merge mailserver-topics) #(apply dissoc % topics))
(update :mailserver/fetching-gaps-in-progress (update :mailserver/topics merge mailserver-topics)
(fn [gaps] (update :mailserver/fetching-gaps-in-progress
(if gap (fn [gaps]
(update gaps chat-id dissoc gap) (if gap
gaps))) (update gaps chat-id dissoc gap)
(update :mailserver/planned-gap-requests gaps)))
dissoc gap)) (update :mailserver/planned-gap-requests
::json-rpc/call dissoc gap))
(mapv (fn [[topic mailserver-topic]] ::json-rpc/call
{:method "mailservers_addMailserverTopic" (mapv (fn [[topic mailserver-topic]]
:params [(assoc mailserver-topic :topic topic)] {:method "mailservers_addMailserverTopic"
:on-success #(log/debug "added mailserver-topic successfully") :params [(assoc mailserver-topic :topic topic)]
:on-failure #(log/error "failed to delete mailserver topic" %)}) :on-success
mailserver-topics)} #(log/debug "added mailserver-topic successfully")
(process-next-messages-request)))))))) :on-failure
#(log/error "failed to delete mailserver topic" %)})
mailserver-topics)}
(process-next-messages-request))))))))
(fx/defn retry-next-messages-request (fx/defn retry-next-messages-request
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -772,21 +835,23 @@
(fx/merge (fx/merge
cofx cofx
{:mailserver/increase-limit [] {:mailserver/increase-limit []
:dispatch-n (map :dispatch-n
#(identity [:chat.ui/join-time-messages-checked %]) (map
never-synced-chats-in-request)} #(identity [:chat.ui/join-time-messages-checked %])
never-synced-chats-in-request)}
(update-chats-and-gaps cursor) (update-chats-and-gaps cursor)
(update-mailserver-topics {:request-id requestID (update-mailserver-topics {:request-id requestID
:cursor cursor})) :cursor cursor}))
(fx/merge (fx/merge
cofx cofx
{:mailserver/increase-limit [] {:mailserver/increase-limit []
:dispatch-later (vec :dispatch-later
(map (vec
#(identity (map
{:ms 1000 #(identity
:dispatch [:chat.ui/join-time-messages-checked %]}) {:ms 1000
never-synced-chats-in-request))} :dispatch [:chat.ui/join-time-messages-checked %]})
never-synced-chats-in-request))}
(update-chats-and-gaps cursor) (update-chats-and-gaps cursor)
(update-mailserver-topics {:request-id requestID (update-mailserver-topics {:request-id requestID
:cursor cursor}))) :cursor cursor})))
@ -803,18 +868,20 @@
(let [mailserver-error (:mailserver/request-error db)] (let [mailserver-error (:mailserver/request-error db)]
{:utils/show-confirmation {:utils/show-confirmation
{:title (i18n/label :t/mailserver-request-error-title) {:title (i18n/label :t/mailserver-request-error-title)
:content (i18n/label :t/mailserver-request-error-content {:error mailserver-error}) :content (i18n/label :t/mailserver-request-error-content
{:error mailserver-error})
:on-accept #(re-frame/dispatch [:mailserver.ui/retry-request-pressed]) :on-accept #(re-frame/dispatch [:mailserver.ui/retry-request-pressed])
:confirm-button-text (i18n/label :t/mailserver-request-retry)}})) :confirm-button-text (i18n/label :t/mailserver-request-retry)}}))
(fx/defn fetch-history (fx/defn fetch-history
"Retrive a list of topics given a chat id, set them to the specified time interval "Retrive a list of topics given a chat id, set them to the specified
and start a mailserver request" time interval and start a mailserver request"
[{:keys [db] :as cofx} chat-id {:keys [from to]}] [{:keys [db] :as cofx} chat-id {:keys [from to]}]
(let [topics (mailserver.topics/topics-for-chat (let [topics (mailserver.topics/topics-for-chat
db db
chat-id)] chat-id)]
(log/debug "fetch-history" "chat-id:" chat-id "from-timestamp:" from "topics:" topics) (log/debug "fetch-history" "chat-id:" chat-id "from-timestamp:"
from "topics:" topics)
(fx/merge cofx (fx/merge cofx
{:db (reduce {:db (reduce
(fn [db topic] (fn [db topic]
@ -833,8 +900,8 @@
(map (map
(fn [{:keys [from to id]}] (fn [{:keys [from to id]}]
[id [id
{:from (max from {:from (max from
(- to constants/max-request-range)) (- to constants/max-request-range))
:to to :to to
:force-to? true :force-to? true
:topics topics :topics topics
@ -885,12 +952,16 @@
(dissoc :mailserver/planned-gap-requests))} (dissoc :mailserver/planned-gap-requests))}
mailserver mailserver
(let [{:keys [topics from to cursor limit] :as request} current-request] (let [{:keys [topics from to cursor limit] :as request}
(log/info "mailserver: message request " request-id "expired for mailserver topic" topics "from" from "to" to "cursor" cursor "limit" (decrease-limit)) current-request]
{:db (update-in db [:mailserver/current-request :attempts] inc) (log/info "mailserver: message request " request-id
"expired for mailserver topic" topics "from" from
"to" to "cursor" cursor "limit" (decrease-limit))
{:db (update-in db [:mailserver/current-request :attempts] inc)
:mailserver/decrease-limit [] :mailserver/decrease-limit []
:mailserver/request-messages {:mailserver mailserver :mailserver/request-messages
:request (assoc request :limit (decrease-limit))}}) {:mailserver mailserver
:request (assoc request :limit (decrease-limit))}})
:else :else
{:mailserver/decrease-limit []})))))) {:mailserver/decrease-limit []}))))))
@ -901,8 +972,10 @@
{:mailserver/set-limit constants/default-limit} {:mailserver/set-limit constants/default-limit}
(set-current-mailserver))) (set-current-mailserver)))
(def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") (def enode-address-regex
(def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
(def enode-url-regex
#"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
(defn- extract-address-components [address] (defn- extract-address-components [address]
(rest (re-matches #"enode://(.*)@(.*)" address))) (rest (re-matches #"enode://(.*)@(.*)" address)))
@ -948,7 +1021,7 @@
(def default? (comp not :user-defined fetch)) (def default? (comp not :user-defined fetch))
(fx/defn edit [{:keys [db] :as cofx} id] (fx/defn edit [{:keys [db] :as cofx} id]
(let [{:keys [id address password name]} (fetch cofx id) (let [{:keys [id address password name]} (fetch db id)
url (when address (build-url address password))] url (when address (build-url address password))]
(fx/merge cofx (fx/merge cofx
(set-input :id id) (set-input :id id)
@ -966,16 +1039,17 @@
[{{:mailserver.edit/keys [mailserver] :keys [multiaccount] :as db} :db [{{:mailserver.edit/keys [mailserver] :keys [multiaccount] :as db} :db
random-id-generator :random-id-generator :as cofx}] random-id-generator :random-id-generator :as cofx}]
(let [{:keys [name url id]} mailserver (let [{:keys [name url id]} mailserver
current-fleet (node/current-fleet-key db) current-fleet (node/current-fleet-key db)
mailserver (build mailserver (build
(or (:value id) (or (:value id)
(keyword (string/replace (random-id-generator) "-" ""))) (keyword (string/replace (random-id-generator) "-" "")))
(:value name) (:value name)
(:value url)) (:value url))
current (connected? cofx (:id mailserver))] current (connected? db (:id mailserver))]
{:db (-> db {:db (-> db
(dissoc :mailserver.edit/mailserver) (dissoc :mailserver.edit/mailserver)
(assoc-in [:mailserver/mailservers current-fleet (:id mailserver)] mailserver)) (assoc-in [:mailserver/mailservers current-fleet (:id mailserver)]
mailserver))
::json-rpc/call ::json-rpc/call
[{:method "mailservers_addMailserver" [{:method "mailservers_addMailserver"
:params [(mailserver->rpc mailserver current-fleet)] :params [(mailserver->rpc mailserver current-fleet)]
@ -990,13 +1064,13 @@
:dispatch [:navigate-back]})) :dispatch [:navigate-back]}))
(defn can-delete? (defn can-delete?
[cofx id] [db id]
(not (or (default? cofx id) (not (or (default? db id)
(connected? cofx id)))) (connected? db id))))
(fx/defn delete (fx/defn delete
[{:keys [db] :as cofx} id] [{:keys [db] :as cofx} id]
(if (can-delete? cofx id) (if (can-delete? db id)
{:db (update-in db {:db (update-in db
[:mailserver/mailservers (node/current-fleet-key db)] [:mailserver/mailservers (node/current-fleet-key db)]
dissoc id) dissoc id)
@ -1012,12 +1086,16 @@
[{:keys [db]} mailserver-id] [{:keys [db]} mailserver-id]
(let [current-fleet (node/current-fleet-key db)] (let [current-fleet (node/current-fleet-key db)]
{:ui/show-confirmation {:ui/show-confirmation
{:title (i18n/label :t/close-app-title) {:title (i18n/label :t/close-app-title)
:content (i18n/label :t/connect-mailserver-content :content
{:name (get-in db [:mailserver/mailservers current-fleet mailserver-id :name])}) (i18n/label :t/connect-mailserver-content
{:name (get-in db [:mailserver/mailservers
current-fleet mailserver-id :name])})
:confirm-button-text (i18n/label :t/close-app-button) :confirm-button-text (i18n/label :t/close-app-button)
:on-accept #(re-frame/dispatch [:mailserver.ui/connect-confirmed current-fleet mailserver-id]) :on-accept
:on-cancel nil}})) #(re-frame/dispatch
[:mailserver.ui/connect-confirmed current-fleet mailserver-id])
:on-cancel nil}}))
(fx/defn show-delete-confirmation (fx/defn show-delete-confirmation
[{:keys [db]} mailserver-id] [{:keys [db]} mailserver-id]
@ -1025,7 +1103,8 @@
{:title (i18n/label :t/delete-mailserver-title) {:title (i18n/label :t/delete-mailserver-title)
:content (i18n/label :t/delete-mailserver-are-you-sure) :content (i18n/label :t/delete-mailserver-are-you-sure)
:confirm-button-text (i18n/label :t/delete-mailserver) :confirm-button-text (i18n/label :t/delete-mailserver)
:on-accept #(re-frame/dispatch [:mailserver.ui/delete-confirmed mailserver-id])}}) :on-accept #(re-frame/dispatch
[:mailserver.ui/delete-confirmed mailserver-id])}})
(fx/defn set-url-from-qr (fx/defn set-url-from-qr
[cofx url] [cofx url]
@ -1034,7 +1113,7 @@
(fx/defn save-settings (fx/defn save-settings
[{:keys [db] :as cofx} current-fleet mailserver-id] [{:keys [db] :as cofx} current-fleet mailserver-id]
(let [{:keys [address]} (fetch-current cofx) (let [{:keys [address]} (fetch-current db)
settings (get-in db [:multiaccount :settings]) settings (get-in db [:multiaccount :settings])
;; Check if previous mailserver was pinned ;; Check if previous mailserver was pinned
pinned? (get-in settings [:mailserver current-fleet])] pinned? (get-in settings [:mailserver current-fleet])]
@ -1043,16 +1122,18 @@
:mailserver/remove-peer address} :mailserver/remove-peer address}
(connect-to-mailserver) (connect-to-mailserver)
(when pinned? (when pinned?
(multiaccounts.update/update-settings (assoc-in settings [:mailserver current-fleet] mailserver-id) (multiaccounts.update/update-settings
{}))))) (assoc-in settings [:mailserver current-fleet] mailserver-id)
{})))))
(fx/defn unpin (fx/defn unpin
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db) (let [current-fleet (node/current-fleet-key db)
settings (get-in db [:multiaccount :settings])] settings (get-in db [:multiaccount :settings])]
(fx/merge cofx (fx/merge cofx
(multiaccounts.update/update-settings (update settings :mailserver dissoc current-fleet) (multiaccounts.update/update-settings
{}) (update settings :mailserver dissoc current-fleet)
{})
(change-mailserver)))) (change-mailserver))))
(fx/defn pin (fx/defn pin
@ -1061,8 +1142,9 @@
mailserver-id (:mailserver/current-id db) mailserver-id (:mailserver/current-id db)
settings (get-in db [:multiaccount :settings])] settings (get-in db [:multiaccount :settings])]
(fx/merge cofx (fx/merge cofx
(multiaccounts.update/update-settings (assoc-in settings [:mailserver current-fleet] mailserver-id) (multiaccounts.update/update-settings
{})))) (assoc-in settings [:mailserver current-fleet] mailserver-id)
{}))))
(fx/defn load-gaps-fx [{:keys [db] :as cofx} chat-id] (fx/defn load-gaps-fx [{:keys [db] :as cofx} chat-id]
(when-not (get-in db [:chats chat-id :gaps-loaded?]) (when-not (get-in db [:chats chat-id :gaps-loaded?])
@ -1073,10 +1155,12 @@
{:events [::gaps-loaded]} {:events [::gaps-loaded]}
[{:keys [db now] :as cofx} chat-id gaps] [{:keys [db now] :as cofx} chat-id gaps]
(let [now-s (quot now 1000) (let [now-s (quot now 1000)
outdated-gaps (into [] (comp (filter #(< (:to %) outdated-gaps
(- now-s constants/max-gaps-range))) (into []
(map :id)) (comp (filter #(< (:to %)
(vals gaps)) (- now-s constants/max-gaps-range)))
(map :id))
(vals gaps))
gaps (apply dissoc gaps outdated-gaps)] gaps (apply dissoc gaps outdated-gaps)]
(fx/merge (fx/merge
cofx cofx

View File

@ -42,8 +42,7 @@
(fetch-node-info-fx) (fetch-node-info-fx)
(pairing/init) (pairing/init)
(publisher/start-fx) (publisher/start-fx)
(mailserver/initialize-mailserver) (mailserver/initialize-mailserver)))
(mailserver/connect-to-mailserver)))
(fx/defn stop-whisper (fx/defn stop-whisper
"Stops whisper protocol" "Stops whisper protocol"

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "develop", "version": "v0.35.1",
"commit-sha1": "5f6c7008e19227392589a917def8db3780fcc5db", "commit-sha1": "4769fb91c3247c72c21013bf36194843d8d72d18",
"src-sha256": "0akpf4k7i5rpna0vb2m6lsy7lgsgv19g5lszxhysiacpf37q0hxv" "src-sha256": "1b6050kvnvf69gqw5llb7gb5v25pq6vbhkf9nznk9ra2spasqqzy"
} }

View File

@ -45,14 +45,14 @@
:peers-count 1}}))))) :peers-count 1}})))))
(testing "there's not a preferred mailserver" (testing "there's not a preferred mailserver"
(testing "it changes the mailserver" (testing "it changes the mailserver"
(is (= :a (is (= "mailservers_ping"
(get-in (get-in
(mailserver/change-mailserver (mailserver/change-mailserver
{:db {:mailserver/mailservers {:staging {:a "b"}} {:db {:mailserver/mailservers {:staging {:a "b"}}
:multiaccount {:settings :multiaccount {:settings
{:fleet :staging}} {:fleet :staging}}
:peers-count 1}}) :peers-count 1}})
[:db :mailserver/current-id])))) [::json-rpc/call 0 :method]))))
(testing "it does not show the popup" (testing "it does not show the popup"
(is (not (:ui/show-confirmation (mailserver/change-mailserver (is (not (:ui/show-confirmation (mailserver/change-mailserver
{:db {:peers-count 1}})))))))) {:db {:peers-count 1}}))))))))
@ -179,73 +179,82 @@
(deftest connected-mailserver (deftest connected-mailserver
(testing "it returns true when set in mailserver/current-id" (testing "it returns true when set in mailserver/current-id"
(let [cofx {:db {:mailserver/current-id "a"}}] (let [db {:mailserver/current-id "a"}]
(is (mailserver/connected? cofx "a")))) (is (mailserver/connected? db "a"))))
(testing "it returns false otherwise" (testing "it returns false otherwise"
(is (not (mailserver/connected? {:db {}} "a"))))) (is (not (mailserver/connected? {} "a")))))
(deftest fetch-mailserver (deftest fetch-mailserver
(testing "it fetches the mailserver from the db" (testing "it fetches the mailserver from the db"
(let [cofx {:db {:mailserver/mailservers {:eth.staging {"a" {:id "a" (let [db {:mailserver/mailservers {:eth.staging {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}] :address "enode://old-id:old-password@url:port"}}}}]
(is (mailserver/fetch cofx "a"))))) (is (mailserver/fetch db "a")))))
(deftest fetch-current-mailserver (deftest fetch-current-mailserver
(testing "it fetches the mailserver from the db with corresponding id" (testing "it fetches the mailserver from the db with corresponding id"
(let [cofx {:db {:mailserver/current-id "a" (let [db {:mailserver/current-id "a"
:mailserver/mailservers {:eth.staging {"a" {:id "a" :mailserver/mailservers {:eth.staging {"a" {:id "a"
:name "old-name" :name "old-name"
:address "enode://old-id:old-password@url:port"}}}}}] :address "enode://old-id:old-password@url:port"}}}}]
(is (mailserver/fetch-current cofx))))) (is (mailserver/fetch-current db)))))
(deftest set-current-mailserver (deftest set-current-mailserver
(with-redefs [rand-nth (comp last sort)] (let [cofx {:db {:mailserver/mailservers {:eth.staging {"a" {}
(let [cofx {:db {:mailserver/mailservers {:eth.staging {"a" {} "b" {}
"b" {} "c" {}
"c" {} "d" {}}}}}]
"d" {}}}}}] (testing "the user has already a preference"
(testing "the user has already a preference" (let [cofx (assoc-in cofx
(let [cofx (assoc-in cofx [:db :multiaccount :settings]
[:db :multiaccount :settings] {:mailserver {:eth.staging "a"}})]
{:mailserver {:eth.staging "a"}})] (testing "the mailserver exists"
(testing "the mailserver exists" (testing "it sets the preferred mailserver"
(testing "it sets the preferred mailserver" (is (= "a" (-> (mailserver/set-current-mailserver cofx)
(is (= "a" (-> (mailserver/set-current-mailserver cofx)
:db
:mailserver/current-id)))))
(testing "the mailserver does not exists"
(let [cofx (update-in cofx [:db :mailserver/mailservers :eth.staging] dissoc "a")]
(testing "sets a random mailserver"
(is (= "d" (-> (mailserver/set-current-mailserver cofx)
:db
:mailserver/current-id))))))))
(testing "the user has not set an explicit preference"
(testing "current-id is not set"
(testing "it sets a random mailserver"
(is (= "d" (-> (mailserver/set-current-mailserver cofx)
:db :db
:mailserver/current-id))))) :mailserver/current-id)))))
(testing "current-id is set" (testing "the mailserver does not exists"
(testing "it sets the next mailserver" (let [cofx (update-in cofx [:db :mailserver/mailservers :eth.staging] dissoc "a")]
(is (= "c" (-> (mailserver/set-current-mailserver (assoc-in (testing "look for fastest mailserver"
cofx (is (= "mailservers_ping"
[:db :mailserver/current-id] (-> (mailserver/set-current-mailserver cofx)
"b")) ::json-rpc/call
:db first
:mailserver/current-id))) :method))))))))
(is (= "a" (-> (mailserver/set-current-mailserver (assoc-in (testing "the user has not set an explicit preference"
cofx (testing "current-id is not set"
[:db :mailserver/current-id] (testing "it looks for fastest mailserver"
"d")) (is (= "mailservers_ping"
:db (-> (mailserver/set-current-mailserver cofx)
:mailserver/current-id))) ::json-rpc/call
(is (= "a" (-> (mailserver/set-current-mailserver (assoc-in first
cofx :method)))))
[:db :mailserver/current-id] (testing "current-id is set"
"non-existing")) (testing "it looks for fastest mailserver"
:db (is (= "mailservers_ping"
:mailserver/current-id))))))))) (-> (mailserver/set-current-mailserver (assoc-in
cofx
[:db :mailserver/current-id]
"b"))
::json-rpc/call
first
:method)))
(is (= "mailservers_ping"
(-> (mailserver/set-current-mailserver (assoc-in
cofx
[:db :mailserver/current-id]
"d"))
::json-rpc/call
first
:method)))
(is (= "mailservers_ping"
(-> (mailserver/set-current-mailserver (assoc-in
cofx
[:db :mailserver/current-id]
"non-existing"))
::json-rpc/call
first
:method))))))))
(deftest delete-mailserver (deftest delete-mailserver
(testing "the user is not connected to the mailserver" (testing "the user is not connected to the mailserver"
@ -256,7 +265,7 @@
:address "enode://old-id:old-password@url:port"}}}}} :address "enode://old-id:old-password@url:port"}}}}}
actual (mailserver/delete cofx "a")] actual (mailserver/delete cofx "a")]
(testing "it removes the mailserver from the list" (testing "it removes the mailserver from the list"
(is (not (mailserver/fetch actual "a")))) (is (not (mailserver/fetch (:db actual) "a"))))
(testing "it stores it in the db" (testing "it stores it in the db"
(is (= 1 (count (::json-rpc/call actual))))))) (is (= 1 (count (::json-rpc/call actual)))))))
(testing "the mailserver is not user-defined" (testing "the mailserver is not user-defined"
@ -343,12 +352,14 @@
(testing "there's a current request" (testing "there's a current request"
(testing "it reached the maximum number of attempts" (testing "it reached the maximum number of attempts"
(testing "it changes mailserver" (testing "it changes mailserver"
(is (= :connecting (is (= "mailservers_ping"
(get-in (mailserver/resend-request (-> (mailserver/resend-request
{:db {:mailserver/current-request {:db {:mailserver/current-request
{:attempts constants/maximum-number-of-attempts}}} {:attempts constants/maximum-number-of-attempts}}}
{}) {})
[:db :mailserver/state]))))) ::json-rpc/call
first
:method)))))
(testing "it did not reach the maximum number of attempts" (testing "it did not reach the maximum number of attempts"
(testing "it reached the maximum number of attempts" (testing "it reached the maximum number of attempts"
(testing "it decrease the limit") (testing "it decrease the limit")