Caches for two separate Classes are identical????

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Caches for two separate Classes are identical????

jtuchel
Just to follow up on my problem with Duplicate Keys.

It turns out I had a race condition. The code that produced objects and commit a unit of work was run in a background process. This lead to problems in cache lookup.
I am not yet in a position to fully explain what was going on, but since teh commit was moved bck to the main thread, the DuplicatePrimaryKey exception did not occur any more. The piece of code that had these random errors is usually used in the first day of the month in production and we've had our change in production for beginning of September and October now, and it has been used frequently enough now that we are confident to say the problem is solved (with a little bit of finger-crossing remaining, since we never had the chance to reproduce the problem in the development environment).


Joachim




Am Dienstag, 3. September 2019 13:52:56 UTC+2 schrieb Esteban Maringolo:
Hi Joachim,

I haven't pursued this any further, I've been busy with other stuff
since then and have not touched that project to the point I forgot the
state in which I left it.

I might get back to it this weekend/next week. And I'd happily share
what I find with this list.

Regards,

Esteban A. Maringolo

On Mon, Sep 2, 2019 at 7:11 AM jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="GXKdZ2i2AAAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:

>
> Esteban,
>
> did you make any progress on this front?
>
> I would like to find out if your issue and mine are the same problem. At least it sounds like it. I would love to take a look at your test code and to isolate my problem and make it reproducible as well (I failed so far, it only happens on a headless production machine).
>
> I'd love to help make the process of working on Glorp issues (and new Glorp features)  smoother, and I guess we started a few good discussion threads at ESUG last week...
>
> Joachim
>
>
>
>
>
> Am Dienstag, 30. Juli 2019 16:44:44 UTC+2 schrieb Esteban Maringolo:
>>
>> I have a reproducible way of doing this, as part of the "Glorp" Tests
>> of my application.
>>
>> I didn't find time to put myself to fix this, but once I do (if I can)
>> I'll add at least a test to the Glorp test suite.
>>
>> But this in Pharo, I don't know how to contribute upstream, because as
>> far as I understand, the canonical version of Glorp comes from
>> VisualWorks.
>>
>> Regards,
>>
>> Esteban A. Maringolo
>>
>> On Tue, Jul 30, 2019 at 2:16 AM jtuchel <[hidden email]> wrote:
>> >
>> > Esteban,
>> >
>> >
>> > did you find a way to reproduce this error? In our Application, this happens in production from time to time, in an operation that is used (successfully) a dozen to hundreds of times a day, but we never found a way to reliably reproduce it. This makes bug hunting "nice".
>> >
>> > I'd like to see if we have the same bug and if your fix works, but for this as well as to fix it differently (if necassary) we need a reliable way of producing the error...
>> >
>> > Joachim
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> > Am Montag, 29. Juli 2019 21:05:52 UTC+2 schrieb Esteban Maringolo:
>> >>
>> >> I'm not getting duplicate PK errors, but maybe because I'm using
>> >> SQLite for this and the sequences (PK's with AUTOINCREMENT setting)
>> >> work different than with PostgreSQL or MSSQL. I'll move eventually to
>> >> PostgreSQL, but SQLite is so conveniente to create and discard whole
>> >> databases :)
>> >>
>> >> So I cannot tell you if this is the same thing, but I can tell
>> >> something for sure is that the Cache won't hit any instance of a class
>> >> with a Descriptor using a FilteredTypeResolver, becase of the above
>> >> mentioned issue with primaryKeyFromDictionary: (which I'll fix
>> >> somehow).
>> >>
>> >> My basic model is as follows:
>> >>
>> >> Tournament (1:n) Participant
>> >> Tournament (1:n) Scorecard
>> >> Scorecard (1:1) Participant
>> >>
>> >> Participant can be Player or Team, but all relations and class models
>> >> are defined as Participant.
>> >>
>> >> When I read the participants from a Tournament, they're properly added
>> >> to the session's Cache for Participant (and only Participant as per my
>> >> latest change).
>> >> But when I read the Scorecard, it tries to load the reference to a
>> >> Participant, but because primaryKeyFromDictionary: is written in a way
>> >> that doesn't considers FilteredTypeResolvers (that uses IN() for the
>> >> list of types), then it always instantiates a new Player.
>> >>
>> >> So when I take a player from aTournament and try to look for its
>> >> scorecards (by doing something like: `aTournament scorecards select:
>> >> [:each | each player = aPlayer]`) it returns an empty collection,
>> >> because altough the player of the scorecard and the player of the
>> >> argument (aPlayer) represent the same object in the database, they're
>> >> not the same object in the session (or the image at all).
>> >>
>> >> I'll try to find a way to fix it, but need another Saturday to "waste"
>> >> on these things :D
>> >>
>> >> Regards!
>> >>
>> >>
>> >>
>> >> Esteban A. Maringolo
>> >>
>> >>
>> >> On Mon, Jul 29, 2019 at 11:17 AM jtuchel <[hidden email]> wrote:
>> >> >
>> >> > Esteban,
>> >> >
>> >> > I think I am seeing the same bug from time to time - but not on every read or write exception.
>> >> >
>> >> > Just to make sure it is the same problem: I keep getting "ominous" DuplicatePrimaryKeyException" errors in #isNew: . The classes I get these for are subclasses of a nabstract superclass, all living in the same table, so I am using a FilteredTypeResolver as well.
>> >> > They share a Sequence, so this is not a duplicate key, but rather a Cach Lookup Problem. I am very sure it is not a classical DuplicateKey-Exception because it occurs before any SQL statement is sent to the Database. This all happens somewhere in the registerTranscitiveClosure cascade from a persistent object.
>> >> >
>> >> > Here's the relevant part of the walkback:
>> >> >
>> >> > DuplicatePrimaryKeyException(GlorpError)>>#signal
>> >> >   receiver = Signal on Exception: (ExDuplicatePrimaryKeyException) An exception has occurred
>> >> > Cache>>#includesKey:as:
>> >> >   receiver = a Cache
>> >> >   arg1 = 7109
>> >> >   arg2 = an ElsterUStVA
>> >> >   temp1 = an ElsterUStVA
>> >> >   temp2 = an ElsterUStVA
>> >> > CacheManager>>#containsObject:key:
>> >> >   receiver = a CacheManager
>> >> >   arg1 = an ElsterUStVA
>> >> >   arg2 = 7109
>> >> >   temp1 = a Cache
>> >> > GlorpSession>>#cacheContainsObject:key:
>> >> >   receiver = a GlorpSession
>> >> >   arg1 = an ElsterUStVA
>> >> >   arg2 = 7109
>> >> > [] in GlorpSession>>#isNew:
>> >> >   receiver = a GlorpSession
>> >> >   arg1 = an ElsterUStVA
>> >> >   temp1 = 7109
>> >> >   temp2 = a Descriptor(ElsterUStVA)
>> >> >
>> >> >
>> >> >
>> >> > Does that look familiar to you, Esteban?
>> >> >
>> >> >
>> >> > Joachim
>> >> >
>> >> >
>> >> > --
>> >> > You received this message because you are subscribed to the Google Groups "glorp-group" group.
>> >> > To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
>> >> > To view this discussion on the web visit <a href="https://groups.google.com/d/msgid/glorp-group/234fc6b2-604e-4cd8-adb2-3230f3b4d279%40googlegroups.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/234fc6b2-604e-4cd8-adb2-3230f3b4d279%40googlegroups.com&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/234fc6b2-604e-4cd8-adb2-3230f3b4d279%40googlegroups.com&#39;;return true;">https://groups.google.com/d/msgid/glorp-group/234fc6b2-604e-4cd8-adb2-3230f3b4d279%40googlegroups.com.
>> >
>> > --
>> > You received this message because you are subscribed to the Google Groups "glorp-group" group.
>> > To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
>> > To view this discussion on the web visit <a href="https://groups.google.com/d/msgid/glorp-group/01905fc8-54df-4f65-9d40-1c2b6f8d4fbb%40googlegroups.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/01905fc8-54df-4f65-9d40-1c2b6f8d4fbb%40googlegroups.com&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/01905fc8-54df-4f65-9d40-1c2b6f8d4fbb%40googlegroups.com&#39;;return true;">https://groups.google.com/d/msgid/glorp-group/01905fc8-54df-4f65-9d40-1c2b6f8d4fbb%40googlegroups.com.
>
> --
> You received this message because you are subscribed to the Google Groups "glorp-group" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="GXKdZ2i2AAAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@googlegroups.com.
> To view this discussion on the web visit <a href="https://groups.google.com/d/msgid/glorp-group/11a98abb-cffd-45ea-bc4d-673fbcc78ad4%40googlegroups.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/11a98abb-cffd-45ea-bc4d-673fbcc78ad4%40googlegroups.com&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/msgid/glorp-group/11a98abb-cffd-45ea-bc4d-673fbcc78ad4%40googlegroups.com&#39;;return true;">https://groups.google.com/d/msgid/glorp-group/11a98abb-cffd-45ea-bc4d-673fbcc78ad4%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/813cdc4d-ddfc-4eb2-aebf-1d37ba2747e4%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Caches for two separate Classes are identical????

Annick-2
In reply to this post by jtuchel
Hi ,

I have exactly the same problem with duplicate keys when registering objects.
Annick

Le mardi 10 octobre 2017 15:51:33 UTC+2, jtuchel a écrit :
I am currently having deep trouble with DuplicatePrimaryKeyExceptions in read operations ... ???

The problem is that the Session's Cache contains two subcaches for separate classes that are the same object.

Meaning:

(sess cacheFor: ClassA) == (sess cacheFor: ClassB) evaluates to true.

The DuplicateKey exception happens in a check for isNew: during registration of a TransitiveClosure. It happens because in that Cache there are two instances of classes ClassA and ClassB that have the same primary key. That is why


Cache>>#includesKey: key as: anObject
    "Return true if we include the object, and it matches the given object. If we include a different object with the same key, raise an exception. Don't listen to any expiry policy"

    | item value |

    item := self basicAt: key ifAbsent: [^false].
    value := policy contentsOf: item.
    value == anObject ifFalse: [(DuplicatePrimaryKeyException new: anObject existing: value) signal].
    ^true


fails with a DuplicateKeyException. instanceA is an instance of ClassA and has id=1541 and instanceB us an instance of ClassB and also has id=1541. Glorp assumes thata subcache only contains instances of one class, and that usually is true.
Inpscting the Cache and its subcaches clearly shows that the subcache contains objects from both ClassA and ClassB.

What could I have done wrong? How could I have two subcaches in a Session's Cache that both are the identical object???? I am not messing with Caches in my application code. I know I am not clever enough to change anything "down there"... ;-)


I tried a fresh image and loaded my code into it and the problem still persists.

Any hints? Anybody ever seen this? Where to look?


Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/d02081f8-e4cc-4025-9df3-d0f71f31af10%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Caches for two separate Classes are identical????

jtuchel
Annick,

in my case, this was a race condition. I don't have all the details any more, but I remember that either I had modified an object in a background process and committed in the root process, or even the commit was in a forked process.

Can you check?

Joachim




Am Donnerstag, 4. Juni 2020 13:43:20 UTC+2 schrieb Annick:
Hi ,

I have exactly the same problem with duplicate keys when registering objects.
Annick

Le mardi 10 octobre 2017 15:51:33 UTC+2, jtuchel a écrit :
I am currently having deep trouble with DuplicatePrimaryKeyExceptions in read operations ... ???

The problem is that the Session's Cache contains two subcaches for separate classes that are the same object.

Meaning:

(sess cacheFor: ClassA) == (sess cacheFor: ClassB) evaluates to true.

The DuplicateKey exception happens in a check for isNew: during registration of a TransitiveClosure. It happens because in that Cache there are two instances of classes ClassA and ClassB that have the same primary key. That is why


Cache>>#includesKey: key as: anObject
    "Return true if we include the object, and it matches the given object. If we include a different object with the same key, raise an exception. Don't listen to any expiry policy"

    | item value |

    item := self basicAt: key ifAbsent: [^false].
    value := policy contentsOf: item.
    value == anObject ifFalse: [(DuplicatePrimaryKeyException new: anObject existing: value) signal].
    ^true


fails with a DuplicateKeyException. instanceA is an instance of ClassA and has id=1541 and instanceB us an instance of ClassB and also has id=1541. Glorp assumes thata subcache only contains instances of one class, and that usually is true.
Inpscting the Cache and its subcaches clearly shows that the subcache contains objects from both ClassA and ClassB.

What could I have done wrong? How could I have two subcaches in a Session's Cache that both are the identical object???? I am not messing with Caches in my application code. I know I am not clever enough to change anything "down there"... ;-)


I tried a fresh image and loaded my code into it and the problem still persists.

Any hints? Anybody ever seen this? Where to look?


Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/73c31418-e1b7-47cc-9d39-9c0e4763985a%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Caches for two separate Classes are identical????

Maarten Mostert
In reply to this post by Annick-2
To my experience this always happens when the object where you compare with is a copy of the original query.

The only way to avoid is to make sure they have the same pointer.

Even parsing the object as an argument is not enough, you must use valueHolders or collections holding the original value to make sure not to create DuplicatePrimaryKeyExceptions.


Maarten


Le 4 juin 2020 à 13:43, Annick <[hidden email]> a écrit :

Hi ,

I have exactly the same problem with duplicate keys when registering objects.
Annick

Le mardi 10 octobre 2017 15:51:33 UTC+2, jtuchel a écrit :
I am currently having deep trouble with DuplicatePrimaryKeyExceptions in read operations ... ??? 

The problem is that the Session's Cache contains two subcaches for separate classes that are the same object.

Meaning:

(sess cacheFor: ClassA) == (sess cacheFor: ClassB) evaluates to true.

The DuplicateKey exception happens in a check for isNew: during registration of a TransitiveClosure. It happens because in that Cache there are two instances of classes ClassA and ClassB that have the same primary key. That is why 


Cache>>#includesKey: key as: anObject
    "Return true if we include the object, and it matches the given object. If we include a different object with the same key, raise an exception. Don't listen to any expiry policy"

    | item value |

    item := self basicAt: key ifAbsent: [^false].
    value := policy contentsOf: item.
    value == anObject ifFalse: [(DuplicatePrimaryKeyException new: anObject existing: value) signal].
    ^true


fails with a DuplicateKeyException. instanceA is an instance of ClassA and has id=1541 and instanceB us an instance of ClassB and also has id=1541. Glorp assumes thata subcache only contains instances of one class, and that usually is true.
Inpscting the Cache and its subcaches clearly shows that the subcache contains objects from both ClassA and ClassB.

What could I have done wrong? How could I have two subcaches in a Session's Cache that both are the identical object???? I am not messing with Caches in my application code. I know I am not clever enough to change anything "down there"... ;-)


I tried a fresh image and loaded my code into it and the problem still persists.

Any hints? Anybody ever seen this? Where to look?


Joachim


-- 
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/d02081f8-e4cc-4025-9df3-d0f71f31af10%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/F86A5FC7-D30C-4D87-BF50-7D765779B1F1%40stakepoint.com.
Reply | Threaded
Open this post in threaded view
|

Re: Caches for two separate Classes are identical????

Annick-2
In reply to this post by jtuchel

Thank you Maarten. Actually fetching the objects each time seems to solve the problem.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/2333bd62-80fa-44a5-91a0-77d978a8aa79o%40googlegroups.com.
12