Add a long running task to transfer events to Go when the user logs in, rename interceptors namespace to core, send events in batches, capture s/on-will-focus, capture navigate-to-cofx, stop long running task if any event fails validation, not quite ready yet, needs more testing

Remove redudant println, don't stop the task in case of a bad event, just reject that batch, capture navigate-to-cofx events with an effect, capture parts of screens/on-will-focus event

Fix lint

Shorten comment widths, update  to use less brackets, call events reset once, double run safety for long running task

Call onboard after stopping

Reset periodic-tasks-chan to  on close, formatting

Get rid of redundant inline function

Update go version to point to 0.75.1

Signed-off-by: Shivek Khurana <shivek@status.im>
This commit is contained in:
Shivek Khurana 2021-04-06 18:02:08 +05:30
parent 93ce02b547
commit ed4e227144
No known key found for this signature in database
GPG Key ID: 9BEB56E6E62968C7
10 changed files with 141 additions and 43 deletions

View File

@ -74,6 +74,7 @@
[theme-switcher]
[rn/view
(for [{:keys [name]} screens]
^{:key name}
[rn/touchable-opacity {:on-press #(navigation/navigate-to name nil)}
[rn/view {:style {:padding-vertical 8}}
[quo/text (str "Preview " name)]]])]])

View File

@ -0,0 +1,97 @@
(ns status-im.anon-metrics.core
(:require [status-im.ethereum.json-rpc :as json-rpc]
[taoensso.timbre :as log]
[re-frame.core :as re-frame]
[re-frame.interceptor :refer [->interceptor]]
[status-im.utils.async :refer [async-periodic-exec async-periodic-stop!]]
[status-im.utils.platform :as platform]
[status-im.utils.build :as build]
[status-im.utils.fx :as fx]
[status-im.anon-metrics.transformers :as txf]))
(defonce events-foyer (atom []))
(defonce periodic-tasks-chan (atom nil))
(defn onboard-events
"Check if there are any events in the foyer,
flush them to the backend and clear foyer on-success."
[]
(let [outstanding-events @events-foyer]
(when (seq outstanding-events)
(reset! events-foyer [])
(json-rpc/call
{:method "appmetrics_saveAppMetrics"
:params [outstanding-events]
:on-success #()
:on-error (fn [err]
(log/error {:error err
:events outstanding-events})
(log/warn "All outstanding events will be rejected"))}))))
(re-frame/reg-fx
::transfer-data
(fn [transfer?]
(if (and transfer?
;; double run safety
(not @periodic-tasks-chan))
(do
(log/info "[anon-metrics] Start collection service")
(reset! periodic-tasks-chan
;; interval = 4000 ms (run every `interval` ms)
;; timeout = 5000 ms (exit if the fn doesn't exit within `timeout` ms)
(async-periodic-exec onboard-events 4000 5000)))
(do
(log/info "[anon-metrics] Stop collection service")
(async-periodic-stop! @periodic-tasks-chan)
(reset! periodic-tasks-chan nil)
;; final onboard, will save and clear any pending events
(onboard-events)))))
(fx/defn start-transferring
[_]
{::transfer-data true})
(fx/defn stop-transferring
[_]
{::transfer-data false})
(defn transform-and-log [context]
(when-let [transformed-payload (txf/transform context)]
(swap!
events-foyer
conj
{:event (-> context :coeffects :event first)
:value transformed-payload
:app_version build/version
:os platform/os})))
(defn catch-events-before [context]
(transform-and-log context)
context)
(def interceptor
(->interceptor
:id :catch-events
:before catch-events-before))
(re-frame/reg-fx ::transform-and-log transform-and-log)
(fx/defn hoax-capture-event
"Due to usage of fx/defn with fx/merge, it might not be able to
intercept some events (like navigate-to-cofx). In cases like that,
this hoax capture event can be used in conjunction with `fx/merge`"
{:events [::hoax-capture-event]}
[_ {:keys [og-event]}]
;; re-shape event to look like a context object
{::transform-and-log {:coeffects {:event og-event}}})
(comment
;; read the database
(def events-in-db (atom nil))
(->> events-in-db
deref
(take-last 5))
(json-rpc/call {:method "appmetrics_getAppMetrics"
:params [1000 0] ; limit, offset
:on-success #(reset! events-in-db %)}))

View File

@ -1,27 +0,0 @@
(ns status-im.anon-metrics.interceptors
(:require [status-im.ethereum.json-rpc :as json-rpc]
[taoensso.timbre :as log]
[re-frame.interceptor :refer [->interceptor]]
[status-im.utils.platform :as platform]
[status-im.utils.build :as build]
[status-im.anon-metrics.transformers :as txf]))
(defn transform-and-log [context]
(log/info :catch-event-fn (get-in context [:coeffects :event]))
(when-let [transformed-payload (txf/transform context)]
(json-rpc/call {:method "appmetrics_saveAppMetrics"
:params [[{:event (-> context :coeffects :event first)
:value transformed-payload
:app_version build/version
:os platform/os}]]
:on-failure #(log/error)})))
(defn catch-events-before [context]
(log/info "catch-events/interceptor fired")
(transform-and-log context)
context)
(def catch-events
(->interceptor
:id :catch-events
:before catch-events-before))

View File

@ -1,14 +1,24 @@
(ns status-im.anon-metrics.transformers)
(defn navigate-to-txf [context]
{:view-id (second context)
:params (-> context
(nth 2)
(select-keys [:screen]))})
(let [event (-> context :coeffects :event)]
{:view_id (second event)
:params {:screen (get-in event [1 :screen] "")}}))
(def transformations
{:navigate-to navigate-to-txf})
(defn screens-on-will-focus-txf [context]
(let [view-id (-> context :coeffects :event second)]
;; we need this check because in some cases, :screens/on-will-focus is dispatched
;; after navigate to this check ensures that only the events that are not handled
;; via navigate to are captured hence avoiding duplicates
(when (#{:chat :empty-tab :wallet :status :my-profile} view-id)
{:view_id view-id
:params {:screen ""}})))
(def value-transformations
{:navigate-to navigate-to-txf
:screens/on-will-focus screens-on-will-focus-txf})
(defn transform [ctx]
(when-let [txf (-> ctx first transformations)]
(when-let [txf (-> ctx :coeffects :event first value-transformations)]
(txf ctx)))

View File

@ -185,7 +185,8 @@
"mailservers_addChatRequestRanges" {}
"mailservers_getChatRequestRanges" {}
"mailservers_deleteChatRequestRange" {}
"appmetrics_saveAppMetrics" {}})
"appmetrics_saveAppMetrics" {}
"appmetrics_getAppMetrics" {}})
(defn on-error-retry
[call-method {:keys [method number-of-retries delay on-error] :as arg}]

View File

@ -16,6 +16,7 @@
[status-im.ui.components.permissions :as permissions]
[status-im.utils.utils :as utils]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.anon-metrics.core :as anon-metrics]
clojure.set
status-im.currency.core
status-im.navigation
@ -185,7 +186,8 @@
(chat/preload-chat-data cofx constants/timeline-chat-id)))
(fx/defn on-will-focus
{:events [:screens/on-will-focus]}
{:events [:screens/on-will-focus]
:interceptors [anon-metrics/interceptor]}
[cofx view-id]
(fx/merge cofx
#(case view-id

View File

@ -1,5 +1,6 @@
(ns status-im.multiaccounts.login.core
(:require [re-frame.core :as re-frame]
[status-im.anon-metrics.core :as anon-metrics]
[status-im.chat.models.loading :as chat.loading]
[status-im.contact.core :as contact]
[status-im.data-store.settings :as data-store.settings]
@ -361,6 +362,8 @@
::json-rpc/call
[{:method "web3_clientVersion"
:on-success #(re-frame/dispatch [::initialize-web3-client-version %])}]}
;; Start tasks to save usage data locally
(anon-metrics/start-transferring)
;;FIXME
(when nodes
(fleet/set-nodes :eth.contract nodes))

View File

@ -1,5 +1,6 @@
(ns status-im.multiaccounts.logout.core
(:require [re-frame.core :as re-frame]
[status-im.anon-metrics.core :as anon-metrics]
[status-im.i18n.i18n :as i18n]
[status-im.init.core :as init]
[status-im.native-module.core :as status]
@ -20,6 +21,7 @@
:keychain/clear-user-password key-uid
::init/open-multiaccounts #(re-frame/dispatch [::init/initialize-multiaccounts % {:logout? logout?}])}
(notifications/logout-disable)
(anon-metrics/stop-transferring)
(keychain/save-auth-method key-uid auth-method)
(transport/stop-whisper)
(wallet/clear-timeouts)

View File

@ -3,7 +3,7 @@
[status-im.ui.screens.routing.core :as navigation]
[taoensso.timbre :as log]
[status-im.utils.fx :as fx]
[status-im.anon-metrics.interceptors :as anon-metrics]))
[status-im.anon-metrics.core :as anon-metrics]))
(re-frame/reg-fx
::navigate-to
@ -38,15 +38,16 @@
(assoc-in [:navigation/screen-params view] screen-params)))
(fx/defn navigate-to-cofx
[{:keys [db]} go-to-view-id screen-params]
[{:keys [db] :as cofx} go-to-view-id screen-params]
{:db
(-> (assoc db :view-id go-to-view-id)
(all-screens-params go-to-view-id screen-params))
::navigate-to [go-to-view-id screen-params]})
::navigate-to [go-to-view-id screen-params]
;; simulate a navigate-to event so it can be captured be anon-metrics
::anon-metrics/transform-and-log {:coeffects {:event [:navigate-to go-to-view-id screen-params]}}})
(fx/defn navigate-to
{:events [:navigate-to]
:interceptors [anon-metrics/catch-events]}
{:events [:navigate-to]}
[cofx go-to-view-id screen-params]
(navigate-to-cofx cofx go-to-view-id screen-params))
@ -62,7 +63,7 @@
(fx/defn navigate-replace
{:events [:navigate-replace]
:interceptors [anon-metrics/catch-events]}
:interceptors [anon-metrics/interceptor]}
[{:keys [db]} go-to-view-id screen-params]
(let [db (cond-> (assoc db :view-id go-to-view-id)
(seq screen-params)

View File

@ -40,7 +40,7 @@
(recur acc (seq acc)))))))
(defn task-queue
"Creates `core.async` channel which will process 0 arg functions put there in serial fashon.
"Creates `core.async` channel which will process 0 arg functions put there in serial fashion.
Takes the same argument/s as `core.async/chan`, those arguments will be delegated to the
channel constructor.
Returns task-queue where tasks represented by 0 arg task functions can be put for processing."
@ -100,3 +100,11 @@
(async/alts! [finished-chan (timeout timeout-ms)])
(recur))))
do-now-chan))
(comment
(def c (atom nil))
(let [periodic-task-chan (async-periodic-exec #(prn :task) 5000 1000)]
(reset! c periodic-task-chan))
(async-periodic-stop! @c))