Fork me on GitHub
#crux
<
2021-02-25
>
Luis Santos18:02:24

How do know if a transaction was applied correctly or not and if not what was the reason for the failure? Example:

(api/submit-tx crux [[:crux.tx/put {:crux.db/id :account/transfer-money
                                    :crux.db/fn '(fn [ctx source-id dest-id amount]
                                                   (let [db (crux.api/db ctx)
                                                         source-entity (crux.api/entity db source-id)
                                                         dest-entity (crux.api/entity db dest-id)
                                                         tx {:source (:crux.db/id source-entity) :dest (:crux.db/id dest-entity) :amount amount}
                                                         _s (-> source-entity
                                                                (update :account/balance - amount)
                                                                (update :account/transactions conj tx))
                                                         _d (-> dest-entity
                                                                (update :account/balance + amount)
                                                                (update :account/transactions conj tx))]

                                                     (if (> (- (:account/balance source-entity) amount) 0)
                                                       [[:crux.tx/put _s]
                                                        [:crux.tx/put _d]]
                                                       (throw "Non-sufficient funds"))))}]])
I have a simple transaction function that transfers money between 2 accounts but it should fail if there aren't enough funds in the source account. The transaction works as expected but I would like to access the Exception information. Thanks

refset19:02:22

Hey 🙂 so tx-committed? (https://opencrux.com/reference/21.02-1.15.0/clojure-api.html#_tx_committed) should tell you whether the transaction succeeded, but short of inspecting logs or calling some side-effecting code within your transaction function there is currently no mechanism to observe why a transaction has failed, that I'm aware of. Note that there is a spectrum of failure modes (e.g. invalid source, compilation errors, timeouts, invalid list of return ops), but I'm guessing you are most concerned with logical failure. There probably are reasonably pleasant ways you could work with the side-effects option, perhaps using a core.async channel, but I don't have enough experience to confidently say what might be a good idea to try first. Hopefully someone else can offer a more specific suggestion... Maybe in future tx-committed? could return the error message / anomaly somehow, if it was stored somewhere :thinking_face:

Luis Santos19:02:25

I mixed commited and indexed concepts. But I guess tx-commited? works for now.

Luis Santos19:02:54

I guess having a side effect would not work if one was using the HTTP api for instance.

Luis Santos19:02:25

I would guess that the Error could be stored as part of the indexed transaction. But it would require all the functions to be pure. But I guess the same problem already exists. I can create a transaction that is not deterministic and different nodes would apply the same transaction in multiple ways.

Luis Santos19:02:34

Thanks @U899JBRPF. Your answer was helpful.

🙏 1
refset19:02:27

> I can create a transaction that is not deterministic and different nodes would apply the same transaction in multiple ways. Yes, technically you can, but please never do it 🙂 maybe we should add a big warning sign in the docs for this. Adding the logical error as data into the database is probably the right suggestion, now you mention it. "Non-sufficient funds" doesn't have to result in a Clojure-level transaction function error.