{"action":"opened","issue":{"url":"https://api.github.com/repos/roman01la/citrus/issues/35","repository_url":"https://api.github.com/repos/roman01la/citrus","labels_url":"https://api.github.com/repos/roman01la/citrus/issues/35/labels{/name}","comments_url":"https://api.github.com/repos/roman01la/citrus/issues/35/comments","events_url":"https://api.github.com/repos/roman01la/citrus/issues/35/events","html_url":"https://github.com/roman01la/citrus/issues/35","id":353003346,"node_id":"MDU6SXNzdWUzNTMwMDMzNDY=","number":35,"title":"Behaviour When Mixing Dispatch and Dispatch Sync","user":{"login":"mbutlerw","id":17419288,"node_id":"MDQ6VXNlcjE3NDE5Mjg4","avatar_url":"https://avatars3.githubusercontent.com/u/17419288?v=4","gravatar_id":"","url":"https://api.github.com/users/mbutlerw","html_url":"https://github.com/mbutlerw","followers_url":"https://api.github.com/users/mbutlerw/followers","following_url":"https://api.github.com/users/mbutlerw/following{/other_user}","gists_url":"https://api.github.com/users/mbutlerw/gists{/gist_id}","starred_url":"https://api.github.com/users/mbutlerw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbutlerw/subscriptions","organizations_url":"https://api.github.com/users/mbutlerw/orgs","repos_url":"https://api.github.com/users/mbutlerw/repos","events_url":"https://api.github.com/users/mbutlerw/events{/privacy}","received_events_url":"https://api.github.com/users/mbutlerw/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-08-22T15:20:40Z","updated_at":"2018-08-22T15:20:40Z","closed_at":null,"author_association":"NONE","body":"Hi, I brought this up on the slack, but it got lost due to no history.\r\n\r\nThere is some surprising behaviour when mixing dispatch and dispatch sync.\r\n\r\n```\r\n;; sync inside async gets lost\r\n(defmulti controller (fn [event] event))\r\n\r\n(defmethod controller :one []\r\n  (println \"one\")\r\n  {:state {1 true}\r\n   :effect nil})\r\n\r\n(defmethod controller :two [_ _ state]\r\n  (println \"two:\" state)\r\n  {:state (assoc state 2 true)\r\n   :effect2 nil})\r\n\r\n(defmethod controller :three [_ _ state]\r\n  (println \"three:\" state)\r\n  {:state (assoc state 3 true)\r\n   :effect3 nil})\r\n\r\n(defmethod controller :four [_ _ state]\r\n  (println \"four:\" state)\r\n  {:state (assoc state 4 true)})\r\n\r\n\r\n(defn effect [r _ _]\r\n  (citrus/dispatch-sync! r :controller :two))\r\n\r\n(defn effect2 [r _ _]\r\n  (citrus/dispatch-sync! r :controller :three))\r\n\r\n(defn effect3 [r _ _]\r\n  (citrus/dispatch-sync! r :controller :four))\r\n\r\n\r\n(defonce recon\r\n  (citrus/reconciler {:state (atom {})\r\n                      :controllers {:controller controller}\r\n                      :effect-handlers {:effect effect\r\n                                        :effect2 effect2\r\n                                        :effect3 effect3}}))\r\n\r\n(citrus/dispatch! recon :controller :one)\r\n```\r\n\r\nThe output of this is \r\n\r\n```\r\none\r\ntwo: nil\r\nthree: {2 true}\r\nfour: {2 true, 3 true}\r\n```\r\nand then if you print the reconciler once its all run\r\n\r\n```\r\n#object [citrus.reconciler.Reconciler {:val {:controller {1 true}}}]\r\n```\r\n\r\nThe apparent behaviour is that first the update from the `dispatch!` isn't reflected in the subsequent `dispatch-sync!` method calls. However if you then check the state of the reconciler its only the result of the `dispatch!` that is reflected.\r\n\r\nIf you change `effect` to `dispatch!` as well, like so \r\n\r\n```\r\n(defn effect [r _ _]\r\n  (citrus/dispatch! r :controller :two))\r\n```\r\n\r\nyou get the following output\r\n\r\n```\r\none\r\ntwo: {1 true}\r\nthree: {1 true}\r\nfour: {1 true, 3 true}\r\n#object [citrus.reconciler.Reconciler {:val {:controller {1 true, 2 true}}}]\r\n```\r\n\r\nSo which indicates the \"bug\" is when you switch between `dispatch!` and `dispatch-sync!`\r\n\r\nIf you flip the problem and start from a `dispatch-sync!` and go to `dispatch!` it appears to work as expected.\r\n\r\n```\r\n(citrus/dispatch-sync! recon :controller :one)\r\n\r\n(defn effect [r _ _]\r\n  (citrus/dispatch! r :controller :two))\r\n\r\n(defn effect2 [r _ _]\r\n  (citrus/dispatch! r :controller :three))\r\n\r\n(defn effect3 [r _ _]\r\n  (citrus/dispatch! r :controller :four))\r\n```\r\nOutput:\r\n\r\n```\r\none\r\ntwo: {1 true}\r\nthree: {1 true, 2 true}\r\nfour: {1 true, 2 true, 3 true}\r\n#object [citrus.reconciler.Reconciler {:val {:controller {1 true, 2 true, 3 true, 4 true}}}]\r\n```\r\n\r\nWanted to register this, even if the answer is simply a warning about mixing dispatch and dispatch-sync."}}
{"actor":{"display_login":"mbutlerw"}}