use from parameter for mailserver requests

Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
Eric Dvorsak 2018-05-28 11:34:32 +02:00
parent 3430bfe61e
commit 203f399aca
No known key found for this signature in database
GPG Key ID: 932AC1CE5F05DE0C
17 changed files with 271 additions and 110 deletions

View File

@ -2,7 +2,8 @@
(:require
[status-im.data-store.realm.schemas.account.v1.core :as v1]
[status-im.data-store.realm.schemas.account.v2.core :as v2]
[status-im.data-store.realm.schemas.account.v3.core :as v3]))
[status-im.data-store.realm.schemas.account.v3.core :as v3]
[status-im.data-store.realm.schemas.account.v4.core :as v4]))
;; TODO(oskarth): Add failing test if directory vXX exists but isn't in schemas.
@ -15,4 +16,7 @@
:migration v2/migration}
{:schema v3/schema
:schemaVersion 3
:migration v3/migration}])
:migration v3/migration}
{:schema v4/schema
:schemaVersion 4
:migration v4/migration}])

View File

@ -8,10 +8,7 @@
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
[status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage]
[status-im.data-store.realm.schemas.account.v1.browser :as browser]
[goog.object :as object]
[taoensso.timbre :as log]
[cljs.reader :as reader]
[clojure.string :as string]))
[taoensso.timbre :as log]))
(def schema [chat/schema
transport/schema

View File

@ -0,0 +1,24 @@
(ns status-im.data-store.realm.schemas.account.v4.core
(:require [status-im.data-store.realm.schemas.account.v3.chat :as chat]
[status-im.data-store.realm.schemas.account.v4.transport :as transport]
[status-im.data-store.realm.schemas.account.v1.contact :as contact]
[status-im.data-store.realm.schemas.account.v1.message :as message]
[status-im.data-store.realm.schemas.account.v1.request :as request]
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
[status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage]
[status-im.data-store.realm.schemas.account.v2.mailserver :as mailserver]
[status-im.data-store.realm.schemas.account.v1.browser :as browser]
[taoensso.timbre :as log]))
(def schema [chat/schema
transport/schema
contact/schema
message/schema
request/schema
mailserver/schema
user-status/schema
local-storage/schema
browser/schema])
(defn migration [old-realm new-realm]
(log/debug "migrating v4 account database: " old-realm new-realm))

View File

@ -0,0 +1,17 @@
(ns status-im.data-store.realm.schemas.account.v4.transport)
(def schema {:name :transport
:primaryKey :chat-id
:properties {:chat-id :string
:ack :string
:seen :string
:pending-ack :string
:pending-send :string
:topic :string
:fetch-history? {:type :bool
:default false}
:sym-key-id {:type :string
:optional true}
;;TODO (yenda) remove once go implements persistence
:sym-key {:type :string
:optional true}}})

View File

@ -1,6 +1,7 @@
(ns status-im.data-store.realm.schemas.base.core
(:require [status-im.data-store.realm.schemas.base.v1.core :as v1]
[status-im.data-store.realm.schemas.base.v2.core :as v2]))
[status-im.data-store.realm.schemas.base.v2.core :as v2]
[status-im.data-store.realm.schemas.base.v3.core :as v3]))
;; put schemas ordered by version
(def schemas [{:schema v1/schema
@ -8,4 +9,7 @@
:migration v1/migration}
{:schema v2/schema
:schemaVersion 2
:migration v2/migration}])
:migration v2/migration}
{:schema v3/schema
:schemaVersion 3
:migration v3/migration}])

View File

@ -0,0 +1,27 @@
(ns status-im.data-store.realm.schemas.base.v3.account)
(def schema {:name :account
:primaryKey :address
:properties {:address :string
:public-key :string
:name {:type :string :optional true}
:email {:type :string :optional true}
:status {:type :string :optional true}
:debug? {:type :bool :default false}
:photo-path :string
:signing-phrase {:type :string}
:mnemonic {:type :string :optional true}
:last-updated {:type :int :default 0}
:last-sign-in {:type :int :default 0}
:signed-up? {:type :bool
:default false}
:network :string
:networks {:type :list
:objectType :network}
:last-request {:type :int :optional true}
:settings {:type :string}
:sharing-usage-data? {:type :bool :default false}
:dev-mode? {:type :bool :default false}
:seed-backed-up? {:type :bool :default false}
:wallet-set-up-passed? {:type :bool
:default false}}})

View File

@ -0,0 +1,10 @@
(ns status-im.data-store.realm.schemas.base.v3.core
(:require [status-im.data-store.realm.schemas.base.v1.network :as network]
[status-im.data-store.realm.schemas.base.v3.account :as account]
[taoensso.timbre :as log]))
(def schema [network/schema
account/schema])
(defn migration [old-realm new-realm]
(log/debug "migrating base database v3: " old-realm new-realm))

View File

@ -31,7 +31,7 @@
(fn [{{:keys [network-status mailserver-status] :as db} :db :as cofx} [is-connected?]]
(cond-> (handlers-macro/merge-fx cofx
{:db (assoc db :network-status (if is-connected? :online :offline))}
(inbox/request-messages {:discover? true}))
(inbox/request-messages))
is-connected?
(assoc :drain-mixpanel-events nil))))

View File

@ -9,6 +9,7 @@
(spec/def ::pending-ack (spec/coll-of string? :kind vector?))
(spec/def ::pending-send (spec/coll-of string? :kind vector?))
(spec/def ::topic string?)
(spec/def ::fetch-history? boolean?)
;; optional
(spec/def ::sym-key-id string?)
@ -16,7 +17,7 @@
(spec/def ::sym-key string?)
(spec/def ::filter any?)
(spec/def :transport/chat (allowed-keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic]
(spec/def :transport/chat (allowed-keys :req-un [::ack ::seen ::pending-ack ::pending-send ::topic ::fetch-history?]
:opt-un [::sym-key-id ::sym-key ::filter]))
(spec/def :transport/chats (spec/map-of :global/not-empty-string :transport/chat))
@ -26,8 +27,9 @@
"Initialize datastructure for chat representation at the transport level
Currently only :topic is actually used"
[topic]
{:ack []
:seen []
:pending-ack []
:pending-send []
:topic topic})
{:ack []
:seen []
:pending-ack []
:pending-send []
:fetch-history? true
:topic topic})

View File

@ -97,7 +97,7 @@
{:db (assoc-in db
[:transport/chats chat-id :sym-key-id]
sym-key-id)
:dispatch [:inbox/request-messages {:topics [topic] :discover? false}]
:dispatch [:inbox/request-chat-history chat-id]
:shh/add-filter {:web3 web3
:sym-key-id sym-key-id
:topic topic
@ -156,7 +156,7 @@
fx {:db (assoc-in db
[:transport/chats chat-id :sym-key-id]
sym-key-id)
:dispatch [:inbox/request-messages {:topics [topic]}]
:dispatch [:inbox/request-chat-history chat-id]
:shh/add-filter {:web3 web3
:sym-key-id sym-key-id
:topic topic

View File

@ -12,16 +12,40 @@
[status-im.utils.utils :as utils]
[status-im.i18n :as i18n]
[status-im.constants :as constants]
[status-im.utils.handlers-macro :as handlers-macro]))
[status-im.data-store.accounts :as accounts-store]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.data-store.core :as data-store]
[status-im.ui.screens.accounts.events :as accounts]
[status-im.data-store.transport :as transport-store]))
;; How does offline inboxing work ?
;;
;; - We send a request to the mailserver, we are only interested in the
;; messages since `last-request`, the time of the last successful request,
;; and the last 7 days for topics that were just joined
;; - The mailserver doesn't directly respond to the request and
;; instead we start receiving messages in the filters for the requested
;; topics.
;; - These messages are expired that is how we differentiate them from
;; normal whisper messages to update last-received
;; - After fetching-timeout is reached since the last mailserver message
;; was received without a connection incident, we consider the request
;; successfull and update `last-request` and `fetch-history?` fields of each
;; topic to false
;; - If the mailserver was not ready when we tried for instance to request
;; the history of a topic after joining a chat, the request will be done
;; as soon as the mailserver becomes available
(def connection-timeout
"Time after which mailserver connection is considered to have failed"
60000)
(def fetching-messages-notification-timeout
"Time after which we consider mailserver is done fetching messages and we can
stop showing notification to user"
5000)
(def fetching-timeout
"Time we should wait after last message was fetch from mailserver before we
consider it done
Needs to be at least 10 seconds because that is the time it takes for the app
to realize it was disconnected"
10000)
(defn- parse-json
;; NOTE(dmitryn) Expects JSON response like:
@ -102,7 +126,7 @@
(mark-trusted-peer web3
wnode
#(re-frame/dispatch [:inbox/mailserver-trusted %])
#(re-frame/dispatch [:inbox/connection-check]))))
#(re-frame/dispatch [:inbox/check-connection]))))
(re-frame/reg-fx
::request-messages
@ -116,9 +140,23 @@
#(log/info "offline inbox: request-messages response" %)
#(log/error "offline inbox: request-messages error" %1 %2 to from))))
(re-frame/reg-fx
::request-history
(fn [{:keys [wnode topics to from sym-key-id web3]}]
(request-inbox-messages web3
wnode
topics
to
from
sym-key-id
#(log/info "offline inbox: request-messages response" %)
#(log/error "offline inbox: request-messages error" %1 %2 to from))))
(defn update-mailserver-status [transition {:keys [db]}]
(let [state transition]
{:db (assoc db :mailserver-status state)}))
{:db (assoc db
:mailserver-status state
:inbox/fetching? false)}))
(defn generate-mailserver-symkey [{:keys [db] :as cofx}]
(when-not (:inbox/sym-key-id db)
@ -149,7 +187,7 @@
(handlers-macro/merge-fx cofx
{::add-peer {:wnode wnode}
:utils/dispatch-later [{:ms connection-timeout
:dispatch [:inbox/connection-check]}]}
:dispatch [:inbox/check-connection]}]}
(update-mailserver-status :connecting)
(generate-mailserver-symkey))))))
@ -166,8 +204,10 @@
wnode)
mailserver-is-registered? (registered-peer? peers-summary
wnode)
;; the mailserver just connected
mailserver-connected? (and mailserver-is-registered?
(not mailserver-was-registered?))
;; the mailserver just disconnected
mailserver-disconnected? (and mailserver-was-registered?
(not mailserver-is-registered?))]
(cond
@ -178,40 +218,69 @@
{::mark-trusted-peer {:web3 (:web3 db)
:wnode wnode}}))))
(defn get-topics
[db topics discover?]
(let [inbox-topics (:inbox/topics db)
discovery-topic (transport.utils/get-topic constants/contact-discovery)
topics (or topics
(map #(:topic %) (vals (:transport/chats db))))]
(cond-> (apply conj inbox-topics topics)
discover? (conj discovery-topic))))
(defn inbox-ready? [{:keys [db]}]
(let [mailserver-status (:mailserver-status db)
sym-key-id (:inbox/sym-key-id db)]
(and (= :connected mailserver-status)
sym-key-id)))
(defn get-request-messages-topics
"Returns topics for which full history has already been recovered"
[db]
(conj (mapv :topic
(remove :fetch-history?
(vals (:transport/chats db))))
(transport.utils/get-topic constants/contact-discovery)))
(defn get-request-history-topics
"Returns topics for which full history has not been recovered"
[db]
(mapv :topic
(filter :fetch-history?
(vals (:transport/chats db)))))
(defn request-messages
([cofx]
(request-messages {} cofx))
([{:keys [topics discover? should-recover?]
:or {should-recover? true
discover? true}}
{:keys [db] :as cofx}]
(let [mailserver-status (:mailserver-status db)
sym-key-id (:inbox/sym-key-id db)
wnode (get-current-wnode-address db)
inbox-topics (get-topics db topics discover?)
inbox-ready? (and (= :connected mailserver-status)
sym-key-id)]
(when should-recover?
(if inbox-ready?
{::request-messages {:wnode wnode
:topics (into [] inbox-topics)
:sym-key-id sym-key-id
:web3 (:web3 db)}
:db (assoc db
:inbox/fetching? true
:inbox/topics #{})
:dispatch-later [{:ms fetching-messages-notification-timeout
:dispatch [:inbox/remove-fetching-notification]}]}
{:db (assoc db :inbox/topics (into #{} inbox-topics))})))))
([{:keys [db now] :as cofx}]
(let [wnode (get-current-wnode-address db)
web3 (:web3 db)
sym-key-id (:inbox/sym-key-id db)
now-in-s (quot now 1000)
last-request (get-in db [:account/account :last-request]
(- now-in-s (* 3600 24)))
request-messages-topics (get-request-messages-topics db)
request-history-topics (get-request-history-topics db)]
(when (inbox-ready? cofx)
{::request-messages {:wnode wnode
:topics request-messages-topics
:from last-request
:to now-in-s
:sym-key-id sym-key-id
:web3 web3}
::request-history {:wnode wnode
:topics request-history-topics
:sym-key-id sym-key-id
:web3 web3}
:db (assoc db :inbox/fetching? true)
:dispatch-later [{:ms fetching-timeout
:dispatch [:inbox/check-fetching now-in-s]}]})))
([should-recover? {:keys [db] :as cofx}]
(when should-recover?
(request-messages cofx))))
(defn request-chat-history [chat-id {:keys [db now] :as cofx}]
(let [wnode (get-current-wnode-address db)
web3 (:web3 db)
sym-key-id (:inbox/sym-key-id db)
topic (get-in db [:transport/chats chat-id :topic])
now-in-s (quot now 1000)]
(when (inbox-ready? cofx)
{::request-history {:wnode wnode
:topics [topic]
:sym-key-id sym-key-id
:web3 web3}
:db (assoc db :inbox/fetching? true)
:dispatch-later [{:ms fetching-timeout
:dispatch [:inbox/check-fetching now-in-s chat-id]}]})))
;;;; Handlers
@ -239,20 +308,68 @@
(request-messages))))
(handlers/register-handler-fx
:inbox/request-messages
(fn [cofx [_ args]]
(request-messages args cofx)))
:inbox/request-chat-history
(fn [{:keys [db] :as cofx} [_ chat-id]]
(request-chat-history chat-id cofx)))
(handlers/register-handler-fx
:inbox/connection-check
:inbox/check-connection
(fn [{:keys [db] :as cofx} [_ _]]
(when (= :connecting (:mailserver-status db))
(update-mailserver-status :error cofx))))
(defn update-last-request [last-request {:keys [db]}]
(let [chats (:transport/chats db)
transport-txs (reduce (fn [txs [chat-id chat]]
(if (:fetch-history? chat)
(conj txs
(transport-store/save-transport-tx
{:chat-id chat-id
:chat (assoc chat
:fetch-history? false)}))
txs))
[]
chats)
chats-update (reduce (fn [acc [chat-id chat]]
(if (:fetch-history? chat)
(assoc acc chat-id (assoc chat :fetch-history? false))
(assoc acc chat-id chat)))
{}
chats)]
{:db (-> db
(assoc :transport/chats chats-update)
(assoc-in [:account/account :last-request]
last-request))
:data-store/base-tx [(accounts-store/save-account-tx
(assoc (:account/account db)
:last-request last-request))]
:data-store/tx transport-txs}))
(defn update-fetch-history [chat-id {:keys [db]}]
{:db (assoc-in db
[:transport/chats chat-id :fetch-history?]
false)
:data-store/tx [(transport-store/save-transport-tx
{:chat-id chat-id
:chat (assoc (get-in db [:transport/chats chat-id])
:fetch-history? false)})]})
(handlers/register-handler-fx
:inbox/remove-fetching-notification
(fn [{:keys [db] :as cofx} [_ _]]
{:db (dissoc db :inbox/fetching?)}))
:inbox/check-fetching
(fn [{:keys [db now] :as cofx} [_ last-request chat-id]]
(when (:inbox/fetching? db)
(let [time-since-last-received (- now (:inbox/last-received db))]
(if (> time-since-last-received fetching-timeout)
(if chat-id
(handlers-macro/merge-fx cofx
{:db (assoc db :inbox/fetching? false)}
(update-fetch-history chat-id))
(handlers-macro/merge-fx cofx
{:db (assoc db :inbox/fetching? false)}
(update-last-request last-request)))
{:dispatch-later [{:ms (- fetching-timeout
time-since-last-received)
:dispatch [:inbox/check-fetching last-request chat-id]}]})))))
(handlers/register-handler-fx
:inbox/reconnect

View File

@ -30,7 +30,7 @@
(fn [{:keys [db] :as cofx} [_ {:keys [sym-key-id sym-key chat-id]}]]
(let [{:keys [web3]} db
topic (transport.utils/get-topic chat-id)]
{: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
:sym-key-id sym-key-id
:topic topic
@ -41,6 +41,4 @@
(assoc :sym-key-id sym-key-id)
;;TODO (yenda) remove once go implements persistence
(assoc :sym-key sym-key))})]
:dispatch [:inbox/request-messages {:topics [topic]
:discover? false
:from 0}]})))
:dispatch [:inbox/request-chat-history chat-id]})))

View File

@ -18,6 +18,7 @@
(spec/def :account/signed-up? (spec/nilable boolean?))
(spec/def :account/last-updated (spec/nilable int?))
(spec/def :account/last-sign-in (spec/nilable int?))
(spec/def :account/last-request (spec/nilable int?))
(spec/def :account/photo-path (spec/nilable string?))
(spec/def :account/debug? (spec/nilable boolean?))
(spec/def :account/status (spec/nilable string?))
@ -40,7 +41,7 @@
:account/networks :account/settings :account/wnode
:account/last-sign-in :account/sharing-usage-data? :account/dev-mode?
:account/seed-backed-up? :account/mnemonic
:account/wallet-set-up-passed?]))
:account/wallet-set-up-passed? :account/last-request]))
(spec/def :accounts/accounts (spec/nilable (spec/map-of :account/address :accounts/account)))

View File

@ -42,7 +42,6 @@
:notifications {}
:network constants/default-network
:networks/networks constants/default-networks
:inbox/topics #{}
:inbox/wnodes constants/default-wnodes
:inbox/password constants/inbox-password
:my-profile/editing? false
@ -72,7 +71,6 @@
(spec/def ::network-status (spec/nilable keyword?))
(spec/def ::mailserver-status (spec/nilable keyword?))
(spec/def :inbox/topics set?)
;;;;NODE
@ -175,10 +173,8 @@
:node/after-start
:node/after-stop
:inbox/wnodes
:inbox/topics
:inbox/password
:inbox/sym-key-id
:inbox/last-request
:inbox/last-received
:inbox/fetching?
:browser/browsers

View File

@ -456,8 +456,7 @@
(let [app-coming-from-background? (= state "active")]
(handlers-macro/merge-fx cofx
{::app-state-change-fx state}
(inbox/request-messages {:should-recover? app-coming-from-background?
:discover? true})))))
(inbox/request-messages app-coming-from-background?)))))
(handlers/register-handler-fx
:request-permissions

View File

@ -17,5 +17,4 @@
(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/sym-key-id string?)
(spec/def :inbox/last-request integer?)
(spec/def :inbox/last-received integer?)

View File

@ -3,40 +3,6 @@
[status-im.transport.inbox :as inbox]
[status-im.constants :as constants]))
(deftest request-messages
(testing "mailserver not connected"
(is (= (inbox/request-messages {} {:db {:mailserver-status :connecting :inbox/sym-key-id :sym-key}})
{:db
{:mailserver-status :connecting,
:inbox/sym-key-id :sym-key,
:inbox/topics #{"0xf8946aac"}}}))
(is (= (inbox/request-messages {:discover? false :topics ["Oxaaaaaaaa"]} {:db {:mailserver-status :connecting :inbox/sym-key-id :sym-key}})
{:db
{:mailserver-status :connecting,
:inbox/sym-key-id :sym-key,
:inbox/topics #{"Oxaaaaaaaa"}}})))
(testing "mailserver is connected"
(is (= (inbox/request-messages {} {:db {:mailserver-status :connected :inbox/sym-key-id :sym-key}})
{:status-im.transport.inbox/request-messages
{:wnode nil, :topics ["0xf8946aac"], :sym-key-id :sym-key, :web3 nil},
:db
{:mailserver-status :connected,
:inbox/sym-key-id :sym-key,
:inbox/fetching? true,
:inbox/topics #{}},
:dispatch-later
[{:ms 5000, :dispatch [:inbox/remove-fetching-notification]}]})
(= (inbox/request-messages {:discover? false :topics ["Oxaaaaaaaa"]} {:db {:mailserver-status :connected :inbox/sym-key-id :sym-key}})
{:status-im.transport.inbox/request-messages
{:wnode nil, :topics ["Oxaaaaaaaa"], :sym-key-id :sym-key, :web3 nil},
:db
{:mailserver-status :connected,
:inbox/sym-key-id :sym-key,
:inbox/fetching? true,
:inbox/topics #{}},
:dispatch-later
[{:ms 5000, :dispatch [:inbox/remove-fetching-notification]}]}))))
(defn cofx-fixtures [sym-key registered-peer?]
{:db {:mailserver-status :connected
:inbox/sym-key-id sym-key