Jul 5, 2020, 7:46:42 PM7/5/20
Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message as abuse
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to GLORP Mailing List
As I did some large ETL into a database via Glorp I started to be
bitten by an "UNIQUE constraint" violation failure.
And even using GUIDs as keys (stored in base36 encoding). So it wasn't
some race condition or similar in the assignment of ids. At first I
thought it was something related with the proxy resolution, so I
changed all my mappings to not use proxies at all, which obviously
made things slowly worse. I couldn't reproduce the situation because
it involved a lot of objects and didn't always fail (although it
failed consistently with the same elements).
I had two class hierarchies that were using filtered resolvers, and
all my mappings are described using the abstract class, but I had the
issue that when read, the manager would store the instance in the
specific cache, but when looked up it used the abstract class. So a
lot of cache failures when the object was there (somewhere).
What I did was to change the cacheForClass: implementation to always
return the "abstract" (rootClass) class of the type resolver.
| resolver cacheClass |
resolver := (self session descriptorFor: aClass) typeResolver.
cacheClass := resolver usesInheritance ifTrue: [ resolver rootClass
] ifFalse: [ aClass ].
^ subCaches at: cacheClass ifAbsentPut: [ self makeCacheFor: cacheClass ]
This comes with caveats, as the whole hierarchy in the resolvers
should use the same primary key in order to resolve properly, and for
other parts in Glorp, the descriptor for the abstract class should
also specify it's primary key mapping.
My "abstract" participant class (with Player, Team and other kinds of
participants as concrete types)
| table |
table := self tableNamed: 'GWPARTICIPANT'.
aDescriptor table: table.
(self typeResolverFor: GwParticipant) register: aDescriptor abstract: true.
(aDescriptor newMapping: DirectMapping) from: #id to: (table fieldNamed: 'id')
So maybe the "cacheForClass:" should be optimized (could simply
delegate the "cacheKeyClass" to the Descriptor itself), but for my
testing purposes I changed this and all my tests passed and wasn't hit
by this behavior anymore.
In the way to reach this, I simplified my database mappings, and
simplified it a lot, having a lighter and faster schema, albeit less
object oriented. I might reintroduce that back, but just for
"analytics" from the SQL side.
Esteban A. Maringolo