[JAVA-3747] Redesign Codec Resolution Created: 27/May/20 Updated: 30/Mar/22 |
|
| Status: | Backlog |
| Project: | Java Driver |
| Component/s: | Codecs, Scala |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | New Feature | Priority: | Major - P3 |
| Reporter: | Aki ks | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Attachments: |
|
| Description |
| Comments |
| Comment by Ross Lawley [ 10/Jun/20 ] |
|
Thanks again aki-ks.cloud.mongodb.com@m.mader.dev, Some great points. I'm moving this ticket to "open" for future consideration. |
| Comment by Aki ks [ 02/Jun/20 ] |
|
The current scala driver already includes Macros that work for case classes and adt's, but those do only summon one `Codec[A]` for the one requested type "A". Instead of using shapeless we should implement such custom macros. It would generate more optimized Code the when using Shapleless. Back then I've just decided to use Shapeless since I've wanted to get running Code quickly and I've often had troubled with scala macros in the past. So once you've retrieved macro-generated codecs, you must currently register them in the Codec-Registry one by one. For every type that might be contained in the Datastructure to be serialized, one Codec must get explicitly registered. As you've said, at runtime some kind of `Map[Class[A], Codec[A]]` looks those Codes up. But if you've for instance forgot to register a Codec for one type, you will notice this only at runtime when such a type should get serialized for the first time. My main idea is to completely get rid of the usage of CodecRegistry in the Scala driver. Due to limitiations in the Java language it was required there and it has many disadvantages, but with the power of implicits we do no longer need to rely on it for codec-resolution in the Scala-driver. |
| Comment by Ross Lawley [ 02/Jun/20 ] |
|
Hi aki-ks.cloud.mongodb.com@m.mader.dev, Thanks for the ticket. As you may know the Scala driver is a layer written upon the Java driver and internally, the Java driver uses a CodecRegistry for converting type T to its equivalent Bson Type. The registry can be thought as a Map like structure where the key is the class of the type to be encoded and the value is the Codec. So it isn't really reflection based persae but as you rightly pointed out that can cause issues where generics are involved - as the type information is erased the user has to cast to the expected type. To combat this the Scala driver does two things:
That said, I really like what you have done by using shapeless you've used reflection to implicitly handle case classes and other scala types to map into a Codec. Also by wrapping that into a Macro to set the Codec at compile time that would improve the performance by removing the runtime reflection. These are two approaches to the same problem, the Java driver uses a single registry throughout and your approach provides a specialized custom codec for each usecase. The only downside would be to take a hard dependency on shapeless, which can causes issues with users ecosystems with different versions etc. The JVM drivers aim to take the absolute minimum of outside dependencies because of the drivers wide usecases and the interactions with many different systems and stacks. I would love to see an alternative Scala driver implementation written ontop of the Reactive Streams Driver that uses shapeless and your ideas. I think that could be a benefit to Scala users. Ross |