#264:Provide better exception when unable to resolve class while dese…#476
#264:Provide better exception when unable to resolve class while dese…#476EthanEChristian wants to merge 4 commits intooracle-samples:mainfrom
Conversation
…ass while deserializing rulebase
| (read-record rdr nil)) | ||
| ([^Reader rdr add-fn] | ||
| (let [builder (-> (.readObject rdr) resolve deref) | ||
| (let [try-resolve #(if-let [clazz (resolve %)] |
There was a problem hiding this comment.
could be named resolve-or-fail
There was a problem hiding this comment.
That’s used elsewhere I think?
There was a problem hiding this comment.
not in this repo, but it is around ;)
mrrodriguez
left a comment
There was a problem hiding this comment.
I have minor suggestions.
| (read-record rdr nil)) | ||
| ([^Reader rdr add-fn] | ||
| (let [builder (-> (.readObject rdr) resolve deref) | ||
| (let [try-resolve #(if-let [clazz (resolve %)] |
There was a problem hiding this comment.
That’s used elsewhere I think?
Co-authored-by: Mike Rodriguez <mjr4184@gmail.com>
Co-authored-by: Mike Rodriguez <mjr4184@gmail.com>
|
I plan on merging this this weekend to allow for a little additional time for @WilliamParker if he is able to. |
| ([^Reader rdr add-fn] | ||
| (let [builder (-> (.readObject rdr) resolve deref) | ||
| (let [try-resolve #(if-let [clazz (resolve %)] | ||
| clazz |
There was a problem hiding this comment.
I don't think this is a class, but rather a Clojure Var for the record constructor function. From the implementation before this PR:
(defn write-record
"Same as write-with-meta, but with Clojure record support. The type of the record will
be preserved."
[^Writer w tag rec]
(let [m (meta rec)]
(.writeTag w tag 3)
(.writeObject w (record-map-constructor-name rec) true)
(write-map w rec)
(if m
(.writeObject w m)
(.writeNull w))))
Then looking at the current read implementation:
(defn read-record
"Same as read-with-meta, but with Clojure record support. The type of the record will
be preserved."
([^Reader rdr]
(read-record rdr nil))
([^Reader rdr add-fn]
(let [builder (-> (.readObject rdr) resolve deref)
build-map (.readObject rdr)
m (read-meta rdr)]
(cond-> (builder build-map)
m (with-meta m)
add-fn add-fn))))
If the resolved value was a class it wouldn't be possible to invoke it as a Clojure function - note the (builder build-map) call.
Assuming I'm not missing something, this makes testing easier if you're so inclined, though for this sort of error handling I don't think it is critical. You could just use ns-unmap before deserializing.
There was a problem hiding this comment.
This is a good point. So the suggestion (besides testing) is that the resolved symbol isn't a class at all and the message should avoid being worded suggesting that it is. Also, we shouldn't call it clazz, but perhaps just resolved or resolved-var or something like that? It is notable that deref is called on it a step later, so it definition can't be a class.
There was a problem hiding this comment.
todo:
add a test
| (let [try-resolve #(if-let [clazz (resolve %)] | ||
| clazz | ||
| (throw (ex-info (str "Unable to resolve fact type symbol: '" % "'") | ||
| {:fact-type-class %}))) |
There was a problem hiding this comment.
I don't think this is specific to facts? It is being used for all Clojure records from what I can see here (admittedly it has been a while since I read through this): https://github.com/cerner/clara-rules/blob/0.21.2/src/main/clojure/clara/rules/durability/fressian.clj#L386
There was a problem hiding this comment.
I think you are right. It really is a failure to resolve a record builder fn.
EthanEChristian
left a comment
There was a problem hiding this comment.
correct terminology
| (let [builder (-> (.readObject rdr) resolve deref) | ||
| (let [try-resolve #(if-let [resolved (resolve %)] | ||
| resolved | ||
| (throw (ex-info (str "Unable to resolve fact type symbol: '" % "'") |
There was a problem hiding this comment.
I don't think this is necessarily a fact, although if the Fressian handlers are being brought in by an IWorkingMemorySerializer implementation they usually will be - the Clara engine nodes have their own handlers anyway: https://github.com/cerner/clara-rules/blob/0.21.2/src/main/clojure/clara/rules/durability/fressian.clj#L393 So this seems OK either way as "fact type symbol" or "record constructor symbol".
…rializing rulebase
#264