    (fn[v]
      (cond
        (isa? (type v) clojure.lang.Atom) (recur (deref v))
+       (isa? (type v) clojure.core.async.impl.channels.ManyToManyChannel) :chan
        (coll? v) (valuefy v)
        (not (future? v)) v
        (future-done? v) (deref v)

          (srv/send-msg ws {:op :stop :payload {}} :noenvelope true))))))


(defn msg-handler [msg]
  (let [{:keys [ws data]} msg
        {:keys [op data]} data
        {:keys [user cmd phase modifier compfile eid action]} data
        eid (if (str/ends-with? eid "/") (austr/butlast 1 eid) eid)
        eid (if (str/starts-with? eid "/") (austr/drop 1 eid) eid)
        params {:user user, :cmd op, :modifier modifier
                :phase phase, :action action :eid eid :ws ws}]
    (infof "MSG-HANDLER: MSG %s" (msg :data))
    (try
      (case op

                                         (with-out-str (pprint status)))
                                        (format
                                         "Finished:\n%s\nFinal result:\n%s"
                                         (with-out-str
                                           (pprint (status :DONE [])))
                                         (with-out-str
                                           (pprint res))))]
                             (with-out-str
                               (print (format "%s : %s started @ %s\n%s"
                                              eid action timestamp rstg))))
                          result)))]
      (send-end-msg ws {:op :status :payload retmsg}))))


(defn user-msg-body [ws user eid action params]
  (let [action (name action)
        vmsg (va/validate-exp eid action)]
    (if (not-empty vmsg)
      (send-end-msg ws {:op :validate :payload vmsg})
      (let [{:keys [cmd eid template]} params
            dt (date-time-stg)
            resmap (actions/action cmd eid params get-toolinfo template)
            resfut (resmap :fut)
            jobdb-info (or (get-jdb [user eid action]) [])]
        (aerial.utils.misc/sleep 250)
        (swap! dbg (fn[M] (assoc M eid resmap)))
        (infof "%s : %s" cmd (prn-str resfut))
        (update-jdb [user eid action]
                    (conj jobdb-info
                          {:request {:timestamp dt
                                     :params (dissoc params :ws)}
                           :status (resmap :status)
                           :result resfut}))
        (if (and (future-done? resfut) (map? @resfut) (@resfut :error))
          (let [cause (->> (or (@resfut :msg) (prn-str (@resfut :error)))
                           (str "Job Launch : "))]
            (srv/send-msg ws {:op :error :payload cause}))
          (srv/send-msg ws {:op :launch :payload "Successful"}))
        (srv/send-msg ws {:op :stop :payload {}} :noenvelope true)))))


(defmethod user-msg :aggregate [msg]
  (let [params (msg :params)
        {:keys [ws user eid compfile]} params]
    (infof "AGGREGATE: %s" params)
    (user-msg-body ws user eid (params :cmd) params)
    #_(send-end-msg ws {:op :status :payload "Aggregating"})))

(defmethod user-msg :xcompare [msg]
  (let [params (msg :params)
        {:keys [ws user eid compfile]} params]
    (infof "XCOMPARE: %s" params)
    (user-msg-body ws user eid (params :cmd) params)
    #_(send-end-msg ws {:op :status :payload "Xcomparing"})))

(defmethod user-msg :compare [msg]
  (let [params (msg :params)
        {:keys [ws user eid compfile]} params]
    (infof "COMPARE: %s" params)
    (user-msg-body ws user eid (params :cmd) params)
    #_(send-end-msg ws {:op :status :payload "Comparing"})))


(defmethod user-msg :run [msg]
