001  (ns cmp.resp
002    ^{:author "wactbprot"
003      :doc "Catches responses and dispatchs."}
004    (:require [cheshire.core           :as che]
005              [cmp.config              :as config]
006              [cmp.exchange            :as exch]
007              [cmp.doc                 :as doc]
008              [cmp.lt-mem              :as lt]
009              [cmp.st-mem              :as st]
010              [cmp.st-utils            :as stu]
011              [cmp.utils               :as u]
012              [com.brunobonacci.mulog  :as mu]))
013  
014  
015  
016  (defn retry!
017    [state-key]
018    (let [retry-key (stu/key->retry-key state-key)
019          n         (u/ensure-int (st/key->val retry-key))
020          n-max     (config/max-retry (config/config))]
021      (if (>= n n-max)
022        (do
023          (mu/log ::retry! :error "reached max-retry"  :key state-key)
024          (st/set-val! retry-key 0)
025          {:error "max retry"})
026        (do
027          (mu/log ::retry! :message (str "retry " n "/" n-max) :key state-key)
028          (st/set-val! retry-key (inc n))
029          {:ok "retry"}))))
030  
031          
032  
033  (defn dispatch
034    "Dispatches responds from outer space. Expected responses are:
035  
036    * Result ... data will be stored in long term memory 
037    * ToExchange ... data goes to exchange interface
038    * ids ... renew the active documents 
039    * error ... state will be set to error, processing stops 
040    
041    It's maybe a good idea to save the respons body to a key associated
042    to the state key (done).
043    
044    TODO: detect missing values that should be measured again.
045    Solution: Missing or wrong values are detected at postscripts which
046    leads to `:Retry true`. "
047    [body task state-key]
048    (mu/log ::dispatch :message "try to write response" :key state-key )
049    (st/set-val! (stu/key->response-key state-key) body)
050    (if-let [err (:error body)]
051      (st/set-state! state-key :error err)
052      (let [retry    (:Retry      body)
053            to-exch  (:ToExchange body)
054            results  (:Result     body)
055            ids      (:ids        body)
056            doc-path (:DocPath    task)
057            mp-id    (:MpName     task)]  
058        (if retry
059          (let [res-retry (retry! state-key)]
060            (cond
061              (:error res-retry) (st/set-state! state-key :error)
062              (:ok    res-retry) (st/set-state! state-key :ready)))
063          (let [res-ids   (doc/renew! mp-id ids)
064                res-exch  (exch/to!   mp-id to-exch)
065                res-doc   (doc/store! mp-id results doc-path)]
066            (cond
067              (:error res-exch) (st/set-state! state-key :error "error at exchange")
068              (:error res-doc)  (st/set-state! state-key :error "error at document")
069              (and
070               (:ok res-ids)
071               (:ok res-exch)     
072               (:ok res-doc))  (st/set-state! state-key (if (exch/stop-if task) :executed :ready) "exch and doc ok")
073              :unexpected      (st/set-state! state-key :error "unexpected response")))))))
074  
075  ;;------------------------------
076  ;; check
077  ;;------------------------------
078  (defn check
079    "Checks a response from outer space.  Lookes at the status, parses the
080    body and dispathes."
081    [res task state-key]
082    (if-let [status (:status res)]
083      (if-let [body (che/decode (:body res) true)]
084        (if (< status 400) 
085          (dispatch body task state-key) 
086          (mu/log ::check :error "request for failed" :key  state-key ))            
087        (mu/log ::check :error "body can not be parsed" :key state-key))
088      (mu/log ::check :error "no status in header" :key state-key)))