This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-01-07
Channels
- # announcements (4)
- # babashka (20)
- # beginners (167)
- # calva (1)
- # cider (18)
- # circleci (10)
- # clara (45)
- # clojure (85)
- # clojure-argentina (1)
- # clojure-europe (3)
- # clojure-finland (3)
- # clojure-greece (2)
- # clojure-italy (9)
- # clojure-nl (30)
- # clojure-spec (32)
- # clojure-survey (39)
- # clojure-uk (72)
- # clojurescript (12)
- # core-async (4)
- # data-science (3)
- # emacs (10)
- # figwheel-main (9)
- # fulcro (44)
- # graalvm (3)
- # jobs (12)
- # jobs-discuss (6)
- # joker (3)
- # juxt (1)
- # leiningen (4)
- # off-topic (23)
- # planck (5)
- # re-frame (4)
- # reitit (2)
- # remote-jobs (1)
- # shadow-cljs (43)
- # spacemacs (8)
- # test-check (19)
- # tools-deps (21)
Hi all, I want to serialize/deserialize the working-memory separately so I started off by using a simple implementation for IWorkingMemorySerializer
that serializes to an atom (as per Clara's docs) and deserializing from the atom by derefing it. That works perfectly fine, in that I am able to run queries and get the same results from both the original and deserialized session. However, if I add the extra step to write to fressian and read fressian to the ser/deserializer of the IWorkingMemorySerializer
, all queries in the deserialized version of the session return with nil: eg. ({:?crn nil})
while the same query on the original is returning ({:?crn {:fact-type :client-representative-notification, :name "Alice", :client "Acme", :level :high}})
. I should note that I am fairly new to clara rules. Has anyone come across something like this before?
@konstantinos562, Do you have a small snippet, it would help me reproduce it locally?
Hi @ethanc do you need the rules as well?
(defrecord WorkingMemoryAtomSerializer [input output]
d/IWorkingMemorySerializer
(serialize-facts [_ facts]
(reset! state (write-fressian facts)))
(deserialize-facts [this]
(-> @state io/input-stream read-fressian)))
with (def state (atom nil))
in the namespace
and the read and write fressian as follows
(defn write-fressian [obj]
(let [baos (ByteArrayOutputStream.)
wr (frz/create-writer baos)]
(frz/write-object wr obj)
(.toByteArray baos)))
(defn read-fressian [b]
(-> b frz/create-reader frz/read-object))
sorry for the long posting all
NB: I have replaced fressian with nippy/freeze and nippy/thaw and it works perfectly fine now. I am not sure what the issue was (most probably I am doing something wrong there)
@konstantinos562 not sure what frz
ns is referring to
sorry it's the requirement: [clojure.data.fressian :as frz]
or they will cause many clj data structures to become Java structures - or not the same as before
you can see Clara defines a more robust set of fressian handlers for clj to clj serialization https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/durability/fressian.clj#L231
however, there really is no compelling reason to not just use nippy
if you have it set up
I wouldn’t have used Fressian to impl Clara’s session serialization if I were to do it again today. it is difficult to work with in what it provides by default and I don’t think it is any better than something like nippy
or perhaps a few others. It is also not documented super well and at the “primitive” level makes some unavoidable Java collections that are awkward to convert from (and also wasting perf time)
for this example, I have not set up any handlers but the facts are fairly simple
[{:fact-type :client-representative :name "Alice" :client "Acme"}
{:fact-type :support-request :client "Acme" :level :high}]
(this is all pluggable and could be implemented with something else on Clara’s side just as well too)
try to Fressian write/read that and see that it returns you the facts in the same structure
@mikerod simply using the fressian write/read does work correctly in REPL
yes, I think I will use the nippy as it seems to be something in the fressian
side that I cannot track at the moment
> simply using the fressian write/read does work correctly in REPL You’ve analyzed waht is returned? is it still a clj vector with 2 clj maps etc?
thank you very much for the prompt responses and help!
@mikerod yes it returns exactly the same facts that are serialized; i.e. a vector of two clj maps
I have some examples in http://www.metasimple.org/2018/02/19/clj-fressian-ext.html
I immediately see that types at least aren’t preserved
(let [r (serde-obj [{:fact-type :client-representative :name "Alice" :client "Acme"}
{:fact-type :support-request :client "Acme" :level :high}])]
(type r))
;;= java.util.Arrays$ArrayList
this isn’t immediately meaning Clara wouldn’t accept it - but it is already on shaky ground
oh I see
@mikerod thank you very much on this!
only issue there being you may not want to deal with the “identity preserving” parts potentially
you can see examples https://github.com/cerner/clara-rules/blob/master/src/test/clojure/clara/test_fressian.clj#L16
that makes sense