below are some assertions you could add, if these rules don't work
exactly right then you could trip into that error condition

diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 5a27140ac..64da5072a 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -2354,11 +2354,11 @@ class Session(_SessionClassMethods):
                           % len_)

             # useful assertions:
-            # if not objects:
-            #    assert not self.identity_map._modified
-            # else:
-            #    assert self.identity_map._modified == \
-            #            self.identity_map._modified.difference(objects)
+            if not objects:
+                assert not self.identity_map._modified
+            else:
+                assert self.identity_map._modified == \
+                    self.identity_map._modified.difference(objects)

             self.dispatch.after_flush_postexec(self, flush_context)

diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py
index 70420ca50..132f1e37e 100644
--- a/lib/sqlalchemy/orm/state.py
+++ b/lib/sqlalchemy/orm/state.py
@@ -767,8 +767,13 @@ class InstanceState(interfaces.InspectionAttr):

             state.expired_attributes.difference_update(dict_)

+            if instance_dict and state in instance_dict._modified:
+                assert state.modified
+
             if instance_dict and state.modified:
                 instance_dict._modified.discard(state)
+            elif instance_dict:
+                assert state not in instance_dict._modified

             state.modified = state.expired = False
             state._strong_obj = None





On Mon, Feb 26, 2018 at 3:06 PM, Mike Bayer <mike...@zzzcomputing.com> wrote:
> if you can at least share the stack trace that should tell a lot
>
> On Mon, Feb 26, 2018 at 3:05 PM, Mike Bayer <mike...@zzzcomputing.com> wrote:
>> On Mon, Feb 26, 2018 at 2:54 PM, Cecil Rock <cecil.r...@gmail.com> wrote:
>>> Hi,
>>>
>>> I have a question about some ORM internal state tracking stuff.  If this
>>> isn't the right venue for this type of question my apologies.
>>>
>>> I've run into what looks like a race condition using the ORM during some our
>>> production workloads. I am trying to figure out if our code has a bug or if
>>> we are hitting a bug inside the ORM.  We are occasionally getting a
>>> FlushError with this message "Over 100 subsequent flushes have occurred
>>> within session.commit() - is an after_flush() hook creating new objects?"(
>>> we are not using any event hooks.)
>>>
>>> I've managed to track this down to what looks like the session.identity_map
>>> has an InstanceState in its modified list (i.e. the session is dirty) but
>>> the InstanceState is not in the sessions.identity_map._dict (i.e not in the
>>> session?).  The InstanceState is showing that it is attached to the session.
>>>
>>> e.g. the WeakInstanceDict looks like this for the session...
>>> _dict = {}  # is empty
>>> _modified = ( TheModifiedInstanceState )
>>>
>>>
>>> This is a difficult bug to reproduce, but seems more likely to occur if we
>>> hold the session open longer like so...
>>>
>>> my_model = MyModel.query.filter('...').first()
>>> my_model.attr = 'something'
>>> sleep(1)
>>> session.commit() <-- flush error "occasionally"
>>>
>>>
>>> I was hoping someone could confirm for me that this is "never a valid state"
>>> for the identity map to be in.  (Or if I'm super lucky someone will
>>> recognize this as a known bug or something).
>>
>> try doing a gc.collect() there instead of a sleep since it looks
>> related to the object being garbage collected.
>>
>> but no, that is never a valid state and I cannot imagine how you would
>> get that error without using any flush hooks.  that error was put in
>> after observing very specifically end-user event hooks that would add
>> more things to the dirty state within the scope of a flush.  There is
>> no way that can happen otherwise.
>>
>>
>>
>>
>>>
>>> Thanks for the help,
>>>
>>> Cecil
>>>
>>> --
>>> SQLAlchemy -
>>> The Python SQL Toolkit and Object Relational Mapper
>>>
>>> http://www.sqlalchemy.org/
>>>
>>> To post example code, please provide an MCVE: Minimal, Complete, and
>>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
>>> description.
>>> ---
>>> You received this message because you are subscribed to the Google Groups
>>> "sqlalchemy" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to sqlalchemy+unsubscr...@googlegroups.com.
>>> To post to this group, send email to sqlalchemy@googlegroups.com.
>>> Visit this group at https://groups.google.com/group/sqlalchemy.
>>> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to