[fix #5599] add semaphore for recurring events
:sync-wallet-transaction and :sync-state are self firing events that dispatch themselves later. this commit introduces semaphores to prevent these event-loops from starting multiple times when the user logs out and logs in again. Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
parent
d46eec0bc8
commit
c5b17ac637
|
@ -4,6 +4,7 @@
|
||||||
[status-im.utils.ethereum.tokens :as tokens]
|
[status-im.utils.ethereum.tokens :as tokens]
|
||||||
[status-im.utils.ethereum.core :as ethereum]
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
[status-im.utils.handlers-macro :as handlers-macro]
|
||||||
|
[status-im.utils.semaphores :as semaphores]
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
(def sync-interval-ms 15000)
|
(def sync-interval-ms 15000)
|
||||||
|
@ -88,21 +89,28 @@
|
||||||
(< sync-interval-ms
|
(< sync-interval-ms
|
||||||
(- (time/timestamp) last-updated-at)))))
|
(- (time/timestamp) last-updated-at)))))
|
||||||
|
|
||||||
(defn set-sync-started [{:keys [db]}]
|
(defn sync
|
||||||
{:db (assoc-in db [:wallet :transactions-sync-started?] true)})
|
"Fetch updated data for any unconfirmed transactions or incoming chat transactions missing in wallet
|
||||||
|
and schedule new recurring sync request"
|
||||||
|
[{:keys [db] :as cofx}]
|
||||||
|
(if (:account/account db)
|
||||||
|
(let [in-progress? (get-in db [:wallet :transactions-loading?])
|
||||||
|
{:keys [app-state network-status]} db]
|
||||||
|
(if (and (not= network-status :offline)
|
||||||
|
(= app-state "active")
|
||||||
|
(not in-progress?)
|
||||||
|
(time-to-sync? cofx)
|
||||||
|
(or (have-unconfirmed-transactions? cofx)
|
||||||
|
(have-missing-chat-transactions? cofx)))
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
(run-update)
|
||||||
|
(schedule-sync))
|
||||||
|
(schedule-sync cofx)))
|
||||||
|
{:db (semaphores/free :sync-wallet-transactions? cofx)}))
|
||||||
|
|
||||||
; Fetch updated data for any unconfirmed transactions or incoming chat transactions missing in wallet
|
(defn start-sync [cofx]
|
||||||
; and schedule new recurring sync request
|
(when-not (semaphores/locked? :sync-wallet-transactions? cofx)
|
||||||
(defn sync [{:keys [db] :as cofx}]
|
(handlers-macro/merge-fx cofx
|
||||||
(let [in-progress? (get-in db [:wallet :transactions-loading?])
|
(load-missing-chat-transactions)
|
||||||
{:keys [app-state network-status]} db]
|
(semaphores/lock :sync-wallet-transactions?)
|
||||||
(if (and (not= network-status :offline)
|
(sync))))
|
||||||
(= app-state "active")
|
|
||||||
(not in-progress?)
|
|
||||||
(time-to-sync? cofx)
|
|
||||||
(or (have-unconfirmed-transactions? cofx)
|
|
||||||
(have-missing-chat-transactions? cofx)))
|
|
||||||
(handlers-macro/merge-fx cofx
|
|
||||||
(run-update)
|
|
||||||
(schedule-sync))
|
|
||||||
(schedule-sync cofx))))
|
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.utils.datetime :as datetime]
|
[status-im.utils.datetime :as datetime]
|
||||||
[status-im.utils.ethereum.core :as ethereum-utils]
|
|
||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.utils.handlers-macro :as handlers-macro]
|
[status-im.utils.handlers-macro :as handlers-macro]
|
||||||
[status-im.utils.web3-provider :as web3-provider]
|
[status-im.utils.web3-provider :as web3-provider]
|
||||||
[status-im.transport.core :as transport]
|
[status-im.transport.core :as transport]
|
||||||
[status-im.transport.inbox :as transport.inbox]
|
[status-im.transport.inbox :as transport.inbox]
|
||||||
[status-im.utils.ethereum.core :as ethereum]))
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.protocol.models :as models]))
|
||||||
|
|
||||||
;;;; COFX
|
;;;; COFX
|
||||||
(re-frame/reg-cofx
|
(re-frame/reg-cofx
|
||||||
|
@ -71,35 +71,15 @@
|
||||||
|
|
||||||
(handlers/register-handler-db
|
(handlers/register-handler-db
|
||||||
:update-sync-state
|
:update-sync-state
|
||||||
(fn [{:keys [sync-state sync-data] :as db} [_ error sync]]
|
(fn [cofx [_ error sync]]
|
||||||
(let [{:keys [highestBlock currentBlock] :as state}
|
(models/update-sync-state cofx error sync)))
|
||||||
(js->clj sync :keywordize-keys true)
|
|
||||||
syncing? (> (- highestBlock currentBlock) constants/blocks-per-hour)
|
|
||||||
new-state (cond
|
|
||||||
error :offline
|
|
||||||
syncing? (if (= sync-state :done)
|
|
||||||
:pending
|
|
||||||
:in-progress)
|
|
||||||
:else (if (or (= sync-state :done)
|
|
||||||
(= sync-state :pending))
|
|
||||||
:done
|
|
||||||
:synced))]
|
|
||||||
(cond-> db
|
|
||||||
(when (and (not= sync-data state) (= :in-progress new-state)))
|
|
||||||
(assoc :sync-data state)
|
|
||||||
(when (not= sync-state new-state))
|
|
||||||
(assoc :sync-state new-state)))))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:check-sync
|
:check-sync-state
|
||||||
(fn [{{:keys [web3]} :db} _]
|
(fn [cofx _]
|
||||||
{::web3-get-syncing web3
|
(models/check-sync-state cofx)))
|
||||||
:dispatch-later [{:ms 10000 :dispatch [:check-sync]}]}))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:initialize-sync-listener
|
:start-check-sync-state
|
||||||
(fn [{{:keys [sync-listening-started network account/account] :as db} :db} _]
|
(fn [cofx _]
|
||||||
(when (and (not sync-listening-started)
|
(models/start-check-sync-state cofx)))
|
||||||
(not (ethereum-utils/network-with-upstream-rpc? (get-in account [:networks network]))))
|
|
||||||
{:db (assoc db :sync-listening-started true)
|
|
||||||
:dispatch [:check-sync]})))
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
(ns status-im.protocol.models
|
||||||
|
(:require [status-im.constants :as constants]
|
||||||
|
[status-im.utils.semaphores :as semaphores]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||||
|
|
||||||
|
(defn update-sync-state
|
||||||
|
[{:keys [sync-state sync-data] :as db} error sync]
|
||||||
|
(let [{:keys [highestBlock currentBlock] :as state}
|
||||||
|
(js->clj sync :keywordize-keys true)
|
||||||
|
syncing? (> (- highestBlock currentBlock) constants/blocks-per-hour)
|
||||||
|
new-state (cond
|
||||||
|
error :offline
|
||||||
|
syncing? (if (= sync-state :done)
|
||||||
|
:pending
|
||||||
|
:in-progress)
|
||||||
|
:else (if (or (= sync-state :done)
|
||||||
|
(= sync-state :pending))
|
||||||
|
:done
|
||||||
|
:synced))]
|
||||||
|
(cond-> db
|
||||||
|
(and (not= sync-data state) (= :in-progress new-state))
|
||||||
|
(assoc :sync-data state)
|
||||||
|
(not= sync-state new-state)
|
||||||
|
(assoc :sync-state new-state))))
|
||||||
|
|
||||||
|
(defn check-sync-state
|
||||||
|
[{{:keys [web3] :as db} :db :as cofx}]
|
||||||
|
(if (:account/account db)
|
||||||
|
{::web3-get-syncing web3
|
||||||
|
:dispatch-later [{:ms 10000 :dispatch [:check-sync-state]}]}
|
||||||
|
(semaphores/free :check-sync-state? cofx)))
|
||||||
|
|
||||||
|
(defn start-check-sync-state
|
||||||
|
[{{:keys [network account/account] :as db} :db :as cofx}]
|
||||||
|
(when (and (not (semaphores/locked? :check-sync-state? cofx))
|
||||||
|
(not (ethereum/network-with-upstream-rpc? (get-in account [:networks network]))))
|
||||||
|
(handlers-macro/merge-fx cofx
|
||||||
|
{:dispatch [:check-sync-state]}
|
||||||
|
(semaphores/lock :check-sync-state?))))
|
|
@ -41,6 +41,7 @@
|
||||||
:peers-count 0
|
:peers-count 0
|
||||||
:peers-summary []
|
:peers-summary []
|
||||||
:notifications {}
|
:notifications {}
|
||||||
|
:semaphores #{}
|
||||||
:network constants/default-network
|
:network constants/default-network
|
||||||
:networks/networks constants/default-networks
|
:networks/networks constants/default-networks
|
||||||
:inbox/wnodes constants/default-wnodes
|
:inbox/wnodes constants/default-wnodes
|
||||||
|
@ -84,7 +85,6 @@
|
||||||
|
|
||||||
;;;;NODE
|
;;;;NODE
|
||||||
|
|
||||||
(spec/def ::sync-listening-started (spec/nilable boolean?))
|
|
||||||
(spec/def ::sync-state (spec/nilable #{:pending :in-progress :synced :done :offline}))
|
(spec/def ::sync-state (spec/nilable #{:pending :in-progress :synced :done :offline}))
|
||||||
(spec/def ::sync-data (spec/nilable map?))
|
(spec/def ::sync-data (spec/nilable map?))
|
||||||
|
|
||||||
|
@ -169,6 +169,8 @@
|
||||||
; Shows that push notification used to start the application is processed
|
; Shows that push notification used to start the application is processed
|
||||||
(spec/def :push-notifications/initial? (spec/nilable boolean?))
|
(spec/def :push-notifications/initial? (spec/nilable boolean?))
|
||||||
|
|
||||||
|
(spec/def ::semaphores set?)
|
||||||
|
|
||||||
(spec/def ::db (allowed-keys
|
(spec/def ::db (allowed-keys
|
||||||
:opt
|
:opt
|
||||||
[:contacts/contacts
|
[:contacts/contacts
|
||||||
|
@ -241,12 +243,12 @@
|
||||||
::mailserver-status
|
::mailserver-status
|
||||||
::peers-count
|
::peers-count
|
||||||
::peers-summary
|
::peers-summary
|
||||||
::sync-listening-started
|
|
||||||
::sync-state
|
::sync-state
|
||||||
::sync-data
|
::sync-data
|
||||||
::network
|
::network
|
||||||
::chain
|
::chain
|
||||||
::app-state
|
::app-state
|
||||||
|
::semaphores
|
||||||
:navigation/view-id
|
:navigation/view-id
|
||||||
:navigation/navigation-stack
|
:navigation/navigation-stack
|
||||||
:navigation/prev-tab-view-id
|
:navigation/prev-tab-view-id
|
||||||
|
|
|
@ -298,7 +298,7 @@
|
||||||
(fn [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks
|
(fn [{:keys [accounts/accounts accounts/create contacts/contacts networks/networks
|
||||||
network network-status peers-count peers-summary view-id navigation-stack
|
network network-status peers-count peers-summary view-id navigation-stack
|
||||||
status-module-initialized? status-node-started? device-UUID
|
status-module-initialized? status-node-started? device-UUID
|
||||||
push-notifications/initial?]
|
push-notifications/initial? semaphores]
|
||||||
:or [network (get app-db :network)]} [_ address]]
|
:or [network (get app-db :network)]} [_ address]]
|
||||||
(let [console-contact (get contacts constants/console-chat-id)
|
(let [console-contact (get contacts constants/console-chat-id)
|
||||||
current-account (accounts address)
|
current-account (accounts address)
|
||||||
|
@ -319,7 +319,8 @@
|
||||||
:push-notifications/initial? initial?
|
:push-notifications/initial? initial?
|
||||||
:peers-summary peers-summary
|
:peers-summary peers-summary
|
||||||
:peers-count peers-count
|
:peers-count peers-count
|
||||||
:device-UUID device-UUID)
|
:device-UUID device-UUID
|
||||||
|
:semaphores semaphores)
|
||||||
console-contact
|
console-contact
|
||||||
(assoc :contacts/contacts {constants/console-chat-id console-contact})))))
|
(assoc :contacts/contacts {constants/console-chat-id console-contact})))))
|
||||||
|
|
||||||
|
@ -329,7 +330,7 @@
|
||||||
{:dispatch-n (cond-> [[:initialize-account-db address]
|
{:dispatch-n (cond-> [[:initialize-account-db address]
|
||||||
[:initialize-protocol address]
|
[:initialize-protocol address]
|
||||||
[:fetch-web3-node-version]
|
[:fetch-web3-node-version]
|
||||||
[:initialize-sync-listener]
|
[:start-check-sync-state]
|
||||||
[:load-contacts]
|
[:load-contacts]
|
||||||
[:initialize-chats]
|
[:initialize-chats]
|
||||||
[:initialize-browsers]
|
[:initialize-browsers]
|
||||||
|
|
|
@ -273,8 +273,4 @@
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:start-wallet-transactions-sync
|
:start-wallet-transactions-sync
|
||||||
(fn [cofx _]
|
(fn [cofx _]
|
||||||
(when-not (get-in cofx [:db :wallet :transactions-sync-started?])
|
(wallet.transactions/start-sync cofx)))
|
||||||
(handlers-macro/merge-fx cofx
|
|
||||||
(wallet.transactions/load-missing-chat-transactions)
|
|
||||||
(wallet.transactions/sync)
|
|
||||||
(wallet.transactions/set-sync-started)))))
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
(ns status-im.utils.semaphores)
|
||||||
|
|
||||||
|
(defn lock [semaphore {:keys [db]}]
|
||||||
|
{:pre [(keyword? semaphore)]}
|
||||||
|
{:db (update db :semaphores conj semaphore)})
|
||||||
|
|
||||||
|
(defn free [semaphore {:keys [db]}]
|
||||||
|
{:pre [(keyword? semaphore)]}
|
||||||
|
(update db :semaphores disj semaphore))
|
||||||
|
|
||||||
|
(defn locked? [semaphore cofx]
|
||||||
|
{:pre [(keyword? semaphore)]}
|
||||||
|
((get-in cofx [:db :semaphores]) semaphore))
|
Loading…
Reference in New Issue