Report messages as "processed" to status-go only after they were successfully stored in the DB.

Signed-off-by: Igor Mandrigin <i@mandrigin.ru>
This commit is contained in:
Igor Mandrigin 2019-01-10 17:54:37 +01:00
parent 13b6295469
commit e8de37f5ef
No known key found for this signature in database
GPG Key ID: 4A0EDDE26E66BC8B
8 changed files with 110 additions and 28 deletions

View File

@ -5,21 +5,20 @@
;; Seen messages
(fx/defn receive-seen
[{:keys [db js-obj]} chat-id sender {:keys [message-ids]}]
(merge {:transport/confirm-messages-processed [{:web3 (:web3 db)
:js-obj js-obj}]}
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(select-keys message-ids)
keys)]
(let [statuses (map (fn [message-id]
{:chat-id chat-id
:message-id message-id
:public-key sender
:status :seen})
seen-messages-ids)]
{:db (reduce (fn [acc {:keys [message-id] :as status}]
(assoc-in acc [:chats chat-id :message-statuses
message-id sender]
status))
db
statuses)
:data-store/tx [(user-statuses-store/save-statuses-tx statuses)]}))))
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(select-keys message-ids)
keys)]
(let [statuses (map (fn [message-id]
{:chat-id chat-id
:message-id message-id
:public-key sender
:status :seen})
seen-messages-ids)]
{:db (reduce (fn [acc {:keys [message-id] :as status}]
(assoc-in acc [:chats chat-id :message-statuses
message-id sender]
status))
db
statuses)
:data-store/tx [{:transaction (user-statuses-store/save-statuses-tx statuses)
:success-event [:message/message-persisted js-obj]}]})))

View File

@ -111,7 +111,7 @@
(fx/defn add-message
[{:keys [db] :as cofx}
{{:keys [chat-id message-id clock-value timestamp from] :as message} :message
:keys [current-chat? batch? last-clock-value]}]
:keys [current-chat? batch? last-clock-value raw-message]}]
(let [current-public-key (accounts.db/current-public-key cofx)
prepared-message (-> message
(prepare-message chat-id current-chat?)
@ -136,7 +136,10 @@
(not= from current-public-key))
(update-in [:chats chat-id :loaded-unviewed-messages-ids]
(fnil conj #{}) message-id))
:data-store/tx [(messages-store/save-message-tx prepared-message)]}
:data-store/tx [(merge
{:transaction (messages-store/save-message-tx prepared-message)}
(when raw-message
{:success-event [:message/message-persisted raw-message]}))]}
(when (and platform/desktop?
(not batch?)
(not (system-message? prepared-message)))
@ -196,11 +199,10 @@
;; TODO (cammellos): Refactor so it's not computed twice
(add-outgoing-status current-public-key))]
(fx/merge cofx
{:transport/confirm-messages-processed [{:web3 web3
:js-obj js-obj}]}
(add-message {:batch? true
:message message
:current-chat current-chat?})
:current-chat current-chat?
:raw-message js-obj})
;; Checking :outgoing here only works for now as we don't have a :seen
;; status for public chats, if we add processing of our own messages
;; for 1-to-1 care needs to be taken not to override the :seen status
@ -468,6 +470,11 @@
[{:keys [db]} chat-id message-id]
{:db (update-in db [:chats chat-id :messages message-id :expanded?] not)})
(fx/defn confirm-message-processed
[{:keys [db]} raw-message]
{:transport/confirm-messages-processed [{:web3 (:web3 db)
:js-obj raw-message}]})
;; effects
(re-frame.core/reg-fx

View File

@ -46,14 +46,37 @@
(then
#(data-source/open-account address password encryption-key))))
(defn merge-events-of-type [success-events event-type]
;; merges data value of events of specified type together
;; keeps the other events intact
;; [[:e1 [:d1]] [:e1 [:d2]]] => [[:e1 [:d1 :d2]]]
(let [event-to-merge? (fn [event]
(and (vector? event)
(= (first event) event-type)
(vector? (second event))))
unmergeable-events (filter (complement event-to-merge?) success-events)
mergeable-events (filter event-to-merge? success-events)]
(into []
(into unmergeable-events
(when-not (empty? mergeable-events)
(let [merged-values (reduce into
(map second mergeable-events))]
[(into [event-type]
(when merged-values
[merged-values]))]))))))
(defn- merge-persistence-events [success-events]
(merge-events-of-type success-events :message/message-persisted))
(defn- perform-transactions [raw-transactions realm]
(let [success-events (keep :success-event raw-transactions)
transactions (map (fn [{:keys [transaction] :as f}]
(or transaction f)) raw-transactions)]
(data-source/write realm #(doseq [transaction transactions]
(transaction realm)))
(doseq [event success-events]
(re-frame/dispatch event))))
(let [optimized-events (merge-persistence-events success-events)]
(doseq [event optimized-events]
(re-frame/dispatch event)))))
(re-frame/reg-fx
:data-store/base-tx

View File

@ -788,6 +788,11 @@
(fn [cofx [_ chat-id message-id status]]
(chat.message/update-message-status cofx chat-id message-id status)))
(handlers/register-handler-fx
:message/message-persisted
(fn [cofx [_ raw-message]]
(chat.message/confirm-message-processed cofx raw-message)))
;; signal module
(handlers/register-handler-fx

View File

@ -150,7 +150,6 @@
(apply fx/merge cofx resend-contact-message-fxs))))
(re-frame/reg-fx
;; TODO(janherich): this should be called after `:data-store/tx` actually
:transport/confirm-messages-processed
(fn [messages]
(let [{:keys [web3]} (first messages)

View File

@ -56,8 +56,6 @@
(is message))
(testing "it marks the message as outgoing"
(is (= true (:outgoing message))))
(testing "it confirm the message as processed"
(is (:transport/confirm-messages-processed actual)))
(testing "it stores the message"
(is (:data-store/tx actual)))
(testing "it does not send a seen confirmation"

View File

@ -0,0 +1,49 @@
(ns status-im.test.data-store.core
(:require [cljs.test :refer-macros [deftest is testing use-fixtures]]
[status-im.utils.utils :as utils]
[clojure.string :as string]
[status-im.data-store.core :as core]))
(deftest merge-events-of-type
(def events-test [[:event1 [:data1]] [:event1 [:data2]]
[:event2 [:data3]] [:event2 [:data4]]
[:event3 [:data5]]
[:event4 :data6]
[:event5]])
(testing "merging-events-with-data"
(is (= (core/merge-events-of-type events-test :event1)
[[:event1 [:data1 :data2]]
[:event2 [:data3]] [:event2 [:data4]]
[:event3 [:data5]]
[:event4 :data6]
[:event5]]))
(is (= (core/merge-events-of-type events-test :event2)
[[:event2 [:data3 :data4]]
[:event1 [:data1]] [:event1 [:data2]]
[:event3 [:data5]]
[:event4 :data6]
[:event5]]))
(is (= (core/merge-events-of-type events-test :event3)
[[:event3 [:data5]]
[:event1 [:data1]] [:event1 [:data2]]
[:event2 [:data3]] [:event2 [:data4]]
[:event4 :data6]
[:event5]]))
;; we can't group non-vector event data
(is (= (core/merge-events-of-type events-test :event4)
[[:event1 [:data1]] [:event1 [:data2]]
[:event2 [:data3]] [:event2 [:data4]]
[:event3 [:data5]]
[:event4 :data6]
[:event5]]))
;; we can't group non-vector event data
(is (= (core/merge-events-of-type events-test :event5)
[[:event1 [:data1]] [:event1 [:data2]]
[:event2 [:data3]] [:event2 [:data4]]
[:event3 [:data5]]
[:event4 :data6]
[:event5]]))))

View File

@ -2,6 +2,7 @@
(:require [doo.runner :refer-macros [doo-tests]]
[status-im.test.contacts.db]
[status-im.test.data-store.chats]
[status-im.test.data-store.core]
[status-im.test.data-store.realm.core]
[status-im.test.extensions.core]
[status-im.test.extensions.ethereum]
@ -75,6 +76,7 @@
'status-im.test.chat.models
'status-im.test.init.core
'status-im.test.data-store.chats
'status-im.test.data-store.core
'status-im.test.data-store.realm.core
'status-im.test.extensions.core
'status-im.test.mailserver.core