I'm not sure this is the right thing to do but it allows me to bring it up.
;; First I'll make some data and a schema.
(def data-0 {:intro-text ["This is" "my intro text"]})
(def intro-text-schema (l/array-schema l/string-schema))
(l/def-record-schema proposal-schema-0
[:intro-text intro-text-schema])
(def bytes-0 (l/serialize proposal-schema-0 data-0))
(l/deserialize proposal-schema-0 proposal-schema-0 bytes-0)
;; => {:intro-text ["This is" "my intro text"]}
;; So far so good.
;; Now I'll make some new data and a new version of my
;; schema that has a different name.
(def data-1 {:intro-text {:lines ["This is" "my first rich text"]
:is-bold true}})
(l/def-record-schema intro-text-rich-schema
[:lines (l/array-schema l/string-schema)]
[:is-bold l/boolean-schema])
;; Note that the schema name here is foo not proposal.
(l/def-record-schema foo-schema
[:intro-text intro-text-rich-schema])
(def bytes-foo (l/serialize foo-schema data-1))
(l/deserialize foo-schema foo-schema bytes-1)
;; => {:intro-text {:lines ["This is" "my first rich text"], :is-bold true}}
;; No surprise there.
;; Now I'll see if my schema change is backwards compatible. I happen to know
;; already that it's not. The reader and write schema are incompatible. (I also
;; learned recently that the schema names need to match (after reading the
;; Avro spec I think it's more accurate to say that the record names need to
;; match) but I'm replicating that learning experience here to demonstrate
;; something.) Let's see what happens.
;; Can new code read old data?
(l/deserialize foo-schema proposal-schema-0 bytes-0)
;; This errors with the message
;; "Serialized data in byte array does not match given writer schema."
;; What? Of course the byte array matches the writer schema, I just defined it
;; a few lines above. Something fishy! After some digging I see there are some
;; "original exceptions" underneath.
(-> *e ex-data :orig-e ex-data :orig-e ex-message)
;; => "Schema names do not match. (:user/proposal != :user/foo)"
;; Now that makes sense. Let's make the schema names match. Anything after
;; "-schema" is stripped off so I can achive this with the following.
(l/def-record-schema proposal-schema-1
[:intro-text intro-text-rich-schema])
(l/deserialize proposal-schema-1 proposal-schema-0 bytes-0)
;; => "Serialized data in byte array does not match given writer schema."
;; What? Of course the byte array matches the writer schema, I just defined it
;; a few lines above. Something fishy! Let's check out those original exceptions
;; again.
(-> *e ex-data :orig-e ex-data :orig-e ex-message)
;; => "No schemas in reader union schema match writer."
;; Now that's the error I expected at the beginning.
I go digging into this and I discover that this try block is, as I understand it, relabeling any exception with this misleading message. The first :orig-e I'm passing by above is thrown here and is from what I can tell accurate but not fully descriptive. The descriptive errors I wanted are defined here (mismatched names) and here (reader union lacks match).
My "fix" here is to remove the outer most wrapping throw that was so misleading to me. Am I correct that it's misleading or do I misunderstand something? Is this pattern of wrapping throws with throws and :orig-e's that get more specific as you drill down a common pattern?
I'm not sure this is the right thing to do but it allows me to bring it up.
I go digging into this and I discover that this try block is, as I understand it, relabeling any exception with this misleading message. The first
:orig-e
I'm passing by above is thrown here and is from what I can tell accurate but not fully descriptive. The descriptive errors I wanted are defined here (mismatched names) and here (reader union lacks match).My "fix" here is to remove the outer most wrapping throw that was so misleading to me. Am I correct that it's misleading or do I misunderstand something? Is this pattern of wrapping throws with throws and
:orig-e
's that get more specific as you drill down a common pattern?