Implement possibility for async command handlers (#1857)
* Implement possibility for async command handlers Command handler can now return results asynchronously, and those results as saved and persisted, indexed by command message-id. * Address feedback raised in PR comments * Different handler codes + simplified error message
This commit is contained in:
parent
0fa863d366
commit
b889a07a86
|
@ -352,11 +352,26 @@ function handleSend(params, context) {
|
||||||
gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
|
gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
|
||||||
return web3.eth.sendTransaction(data);
|
web3.eth.sendTransaction(data, function(error, hash) {
|
||||||
} catch (err) {
|
if (error) {
|
||||||
return {error: err.message};
|
status.sendSignal("handler-data", {
|
||||||
}
|
status: "failed",
|
||||||
|
messageId: context["message-id"],
|
||||||
|
error: error
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
status.sendSignal("handler-data", {
|
||||||
|
status: "sent",
|
||||||
|
messageId: context["message-id"],
|
||||||
|
hash: hash
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'not-confirmed'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function previewSend(params, context) {
|
function previewSend(params, context) {
|
||||||
|
@ -435,6 +450,36 @@ function previewSend(params, context) {
|
||||||
markup = [firstRow];
|
markup = [firstRow];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(context["handler-data"]
|
||||||
|
&& context["handler-data"]["status"] === "sent")) {
|
||||||
|
var pendingRow = status.components.text(
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
color: "#9199a0",
|
||||||
|
fontSize: 12,
|
||||||
|
lineHeight: 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I18n.t('send_transaction_pending')
|
||||||
|
);
|
||||||
|
markup.push(pendingRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context["handler-data"]
|
||||||
|
&& context["handler-data"]["status"] === "failed") {
|
||||||
|
var errorRow = status.components.text(
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
color: "red",
|
||||||
|
fontSize: 12,
|
||||||
|
lineHeight: 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
I18n.t('send_transaction_failed')
|
||||||
|
);
|
||||||
|
markup.push(errorRow);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
markup: status.components.view(
|
markup: status.components.view(
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,8 @@ I18n.translations = {
|
||||||
send_explanation_3: 'probably within 30 seconds.',
|
send_explanation_3: 'probably within 30 seconds.',
|
||||||
send_explanation_4: 'probably within a few seconds.',
|
send_explanation_4: 'probably within a few seconds.',
|
||||||
send_sending_to: 'to ',
|
send_sending_to: 'to ',
|
||||||
|
send_transaction_pending: 'transaction pending',
|
||||||
|
send_transaction_failed: 'transaction failed',
|
||||||
|
|
||||||
eth: 'ETH',
|
eth: 'ETH',
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
|
|
||||||
(defn generate-context
|
(defn generate-context
|
||||||
"Generates context for jail call"
|
"Generates context for jail call"
|
||||||
[{:keys [chats] :accounts/keys [current-account-id]} chat-id to group-id]
|
[{:keys [chats handler-data] :accounts/keys [current-account-id]} message-id chat-id to group-id]
|
||||||
(merge {:platform platform/platform
|
(merge {:platform platform/platform
|
||||||
:from current-account-id
|
:from current-account-id
|
||||||
:to to
|
:to to
|
||||||
:chat {:chat-id chat-id
|
:chat {:chat-id chat-id
|
||||||
:group-chat (or (get-in chats [chat-id :group-chat])
|
:group-chat (or (get-in chats [chat-id :group-chat])
|
||||||
(not (nil? group-id)))}}
|
(not (nil? group-id)))}
|
||||||
|
:handler-data (get handler-data message-id)}
|
||||||
i18n/delimeters))
|
i18n/delimeters))
|
||||||
|
|
||||||
;;;; Coeffects
|
;;;; Coeffects
|
||||||
|
@ -69,7 +70,7 @@
|
||||||
[trim-v]
|
[trim-v]
|
||||||
(fn [{:keys [db]}
|
(fn [{:keys [db]}
|
||||||
[{{:keys [command content-command params type]} :content
|
[{{:keys [command content-command params type]} :content
|
||||||
:keys [chat-id jail-id group-id] :as message}
|
:keys [chat-id jail-id group-id message-id] :as message}
|
||||||
data-type]]
|
data-type]]
|
||||||
(let [{:keys [chats]
|
(let [{:keys [chats]
|
||||||
:accounts/keys [current-account-id]
|
:accounts/keys [current-account-id]
|
||||||
|
@ -84,7 +85,7 @@
|
||||||
data-type]
|
data-type]
|
||||||
to (get-in contacts [chat-id :address])
|
to (get-in contacts [chat-id :address])
|
||||||
jail-params {:parameters params
|
jail-params {:parameters params
|
||||||
:context (generate-context db chat-id to group-id)}]
|
:context (generate-context db message-id chat-id to group-id)}]
|
||||||
{:chat-fx/call-jail {:jail-id jail-id
|
{:chat-fx/call-jail {:jail-id jail-id
|
||||||
:path path
|
:path path
|
||||||
:params jail-params
|
:params jail-params
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
[status-im.data-store.chats :as chats]
|
[status-im.data-store.chats :as chats]
|
||||||
[status-im.data-store.contacts :as contacts]
|
[status-im.data-store.contacts :as contacts]
|
||||||
[status-im.data-store.messages :as messages]
|
[status-im.data-store.messages :as messages]
|
||||||
|
[status-im.data-store.handler-data :as handler-data]
|
||||||
[status-im.data-store.pending-messages :as pending-messages]
|
[status-im.data-store.pending-messages :as pending-messages]
|
||||||
[status-im.constants :refer [text-content-type
|
[status-im.constants :refer [text-content-type
|
||||||
content-type-command
|
content-type-command
|
||||||
|
@ -219,6 +220,7 @@
|
||||||
|
|
||||||
(-> db
|
(-> db
|
||||||
(assoc :chats chats')
|
(assoc :chats chats')
|
||||||
|
(assoc :handler-data (handler-data/get-all))
|
||||||
(dissoc :loaded-chats)
|
(dissoc :loaded-chats)
|
||||||
(init-console-chat true))))
|
(init-console-chat true))))
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
(:require [status-im.utils.handlers :refer [register-handler] :as u]
|
(:require [status-im.utils.handlers :refer [register-handler] :as u]
|
||||||
[clojure.string :as s]
|
[clojure.string :as s]
|
||||||
[status-im.data-store.messages :as messages]
|
[status-im.data-store.messages :as messages]
|
||||||
|
[status-im.data-store.handler-data :as handler-data]
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.utils.random :as random]
|
[status-im.utils.random :as random]
|
||||||
[status-im.utils.datetime :as time]
|
[status-im.utils.datetime :as time]
|
||||||
|
@ -105,9 +106,20 @@
|
||||||
params' (assoc params :command content')]
|
params' (assoc params :command content')]
|
||||||
(dispatch [:prepare-command! wallet-chat-id params'])))))))
|
(dispatch [:prepare-command! wallet-chat-id params'])))))))
|
||||||
|
|
||||||
|
(register-handler ::check-preview-refetch
|
||||||
|
(fn [db [_ chat-id {:keys [message-id] :as message}]]
|
||||||
|
(let [handler-data (get-in db [:handler-data message-id])]
|
||||||
|
(if (:fetch-preview handler-data)
|
||||||
|
(do (dispatch [:request-command-data (assoc message :jail-id chat-id) :preview])
|
||||||
|
(handler-data/save-data {:message-id message-id
|
||||||
|
:data (dissoc handler-data :fetch-preview)})
|
||||||
|
(update-in db [:handler-data message-id] dissoc :fetch-preview))
|
||||||
|
db))))
|
||||||
|
|
||||||
(register-handler ::send-command!
|
(register-handler ::send-command!
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [_ [_ add-to-chat-id params hidden-params]]
|
(fn [_ [_ add-to-chat-id params hidden-params]]
|
||||||
|
(dispatch [::check-preview-refetch add-to-chat-id (:command params)])
|
||||||
(dispatch [::add-command add-to-chat-id params])
|
(dispatch [::add-command add-to-chat-id params])
|
||||||
(dispatch [::save-command! add-to-chat-id params hidden-params])
|
(dispatch [::save-command! add-to-chat-id params hidden-params])
|
||||||
(when (not= add-to-chat-id wallet-chat-id)
|
(when (not= add-to-chat-id wallet-chat-id)
|
||||||
|
@ -150,7 +162,7 @@
|
||||||
to (get-in contacts [chat-id :address])
|
to (get-in contacts [chat-id :address])
|
||||||
identity (or owner-id bot chat-id)
|
identity (or owner-id bot chat-id)
|
||||||
bot-db (get bot-db (or bot chat-id))
|
bot-db (get bot-db (or bot chat-id))
|
||||||
params {:parameters params
|
jail-params {:parameters params
|
||||||
:context {:from address
|
:context {:from address
|
||||||
:to to
|
:to to
|
||||||
:current-account (get accounts current-account-id)
|
:current-account (get accounts current-account-id)
|
||||||
|
@ -161,7 +173,7 @@
|
||||||
#(status/call-jail
|
#(status/call-jail
|
||||||
{:jail-id identity
|
{:jail-id identity
|
||||||
:path [handler-type name :handler]
|
:path [handler-type name :handler]
|
||||||
:params params
|
:params jail-params
|
||||||
:callback (fn [res]
|
:callback (fn [res]
|
||||||
(dispatch [:command-handler! chat-id orig-params res]))})])))))
|
(dispatch [:command-handler! chat-id orig-params res]))})])))))
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
(s/def :chat/expandable-view-height-to-value (s/nilable number?))
|
(s/def :chat/expandable-view-height-to-value (s/nilable number?))
|
||||||
(s/def :chat/global-commands (s/nilable map?)) ; {key (keyword) command (map)} atm used for browse command
|
(s/def :chat/global-commands (s/nilable map?)) ; {key (keyword) command (map)} atm used for browse command
|
||||||
(s/def :chat/loading-allowed (s/nilable boolean?)) ;;allow to load more messages
|
(s/def :chat/loading-allowed (s/nilable boolean?)) ;;allow to load more messages
|
||||||
|
(s/def :chat/handler-data (s/nilable map?))
|
||||||
(s/def :chat/message-data (s/nilable map?))
|
(s/def :chat/message-data (s/nilable map?))
|
||||||
(s/def :chat/message-id->transaction-id (s/nilable map?))
|
(s/def :chat/message-id->transaction-id (s/nilable map?))
|
||||||
(s/def :chat/message-status (s/nilable map?))
|
(s/def :chat/message-status (s/nilable map?))
|
||||||
|
@ -29,4 +30,4 @@
|
||||||
(s/def :chat/new-request (s/nilable map?))
|
(s/def :chat/new-request (s/nilable map?))
|
||||||
(s/def :chat/raw-unviewed-messages (s/nilable vector?))
|
(s/def :chat/raw-unviewed-messages (s/nilable vector?))
|
||||||
(s/def :chat/bot-db (s/nilable map?))
|
(s/def :chat/bot-db (s/nilable map?))
|
||||||
(s/def :chat/geolocation (s/nilable map?))
|
(s/def :chat/geolocation (s/nilable map?))
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
(ns status-im.commands.events.jail
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-im.utils.handlers :as handlers]
|
||||||
|
[status-im.data-store.handler-data :as handler-data]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:save-handler-data
|
||||||
|
(fn [data]
|
||||||
|
(handler-data/save-data data)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:set-handler-data
|
||||||
|
[re-frame/trim-v]
|
||||||
|
(fn [{:keys [db]} [chat-id {:keys [messageId] :as data}]]
|
||||||
|
(let [;; this is very bad, we should refactor our db ASAP
|
||||||
|
message (->> (get-in db [:chats chat-id :messages])
|
||||||
|
(filter #(= (:message-id %) messageId))
|
||||||
|
first)
|
||||||
|
handler-data (cond-> (dissoc data :messageId)
|
||||||
|
;; message not there yet, indicate we want to re-fetch preview once it lands there
|
||||||
|
(nil? message)
|
||||||
|
(assoc :fetch-preview true))
|
||||||
|
old-handler-data (get-in db [:handler-data messageId] {})
|
||||||
|
new-handler-data (merge old-handler-data handler-data)]
|
||||||
|
(cond-> {:db (assoc-in db [:handler-data messageId] new-handler-data)
|
||||||
|
:save-handler-data {:message-id messageId
|
||||||
|
:data new-handler-data}}
|
||||||
|
;; message was already added to db, we can re-fetch preview
|
||||||
|
(not (nil? message))
|
||||||
|
(assoc :dispatch [:request-command-data (assoc message :jail-id chat-id) :preview])))))
|
|
@ -10,7 +10,8 @@
|
||||||
[status-im.constants :refer [console-chat-id]]
|
[status-im.constants :refer [console-chat-id]]
|
||||||
[status-im.i18n :refer [get-contact-translated]]
|
[status-im.i18n :refer [get-contact-translated]]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[status-im.data-store.local-storage :as local-storage]))
|
[status-im.data-store.local-storage :as local-storage]
|
||||||
|
status-im.commands.events.jail))
|
||||||
|
|
||||||
(defn command-handler!
|
(defn command-handler!
|
||||||
[_ [chat-id
|
[_ [chat-id
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
(ns status-im.data-store.handler-data
|
||||||
|
(:require [cljs.reader :as reader]
|
||||||
|
[status-im.data-store.realm.handler-data :as data-store]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
(defn get-all []
|
||||||
|
(->> (data-store/get-all-as-list)
|
||||||
|
(map (fn [{:keys [message-id data]}]
|
||||||
|
[message-id (reader/read-string data)]))
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(defn get-data [message-id]
|
||||||
|
(-> message-id data-store/get-by-message-id :data reader/read-string))
|
||||||
|
|
||||||
|
(defn save-data [handler-data]
|
||||||
|
(data-store/save (update handler-data :data pr-str)))
|
|
@ -0,0 +1,16 @@
|
||||||
|
(ns status-im.data-store.realm.handler-data
|
||||||
|
(:require [status-im.data-store.realm.core :as realm]))
|
||||||
|
|
||||||
|
(defn get-all []
|
||||||
|
(realm/get-all @realm/account-realm :handler-data))
|
||||||
|
|
||||||
|
(defn get-all-as-list []
|
||||||
|
(realm/realm-collection->list (get-all)))
|
||||||
|
|
||||||
|
(defn get-by-message-id
|
||||||
|
[message-id]
|
||||||
|
(realm/get-one-by-field-clj @realm/account-realm :handler-data :message-id message-id))
|
||||||
|
|
||||||
|
(defn save
|
||||||
|
[handler-data]
|
||||||
|
(realm/save @realm/account-realm :handler-data handler-data true))
|
|
@ -11,7 +11,7 @@
|
||||||
[status-im.data-store.realm.schemas.account.v10.core :as v10]
|
[status-im.data-store.realm.schemas.account.v10.core :as v10]
|
||||||
[status-im.data-store.realm.schemas.account.v11.core :as v11]
|
[status-im.data-store.realm.schemas.account.v11.core :as v11]
|
||||||
[status-im.data-store.realm.schemas.account.v12.core :as v12]
|
[status-im.data-store.realm.schemas.account.v12.core :as v12]
|
||||||
))
|
[status-im.data-store.realm.schemas.account.v13.core :as v13]))
|
||||||
|
|
||||||
;; put schemas ordered by version
|
;; put schemas ordered by version
|
||||||
(def schemas [{:schema v1/schema
|
(def schemas [{:schema v1/schema
|
||||||
|
@ -49,4 +49,7 @@
|
||||||
:migration v11/migration}
|
:migration v11/migration}
|
||||||
{:schema v12/schema
|
{:schema v12/schema
|
||||||
:schemaVersion 12
|
:schemaVersion 12
|
||||||
:migration v12/migration}])
|
:migration v12/migration}
|
||||||
|
{:schema v13/schema
|
||||||
|
:schemaVersion 13
|
||||||
|
:migration v13/migration}])
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
(ns status-im.data-store.realm.schemas.account.v13.core
|
||||||
|
(:require [status-im.data-store.realm.schemas.account.v11.chat :as chat]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.chat-contact :as chat-contact]
|
||||||
|
[status-im.data-store.realm.schemas.account.v6.command :as command]
|
||||||
|
[status-im.data-store.realm.schemas.account.v9.command-parameter :as command-parameter]
|
||||||
|
[status-im.data-store.realm.schemas.account.v7.contact :as contact]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.discover :as discover]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.kv-store :as kv-store]
|
||||||
|
[status-im.data-store.realm.schemas.account.v10.message :as message]
|
||||||
|
[status-im.data-store.realm.schemas.account.v12.pending-message :as pending-message]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.processed-message :as processed-message]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.request :as request]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.tag :as tag]
|
||||||
|
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
|
||||||
|
[status-im.data-store.realm.schemas.account.v5.contact-group :as contact-group]
|
||||||
|
[status-im.data-store.realm.schemas.account.v5.group-contact :as group-contact]
|
||||||
|
[status-im.data-store.realm.schemas.account.v8.local-storage :as local-storage]
|
||||||
|
[status-im.data-store.realm.schemas.account.v13.handler-data :as handler-data]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
(def schema [chat/schema
|
||||||
|
chat-contact/schema
|
||||||
|
command/schema
|
||||||
|
command-parameter/schema
|
||||||
|
contact/schema
|
||||||
|
discover/schema
|
||||||
|
kv-store/schema
|
||||||
|
message/schema
|
||||||
|
pending-message/schema
|
||||||
|
processed-message/schema
|
||||||
|
request/schema
|
||||||
|
tag/schema
|
||||||
|
user-status/schema
|
||||||
|
contact-group/schema
|
||||||
|
group-contact/schema
|
||||||
|
local-storage/schema
|
||||||
|
handler-data/schema])
|
||||||
|
|
||||||
|
(defn migration [old-realm new-realm]
|
||||||
|
(log/debug "migrating v13 account database: " old-realm new-realm))
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
(ns status-im.data-store.realm.schemas.account.v13.handler-data)
|
||||||
|
|
||||||
|
(def schema {:name :handler-data
|
||||||
|
:primaryKey :message-id
|
||||||
|
:properties {:message-id "string"
|
||||||
|
:data {:type "string"
|
||||||
|
:default "{}"}}})
|
|
@ -152,6 +152,7 @@
|
||||||
:chat/public-group-topic
|
:chat/public-group-topic
|
||||||
:chat/confirmation-code-sms-listener
|
:chat/confirmation-code-sms-listener
|
||||||
:chat/messages
|
:chat/messages
|
||||||
|
:chat/handler-data
|
||||||
:chat/loaded-chats
|
:chat/loaded-chats
|
||||||
:chat/bot-subscriptions
|
:chat/bot-subscriptions
|
||||||
:chat/new-request
|
:chat/new-request
|
||||||
|
|
|
@ -219,7 +219,7 @@
|
||||||
:markup data}])
|
:markup data}])
|
||||||
"send-message" (dispatch [:send-message-from-jail {:chat-id chat_id
|
"send-message" (dispatch [:send-message-from-jail {:chat-id chat_id
|
||||||
:message data}])
|
:message data}])
|
||||||
|
"handler-data" (dispatch [:set-handler-data chat_id data])
|
||||||
(log/debug "Unknown jail signal " type))))
|
(log/debug "Unknown jail signal " type))))
|
||||||
|
|
||||||
(register-handler-fx
|
(register-handler-fx
|
||||||
|
|
Loading…
Reference in New Issue