Skip to content

Use a signal handler instead of patching save.#130

Merged
treyhunner merged 1 commit intojazzband:masterfrom
schinckel:master
May 13, 2014
Merged

Use a signal handler instead of patching save.#130
treyhunner merged 1 commit intojazzband:masterfrom
schinckel:master

Conversation

@schinckel
Copy link
Copy Markdown
Contributor

References #83.

Instead of patching the save method of a tracked model class, we can use
a signal handler on post_save, which means we can still pickle our model
class.

Note we can't just listen for the signal from the class we have, but
instead listen for all post_save signals. This means we actually install
a new signal handler for each tracked model class, which fires on all
model save occurrences (and returns immediately if this handler doesn't care).

We probably could improve this to have a registry of tracked models, or
something, that allows us to just install one signal handler, and filter
according to membership.

References jazzband#83.

Instead of patching the save method of a tracked model class, we can use
a signal handler on post_save, which means we can still pickle our model
class.

Note we can't just listen for the signal from the class we have, but
instead listen for all post_save signals. This means we actually install
a new signal handler for each tracked model class, which fires on all
model save occurrences (and returns immediately if this handler doesn't care).

We probably could improve this to have a registry of tracked models, or
something, that allows us to just install one signal handler, and filter
according to membership.
@carljm
Copy link
Copy Markdown
Collaborator

carljm commented May 12, 2014

I'm fine with this approach. I'll leave it up to @treyhunner as author of FieldTracker to merge if it looks ok to him, too. Thanks for the PR!

@treyhunner
Copy link
Copy Markdown
Member

Thanks for working on this @schinckel!

My only concern with this is the possibility of inconsistent results for signal handlers registered before our post_save handler. As @carljm noted in our original discussion about this feature, registering a signal handler before ours seems unlikely since ours would be registered on model creation.

If we do find a failing test it could be useful for documenting that behavior and noting it in the docs.

Thoughts on testing for incorrect behavior in very early post_save handlers? Does that seem excessive/uncessary?

I actually don't see any existing tests for has_changed/previous/changed behavior in pre_save and post_save signals. It looks like I neglected those when I initially wrote the tests.

@schinckel
Copy link
Copy Markdown
Contributor Author

Good point. The only way a signal handler could fire before is if it listened for sender=None, like we do.

Writing a test that shows this is possible: the signal handler just needs to be registered before this model is declared (since the declaration of the model will register the signal).

Alternatively, someone else registering a signal handler in the same way we do (contribute_to_class) could beat us.

Having said all of that, it would depend upon what that signal handler is doing. Most signal handlers may not interfere with what the FieldTracker is doing.

@carljm
Copy link
Copy Markdown
Collaborator

carljm commented May 13, 2014

I had a vague memory that this had already been discussed and there was a reason we didn't use a signal, but I didn't go looking for it; thanks @treyhunner.

I think the main concern is not so much other signal handlers interfering with FieldTracker, as other signal handlers expecting to be able to use the information FieldTracker provides, and being surprised when it is not updated yet.

That said, it seems unlikely that such a handler would be registered before creation of the model class. So I could see accepting this limitation and documenting it.

It does mean that we'd be dependent on the signal-handler-ordering behavior of Django -- is that behavior documented/guaranteed? If not that would be a negative for this approach.

@treyhunner
Copy link
Copy Markdown
Member

It does mean that we'd be dependent on the signal-handler-ordering behavior of Django -- is that behavior documented/guaranteed? If not that would be a negative for this approach.

As far as I can tell that behavior is not documented. I doubt that functionality will ever change though.

After thinking this over more I think this is rare enough that we can just document the behavior.

Here's my proposal for accepting this solution:

  1. Note in the FieldTracker documentation that signal handlers relying on FieldTracker methods should only be registered after model creation (e.g. don't use contribute_to_class)
  2. Hope that the undocumented signal fire order remains unchanged and change the implementation if that implementation detail ever changes.

If that plan sounds reasonable I can merge this and update the documentation.

@carljm
Copy link
Copy Markdown
Collaborator

carljm commented May 13, 2014

That sounds fine to me.

@carljm
Copy link
Copy Markdown
Collaborator

carljm commented Aug 1, 2014

Apologies @schinckel for having to revert your work, and for not catching the issue before merge. Appreciate the pull request.

@schinckel
Copy link
Copy Markdown
Contributor Author

Ah, no worries. I’ll just have to look into a solution that works for everything.

@carljm
Copy link
Copy Markdown
Collaborator

carljm commented Aug 1, 2014

I was hoping you'd say that ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants