* Fix #1886

Completly rework the way how async handlers work

Delay further processing of message till async handler returns result

* Fix indent

* Fix #1903
This commit is contained in:
Jan Herich 2017-09-21 13:08:51 +02:00 committed by Roman Volosovskyi
parent bce18bf32c
commit 805d874846
8 changed files with 121 additions and 183 deletions

View File

@ -352,26 +352,27 @@ function handleSend(params, context) {
gasPrice: calculateGasPrice(params["bot-db"]["sliderValue"])
};
web3.eth.sendTransaction(data, function(error, hash) {
if (error) {
status.sendSignal("handler-data", {
status.sendSignal("handler-result", {
status: "failed",
messageId: context["message-id"],
error: error
error: {
markup: status.components.validationMessage(
I18n.t('validation_tx_title'),
I18n.t('validation_tx_failed')
)
},
origParams: context["orig-params"]
});
} else {
status.sendSignal("handler-data", {
status: "sent",
messageId: context["message-id"],
hash: hash
status.sendSignal("handler-result", {
status: "success",
hash: hash,
origParams: context["orig-params"]
});
}
});
return {
status: 'not-confirmed'
};
// async handler, so we don't return anything immediately
}
function previewSend(params, context) {
@ -450,36 +451,6 @@ function previewSend(params, context) {
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 {
markup: status.components.view(
{
@ -512,6 +483,7 @@ var send = {
params: paramsSend,
validator: validateSend,
handler: handleSend,
asyncHandler: true,
preview: previewSend,
shortPreview: shortPreviewSend
};

View File

@ -14,8 +14,6 @@ I18n.translations = {
send_explanation_3: 'probably within 30 seconds.',
send_explanation_4: 'probably within a few seconds.',
send_sending_to: 'to ',
send_transaction_pending: 'transaction pending',
send_transaction_failed: 'transaction failed',
eth: 'ETH',
@ -25,6 +23,8 @@ I18n.translations = {
request_requesting_from: 'from ',
validation_title: 'Amount',
validation_tx_title: 'Transaction',
validation_tx_failed: 'Transaction failed',
validation_amount_specified: 'Amount must be specified',
validation_invalid_number: 'Amount is not valid number',
validation_amount_is_too_small: 'Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)',

View File

@ -27,6 +27,7 @@ Command.prototype.create = function (com) {
this.description = com.description;
this.handler = com.handler;
this["has-handler"] = com.handler != null;
this["async-handler"] = (com.handler != null) && com.asyncHandler
this["registered-only"] = com.registeredOnly;
this.validator = com.validator;
this.color = com.color;
@ -41,6 +42,7 @@ Command.prototype.create = function (com) {
this["execute-immediately?"] = com.executeImmediately;
this["sequential-params"] = com.sequentialParams;
this["hide-send-button"] = com.hideSendButton;
this.addToCatalog();
return this;

View File

@ -13,14 +13,13 @@
(defn generate-context
"Generates context for jail call"
[{:keys [chats handler-data] :accounts/keys [current-account-id]} message-id chat-id to group-id]
[{:keys [chats] :accounts/keys [current-account-id]} chat-id to group-id]
(merge {:platform platform/platform
:from current-account-id
:to to
:chat {:chat-id chat-id
:group-chat (or (get-in chats [chat-id :group-chat])
(not (nil? group-id)))}
:handler-data (get handler-data message-id)}
(not (nil? group-id)))}}
i18n/delimeters))
;;;; Coeffects
@ -70,7 +69,7 @@
[trim-v]
(fn [{:keys [db]}
[{{:keys [command content-command params type]} :content
:keys [chat-id jail-id group-id message-id] :as message}
:keys [chat-id jail-id group-id message-id handler-data] :as message}
data-type]]
(let [{:keys [chats]
:accounts/keys [current-account-id]
@ -85,7 +84,7 @@
data-type]
to (get-in contacts [chat-id :address])
jail-params {:parameters params
:context (generate-context db message-id chat-id to group-id)}]
:context (generate-context db chat-id to group-id)}]
{:chat-fx/call-jail {:jail-id jail-id
:path path
:params jail-params

View File

@ -107,20 +107,9 @@
params' (assoc params :command content')]
(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!
(u/side-effect!
(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 [::save-command! add-to-chat-id params hidden-params])
(when (not= add-to-chat-id wallet-chat-id)
@ -163,11 +152,15 @@
to (get-in contacts [chat-id :address])
identity (or owner-id bot chat-id)
bot-db (get bot-db (or bot chat-id))
;; TODO what's actually semantic difference between `:parameters` and `:context`
;; and do we have some clear API for both ? seems very messy and unorganized now
jail-params {:parameters params
:context {:from address
:context (cond-> {:from address
:to to
:current-account (get accounts current-account-id)
:message-id id}}]
:message-id id}
(:async-handler command)
(assoc :orig-params orig-params))}]
(dispatch
[:check-and-load-commands!
identity
@ -175,8 +168,11 @@
{:jail-id identity
:path [handler-type name :handler]
:params jail-params
:callback (fn [res]
(dispatch [:command-handler! chat-id orig-params res]))})])))))
:callback (if (:async-handler command) ; async handler, we ignore return value
(fn [_]
(log/debug "Async command handler called"))
(fn [res]
(dispatch [:command-handler! chat-id orig-params res])))})])))))
(register-handler :prepare-message
(u/side-effect!

View File

@ -1,31 +0,0 @@
(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])))))

View File

@ -10,14 +10,13 @@
[status-im.constants :refer [console-chat-id]]
[status-im.i18n :refer [get-contact-translated]]
[taoensso.timbre :as log]
[status-im.data-store.local-storage :as local-storage]
status-im.commands.events.jail))
[status-im.data-store.local-storage :as local-storage]))
(defn command-handler!
[_ [chat-id
{:keys [command] :as params}
{:keys [result error]}]]
(let [{:keys [context returned]} result
(let [{:keys [returned]} result
{handler-error :error} returned]
(cond
handler-error
@ -27,9 +26,7 @@
result
(let [command' (assoc command :handler-data returned)
params' (assoc params :command command')]
(if (:eth_sendTransaction context)
(dispatch [:wait-for-transaction (:id command) params'])
(dispatch [:prepare-command! chat-id params'])))
(dispatch [:prepare-command! chat-id params']))
(not (or error handler-error))
(dispatch [:prepare-command! chat-id params])

View File

@ -219,7 +219,10 @@
:markup data}])
"send-message" (dispatch [:send-message-from-jail {:chat-id chat_id
:message data}])
"handler-data" (dispatch [:set-handler-data chat_id data])
"handler-result" (let [orig-params (:origParams data)]
;; TODO(janherich): figure out and fix chat_id from event
(dispatch [:command-handler! (:chat-id orig-params) orig-params
{:result {:returned (dissoc data :origParams)}}]))
(log/debug "Unknown jail signal " type))))
(register-handler-fx