-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Callbacks proxy #35
Callbacks proxy #35
Conversation
Actually, forgot to define which methods to wrap, else we're ending up in an infinite loop... nothing to see here 🙈 |
Yep, now it's looking good 🙂 |
Yeah, this is exactly the path I was thinking 👍 |
Great! I'll flesh this out more in the coming days. |
@dhh most of the functionality should now be "done", I'll add more tests and documentation, though there's one remaining question: what's the preferred signature of the callbacks? Right now it's being called with the |
@dhh I've been doing my best to follow along with the saga of this feature, and I'm super excited to start using this implementation. However, it is currently constrained to the AR model methods. Going back to re-read what you said here, I suspect that my initial interpretation of your words was incorrect. I thought you were talking about the Redis connection instance, not an AR model instance. So suddenly I realize that you appear to be saying that "after callbacks on a simple type are only useful for jobs" and that isn't a strong use case. Is that accurate? If so, I want to urgently implore you to reconsider: calling a job after a simple value type is updated is my number one hope and ambition for this feature! I am a heavy user of simple value types and the use cases for callbacks on Now that we're thinking in terms of reactive UIs, being able to make things happen when data is updated isn't an edge case... it's everything. I checked in with Julian to discuss and he's really ready for this feature to be done. After several re-writes, I don't blame him. I am happy to pick up the baton and run with it - whether that means attempting to contribute to this PR or opening a next one to handle simple types - but clarification from you before I invest would really be appreciated. |
I think this is pretty much done TBH. I will add more tests and docs today. Note that if I'm not mistaken you can use the proxy with a "normal" kredis type if you just omit the record and ensure to supply a callable (Proc) Maybe one could add a convenience factory function?
|
ccfe299
to
d74c12e
Compare
Done! Note that I've changed the signature of the callback to |
Just to follow-up on my last comment, I believe that what I'm looking for is not a callback but a kind of observer - and it's way, way out of scope for Kredis. While the spirit of my desire is intact, I don't think what I was describing belongs in this library and I hope Julian's work can be merged without me muddying the water further. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're getting close. This is great!
lib/kredis/attributes.rb
Outdated
Kredis.send(type, kredis_key_evaluated(key) || kredis_key_for_attribute(name), **options), | ||
self, | ||
callback) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think assigning the proxy to an explaining variable could help with the multi-line nature here.
README.md
Outdated
kredis_list :names, after_change: ->(p) { } | ||
kredis_unique_list :skills, limit: 2, after_change: :skillset_changed | ||
|
||
def skillset_changed(p) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think the instance method callback should probably take a parameter, yeah? Like they don't in Active Record/Model. Only the procs do that.
lib/kredis/types/counter.rb
Outdated
@@ -3,6 +3,10 @@ class Kredis::Types::Counter < Kredis::Types::Proxying | |||
|
|||
attr_accessor :expires_in | |||
|
|||
def callback_operations | |||
%i[increment decrement reset].freeze | |||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like a configuration-level method that shouldn't be exposed directly through the API. What about using a constant instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then you also don't have a to call freeze. And for style, space after opening and before closing 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm too used to standard
😅
Done! (I think) |
Hey, sorry for the long wait on this from me and thanks for all the work on this. My thinking on the implementation here was different enough that I've pushed an alternate take: https://github.com/rails/kredis/compare/after-change-invocations I find the callbacks proxy somewhat overwrought for this, and I'd rather we also support the I'd also like to add some automated checks, so we can catch the case where a new operation was added but the From looking into this, I also found out that both these implementations are incompatible with |
Hm that's somewhat similar to one of my earlier takes 🤔 |
You could certainly go in both directions on this, and the end-user API remains the same, but I like where @julianrubisch has ended up treating the after_change callback structure as essentially an aspect. Cross-cutting feature that the individual types don't need to be concerned about. So given the work @julianrubisch has put into this over several weeks, and the fact that the implementations achieve the same goal, I'd rather we stick with that, as long as the concern around multi can be addressed. |
So what's the contingency plan for this? Document it? Wrap it in a mutex? Not sure how to address it... And re cross cutting concerns, as noted above one could probably conceive convenience functions to address this, e.g.
Not 100% sure how the implementation would look but I think it could be done. (The proxy essentially doesn't care where it sends actions to) |
I think we're fine to note the gotcha / investigate a solution in another PR for now 👍 |
Think we have an issue with the CI. Tests are passing locally. So merging. |
Third iteration:
This time, the API is confined to the ActiveRecord
attributes
class methods.When calling a Kredis type in a model class like so:
proc or method type callbacks are executed, and the method instance passed to them.
One variant would be to also pass the Kredis attribute (the set, list, etc.) to the callback as a second argument to save some characters when accessing it in the callback.
@dhh I would appreciate quick nod if this is what you had in mind, thanks! I will then wrap it up with more tests and docs.