[fix 3843] query mailserver when going back online

Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
Eric Dvorsak 2018-04-13 19:14:26 +02:00
parent de03fc2d6a
commit f8e535f9bc
No known key found for this signature in database
GPG Key ID: 932AC1CE5F05DE0C
8 changed files with 118 additions and 65 deletions

View File

@ -8,7 +8,8 @@
com.andrewmcveigh/cljs-time {:mvn/version "0.5.2"} com.andrewmcveigh/cljs-time {:mvn/version "0.5.2"}
com.taoensso/timbre {:mvn/version "4.10.0"} com.taoensso/timbre {:mvn/version "4.10.0"}
hickory {:mvn/version "0.7.1"} hickory {:mvn/version "0.7.1"}
com.cognitect/transit-cljs {:mvn/version "0.8.248"}} com.cognitect/transit-cljs {:mvn/version "0.8.248"}
day8.re-frame/async-flow-fx {:mvn/version "0.0.10"}}
:aliases :aliases
{:repl {:extra-deps {:repl {:extra-deps

View File

@ -10,7 +10,8 @@
[com.andrewmcveigh/cljs-time "0.5.2"] [com.andrewmcveigh/cljs-time "0.5.2"]
[com.taoensso/timbre "4.10.0"] [com.taoensso/timbre "4.10.0"]
[hickory "0.7.1"] [hickory "0.7.1"]
[com.cognitect/transit-cljs "0.8.248"]] [com.cognitect/transit-cljs "0.8.248"]
[day8.re-frame/async-flow-fx "0.0.10"]]
:plugins [[lein-cljsbuild "1.1.7"] :plugins [[lein-cljsbuild "1.1.7"]
[lein-re-frisk "0.5.8"]] [lein-re-frisk "0.5.8"]]
:clean-targets ["target/" "index.ios.js" "index.android.js"] :clean-targets ["target/" "index.ios.js" "index.android.js"]

View File

@ -1,8 +1,10 @@
(ns status-im.network.events (ns status-im.network.events
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.network.net-info :as net-info] [status-im.network.net-info :as net-info]
[status-im.native-module.core :as status])) [status-im.native-module.core :as status]
[status-im.transport.inbox :as inbox]))
(re-frame/reg-fx (re-frame/reg-fx
::listen-to-network-status ::listen-to-network-status
@ -18,23 +20,26 @@
(status/connection-change data))) (status/connection-change data)))
(handlers/register-handler-fx (handlers/register-handler-fx
:listen-to-network-status :listen-to-network-status
(fn [] (fn []
{::listen-to-network-status [#(re-frame/dispatch [::update-connection-status %]) {::listen-to-network-status [#(re-frame/dispatch [::update-connection-status %])
#(re-frame/dispatch [::update-network-status %])]})) #(re-frame/dispatch [::update-network-status %])]}))
(handlers/register-handler-fx (handlers/register-handler-fx
::update-connection-status ::update-connection-status
[re-frame/trim-v] [re-frame/trim-v]
(fn [{:keys [db]} [is-connected?]] (fn [{:keys [db] :as cofx} [is-connected?]]
(cond-> (let [previous-status (:network-status db)
{:db (assoc db :network-status (if is-connected? :online :offline))} back-online? (and (= previous-status :offline)
is-connected?)]
is-connected? (cond-> (handlers-macro/merge-fx cofx
(assoc :drain-mixpanel-events nil)))) {:db (assoc db :network-status (if is-connected? :online :offline))}
(inbox/recover-offline-inbox back-online?))
is-connected?
(assoc :drain-mixpanel-events nil)))))
(handlers/register-handler-fx (handlers/register-handler-fx
::update-network-status ::update-network-status
[re-frame/trim-v] [re-frame/trim-v]
(fn [_ [data]] (fn [_ [data]]
{::notify-status-go data})) {::notify-status-go data}))

View File

@ -27,6 +27,7 @@
:no "No" :no "No"
:on "On" :on "On"
:off "Off" :off "Off"
:mailserver-connection-error "Could not connect to mailserver"
:camera-access-error "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected." :camera-access-error "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected."
:photos-access-error "To grant the required photos permission, please go to your system settings and make sure that Status > Photos is selected." :photos-access-error "To grant the required photos permission, please go to your system settings and make sure that Status > Photos is selected."

View File

@ -6,7 +6,10 @@
[status-im.transport.utils :as web3.utils] [status-im.transport.utils :as web3.utils]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.ethereum.core :as ethereum])) [status-im.utils.ethereum.core :as ethereum]
[status-im.utils.utils :as utils]
[status-im.i18n :as i18n]
[day8.re-frame.async-flow-fx]))
(defn- parse-json (defn- parse-json
;; NOTE(dmitryn) Expects JSON response like: ;; NOTE(dmitryn) Expects JSON response like:
@ -41,15 +44,38 @@
wnode-id (get-in db [:account/account :settings :wnode network])] wnode-id (get-in db [:account/account :settings :wnode network])]
(get-in db [:inbox/wnodes network wnode-id :address]))) (get-in db [:inbox/wnodes network wnode-id :address])))
(defn initialize-offline-inbox-flow []
{:first-dispatch [:inbox/get-sym-key]
:rules [{:when :seen-both?
:events [:inbox/get-sym-key-success :inbox/connection-success]
:dispatch [:inbox/request-messages]}]})
(defn recover-offline-inbox-flow []
{:first-dispatch [:inbox/fetch-peers]
:rules [{:when :seen?
:events :inbox/connection-success
:dispatch [:inbox/request-messages]}]})
(defn initialize-offline-inbox (defn initialize-offline-inbox
"Initialises offline inbox by producing `::add-peer` effect if inboxing enabled in config, "Initialises offline inbox if inboxing enabled in config"
then the event chan is:
add-peer -> fetch-peers -> check-peer-added -> mark-trusted-peer -> get-sym-key -> request-messages"
[{:keys [db]}] [{:keys [db]}]
(when config/offline-inbox-enabled? (when config/offline-inbox-enabled?
(let [wnode (get-current-wnode-address db)] (let [wnode (get-current-wnode-address db)]
(log/info "offline inbox: initialize") (log/info "offline inbox: initialize " wnode)
{::add-peer {:wnode wnode}}))) (when wnode
{:async-flow (initialize-offline-inbox-flow)
::add-peer {:wnode wnode}}))))
(defn recover-offline-inbox
"Recover offline inbox connection after being offline because of connectivity loss"
[back-online? {:keys [db]}]
(when config/offline-inbox-enabled?
(let [wnode (get-current-wnode-address db)]
(when (and back-online?
wnode
(:account/account db))
(log/info "offline inbox: recover" wnode)
{:async-flow (recover-offline-inbox-flow)}))))
(defn add-peer [enode success-fn error-fn] (defn add-peer [enode success-fn error-fn]
(status/add-peer enode (response-handler error-fn success-fn))) (status/add-peer enode (response-handler error-fn success-fn)))
@ -71,7 +97,7 @@
enode-id (web3.utils/extract-enode-id enode)] enode-id (web3.utils/extract-enode-id enode)]
(contains? peer-ids enode-id))) (contains? peer-ids enode-id)))
(defn mark-trusted-peer [web3 enode peers success-fn error-fn] (defn mark-trusted-peer [web3 enode success-fn error-fn]
(.markTrustedPeer (web3.utils/shh web3) (.markTrustedPeer (web3.utils/shh web3)
enode enode
(fn [err resp] (fn [err resp]
@ -80,7 +106,6 @@
(error-fn err))))) (error-fn err)))))
(defn request-messages [web3 wnode topics to from sym-key-id success-fn error-fn] (defn request-messages [web3 wnode topics to from sym-key-id success-fn error-fn]
(log/info "offline inbox: sym-key-id" sym-key-id)
(let [opts (merge {:mailServerPeer wnode (let [opts (merge {:mailServerPeer wnode
:symKeyID sym-key-id} :symKeyID sym-key-id}
(when from {:from from}) (when from {:from from})
@ -100,22 +125,21 @@
::add-peer ::add-peer
(fn [{:keys [wnode]}] (fn [{:keys [wnode]}]
(add-peer wnode (add-peer wnode
#(re-frame/dispatch [::fetch-peers %]) #(re-frame/dispatch [:inbox/fetch-peers])
#(log/error "offline inbox: add-peer error" %)))) #(log/error "offline inbox: add-peer error" %))))
(re-frame/reg-fx (re-frame/reg-fx
::fetch-peers ::fetch-peers
(fn [retries] (fn [retries]
(fetch-peers #(re-frame/dispatch [::check-peer-added % retries]) (fetch-peers #(re-frame/dispatch [:inbox/check-peer-added % retries])
#(log/error "offline inbox: fetch-peers error" %)))) #(log/error "offline inbox: fetch-peers error" %))))
(re-frame/reg-fx (re-frame/reg-fx
::mark-trusted-peer ::mark-trusted-peer
(fn [{:keys [wnode web3 peers]}] (fn [{:keys [wnode web3]}]
(mark-trusted-peer web3 (mark-trusted-peer web3
wnode wnode
peers #(re-frame/dispatch [:inbox/connection-success %])
#(re-frame/dispatch [::get-sym-key %])
#(log/error "offline inbox: mark-trusted-peer error" % wnode)))) #(log/error "offline inbox: mark-trusted-peer error" % wnode))))
(re-frame/reg-fx (re-frame/reg-fx
@ -133,14 +157,20 @@
;;;; Handlers ;;;; Handlers
(handlers/register-handler-fx (handlers/register-handler-fx
::fetch-peers :inbox/add-peer
;; This event adds a wnode to the list of peers
(fn [_ [_ wnode]]
{::add-peer {:wnode wnode}}))
(handlers/register-handler-fx
:inbox/fetch-peers
;; This event fetches the list of peers ;; This event fetches the list of peers
;; We want it to check if the node has been added ;; We want it to check if the node has been added
(fn [_ [_ retries]] (fn [_ [_ retries]]
{::fetch-peers (or retries 0)})) {::fetch-peers (or retries 0)}))
(handlers/register-handler-fx (handlers/register-handler-fx
::check-peer-added :inbox/check-peer-added
;; We check if the wnode is part of the peers list ;; We check if the wnode is part of the peers list
;; if not we dispatch a new fetch-peer event for later ;; if not we dispatch a new fetch-peer event for later
(fn [{:keys [db]} [_ peers retries]] (fn [{:keys [db]} [_ peers retries]]
@ -149,44 +179,54 @@
(log/info "offline inbox: fetch-peers response" peers) (log/info "offline inbox: fetch-peers response" peers)
(if (registered-peer? peers wnode) (if (registered-peer? peers wnode)
{::mark-trusted-peer {:web3 web3 {::mark-trusted-peer {:web3 web3
:wnode wnode :wnode wnode}}
:peers peers}}
(do (do
(log/info "Peer" wnode "is not registered. Retrying fetch peers.") (log/info "Peer" wnode "is not registered. Retrying fetch peers.")
(let [delay (if (< retries 3) 300 5000)] (let [delay (if (< retries 3) 300 5000)]
(if (> retries 10) (if (> retries 10)
(log/error "Could not connect to mailserver") (do (log/error :mailserver-connection-error)
{:dispatch-later [{:ms delay :dispatch [::fetch-peers (inc retries)]}]}))))))) (utils/show-popup (i18n/label :t/error)
(i18n/label :t/mailserver-connection-error)))
{:dispatch-later [{:ms delay :dispatch [:inbox/fetch-peers (inc retries)]}]})))))))
(handlers/register-handler-fx (handlers/register-handler-fx
::get-sym-key :inbox/get-sym-key
;; TODO(yenda): using core async flow this event can be done in parallel (fn [{:keys [db]} _]
;; with add-peer
(fn [{:keys [db]} [_ response]]
(let [web3 (:web3 db) (let [web3 (:web3 db)
wnode (get-current-wnode-address db) wnode (get-current-wnode-address db)
password (:inbox/password db)] password (:inbox/password db)]
(log/info "offline inbox: mark-trusted-peer response" wnode response)
{:shh/generate-sym-key-from-password {:password password {:shh/generate-sym-key-from-password {:password password
:web3 web3 :web3 web3
:on-success (fn [_ sym-key-id] :on-success (fn [_ sym-key-id]
(re-frame/dispatch [::request-messages sym-key-id])) (re-frame/dispatch [:inbox/get-sym-key-success sym-key-id]))
:on-error #(log/error "offline inbox: get-sym-key error" %)}}))) :on-error #(log/error "offline inbox: get-sym-key error" %)}})))
(handlers/register-handler-fx (handlers/register-handler-fx
::request-messages :inbox/get-sym-key-success
;; TODO(yenda): we want to request-message once per topic and for specific timespan so
;; we want a plural version of this function that does the right thing
(fn [{:keys [db]} [_ sym-key-id]] (fn [{:keys [db]} [_ sym-key-id]]
(log/info "offline inbox: get-sym-key response") sym-key-id {:db (assoc db :inbox/sym-key-id sym-key-id)}))
(handlers/register-handler-fx
:inbox/connection-success
(fn [{:keys [db]} _]
{:db (assoc db :mailserver-status :connected)}))
(handlers/register-handler-fx
:inbox/request-messages
(fn [{:keys [db now]} [_ {:keys [from topics]}]]
(let [web3 (:web3 db) (let [web3 (:web3 db)
wnode (get-current-wnode-address db) wnode (get-current-wnode-address db)
topics (map #(:topic %) (vals (:transport/chats db))) topics (or topics
to nil (map #(:topic %) (vals (:transport/chats db))))
from nil] from (or from (:inbox/last-request db) nil)
sym-key-id (:inbox/sym-key-id db)]
{::request-messages {:wnode wnode {::request-messages {:wnode wnode
:topics topics :topics topics
:to to ;;TODO (yenda) fix from, right now mailserver is dropping us
:from from ;;when we send a requestMessage with a from field
;;:from from
:sym-key-id sym-key-id :sym-key-id sym-key-id
:web3 web3}}))) :web3 web3}
:db (assoc db :inbox/last-request (quot now 1000))})))

View File

@ -25,18 +25,19 @@
(protocol/init-chat chat-id))))) (protocol/init-chat chat-id)))))
(handlers/register-handler-fx (handlers/register-handler-fx
::add-new-sym-key ::add-new-sym-key
(fn [{:keys [db] :as cofx} [_ {:keys [sym-key-id sym-key chat-id]}]] (fn [{:keys [db] :as cofx} [_ {:keys [sym-key-id sym-key chat-id]}]]
(let [{:keys [web3]} db] (let [{:keys [web3]} db
(handlers-macro/merge-fx topic (transport.utils/get-topic chat-id)]
cofx {:db (assoc-in db [:transport/chats chat-id :sym-key-id] sym-key-id)
{:db (assoc-in db [:transport/chats chat-id :sym-key-id] sym-key-id) :shh/add-filter {:web3 web3
:shh/add-filter {:web3 web3 :sym-key-id sym-key-id
:sym-key-id sym-key-id :topic topic
:topic (transport.utils/get-topic chat-id) :chat-id chat-id}
:chat-id chat-id}
:data-store.transport/save {:chat-id chat-id :data-store.transport/save {:chat-id chat-id
:chat (-> (get-in db [:transport/chats chat-id]) :chat (-> (get-in db [:transport/chats chat-id])
(assoc :sym-key-id sym-key-id) (assoc :sym-key-id sym-key-id)
;;TODO (yenda) remove once go implements persistence ;;TODO (yenda) remove once go implements persistence
(assoc :sym-key sym-key))}})))) (assoc :sym-key sym-key))}
:dispatch [:inbox/request-messages {:topics [topic]
:from 0}]})))

View File

@ -166,6 +166,8 @@
:node/after-stop :node/after-stop
:inbox/wnodes :inbox/wnodes
:inbox/password :inbox/password
:inbox/sym-key-id
:inbox/last-request
:browser/browsers :browser/browsers
:browser/options :browser/options
:new/open-dapp :new/open-dapp

View File

@ -13,3 +13,5 @@
(spec/def :inbox/password ::not-blank-string) (spec/def :inbox/password ::not-blank-string)
(spec/def :inbox/wnodes (spec/nilable (spec/map-of keyword? (spec/map-of :wnode/id :wnode/wnode)))) (spec/def :inbox/wnodes (spec/nilable (spec/map-of keyword? (spec/map-of :wnode/id :wnode/wnode))))
(spec/def :inbox/sym-key-id string?)
(spec/def :inbox/last-request integer?)