-
Notifications
You must be signed in to change notification settings - Fork 442
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
make lookup functionality pluggable #86
Conversation
numLookupd := len(r.lookupdHTTPAddrs) | ||
r.mtx.RUnlock() | ||
if numLookupd != 0 && atomic.LoadInt32(&r.stopFlag) == 0 { | ||
have_lookup_sources := r.lookupProvider.HasSources() |
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.
--> has_lookup_sources
It's been pointed out that this could leave a lot more work than is warranted for someone who wants to continue using nsqlookupd sources but wants a simple filter on the returned nsqds. I considered making the default lookup provider public, in an attempt to make it re-usable with embedding. But it's also been suggested that the consumer could optionally have a filter attached, instead of all this. Thoughts? |
r.lookupdHTTPAddrs = append(r.lookupdHTTPAddrs, addr) | ||
numLookupd := len(r.lookupdHTTPAddrs) | ||
r.mtx.Unlock() | ||
was_connected := atomic.SwapInt32(&r.connectedFlag, 1) |
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.
STYLE POLICE 👮 this isn't python plo - wasConnected
@ploxiln in light of the fact that |
I think this looks good as is. I think the interface is more idiomatic than the callback approach, but one could argue that's just a preference of implementation. @mreiferson in case it wasn't obvious, this give the ability to mange swimlanes using go-nsq similar to how we do with pynsq. If i were to brainstorm implementation options, another possible approach would be to give control of polling lookupd's to the |
I wasn't suggesting an actual callback, an interface would be fine. I'm saying that simplification might be useful if all you're missing is the ability to filter the set of returned type Discoverer interface {
Filter([]string) []string
} The default implementation would pass through unfiltered. |
That would indeed be sufficient for our use case. |
I've put up the simple filter function alternative. I also considered a version that used
which might be more convenient for the filtering function, and doesn't add any parsing / string forming steps, just defers them to after the filter. Further opinions? |
|
right, I was going to ask where that was if it already existed |
Well TCPAddr contains an IP, not a dns name |
Ahh, bummer. Guess it would need a custom type then, in which case I probably prefer passing around just the string. |
do we think this is as good as we can agree on? until unspoken eventualities transform the lookupd problem space? |
I think the only question is whether or not this should be exposed as an actual interface rather than callback. It would afford us certain opportunities if we wanted to expose other functionality in the future (by type asserting to other function-exposing interfaces). What to name it? |
|
You might see what @mreiferson means if you look way up at his original suggestion, an interface with a Filter() method. The idea is that you could add more methods later (by adding more comprehensive / different interfaces), and type check to see if a particular one has been implemented. It could be used for any sort of behavior tweaking callback I guess. The most annoying choice to make is what to call the consumer method to set the tweaks object - setConsumerTweaks()? do we really want such a thing? I can pretty quickly bang out what that would look like anyway... |
Updated. The idea is we can, later, specify more interfaces that a "ConsumerBehavior" thingie can implement. Is this the kind of thing you had in mind @mreiferson ? |
// DiscoveryFilter interface | ||
// one of the interfaces an argument to setConsumerBehavior() can satisfy | ||
// for filtering the nsqds returned from discovery via nsqlookupd | ||
type DiscoveryFilter interface { |
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.
hmmm, thinking out loud: DiscoveryProxy
, DiscoveryDelegate
, DiscoveryHandler
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.
actually, sorry I get where you're going with this...
Yes, this is what I had in mind, just gonna simmer on the naming for a bit... nice work |
should we get this in? |
Have your thoughts on naming condensed sufficiently? I'll go ahead and squash... |
@@ -180,6 +189,10 @@ func (r *Consumer) SetLogger(l logger, lvl LogLevel) { | |||
r.logLvl = lvl | |||
} | |||
|
|||
func (r *Consumer) SetConsumerBehavior(cb interface{}) { |
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.
The alternative to exposing a method to set this would be to make it a field of the Config
struct.
I don't know if that's better or worse, just wanted to talk it through.
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.
no matter where we end up, I think this should be called BehaviorDelegate
(I think the use of the word Consumer
is redundant here) and I think it needs Delegate
because a) we've used it elsewhere and b) you're not setting the behavior here you're setting the thing that modifies the behavior 😁
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.
If we keep this a method, we could check that the "delegate" fulfills one of the interfaces, or even return a list or count of the interfaces it does match, for debugging purposes. Maybe we don't really want to do that, just an idea.
9d2e856
to
20632a4
Compare
renamed. could still move the setting of it to the Config struct if desired |
Yea, I like that idea (panic if it does not satisfy at least one of the valid interfaces) |
That is one benefit of it being a function rather than a field on |
I pushed up the I think it's less-good than returning, say, a count of matched interfaces, because you might intend to augment two behaviors, but only augment one and not be sure, and also you might want to clear a behavior delegate you set (though I guess that could be racy). |
We've taken the approach that all of the configuration needs to happen up front, before connection, and is otherwise undefined. It's a toss up whether these situations should panic when used incorrectly or just error. I'm still slowly forming stronger opinions around which of these approaches I prefer, but for right now I think it would be consistent with the rest of the package if it panicked (we can decide to change panicking vs erroring later). |
8b286b2
to
6d83da1
Compare
squashed |
I pushed up another tweak. Are we all agreed? Shall I final squash? |
LGTM |
I don't like the tone of your voice plo |
but 👍 |
for modifying nsq consumer behavior at some defined points panic()s if the behavior delegate casts to no known interfaces currently just supports DiscoveryFilter (with a Filter() method), to filter the nsqd addresses resulting from discovery (via nsqlookupd)
b811579
to
72faeb5
Compare
jeez, I have to walk on eggshells around here these days |
❤️ |
Welcome to funemployment |
make lookup functionality pluggable
We'd like to be able to override how a consumer queries from NSQLookupds.
I think this approach would also allow others to switch NSQLookupd for etcd, zookeeper,
etc.
This is still a WIP but I hope you can see where I'm going with this.
Suggestions and Criticism welcome.
cc @oliver-bitly @jehiah @mreiferson