Skip to content
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

Merged
merged 1 commit into from
Oct 22, 2014

Conversation

ploxiln
Copy link
Member

@ploxiln ploxiln commented Oct 6, 2014

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

@ploxiln ploxiln self-assigned this Oct 6, 2014
numLookupd := len(r.lookupdHTTPAddrs)
r.mtx.RUnlock()
if numLookupd != 0 && atomic.LoadInt32(&r.stopFlag) == 0 {
have_lookup_sources := r.lookupProvider.HasSources()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--> has_lookup_sources

@ploxiln
Copy link
Member Author

ploxiln commented Oct 6, 2014

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)
Copy link
Member

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

@mreiferson
Copy link
Member

@ploxiln in light of the fact that nsqlookupd is going away (eventually, see nsqio/nsq#379) I think it makes more sense to just expose a callback that would filter the list returned from "discovery" (whatever the current underlying implementation may be).

@jehiah
Copy link
Member

jehiah commented Oct 7, 2014

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 LookupProvider such that it takes over what are now LookupdPollInterval config values. The interface then would essentially expose a channel that pushes updated endpoints that have been discovered. That would support more than just timer based discovery.

@mreiferson
Copy link
Member

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 nsqd.

type Discoverer interface {
   Filter([]string) []string
}

The default implementation would pass through unfiltered.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 7, 2014

That would indeed be sufficient for our use case.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 7, 2014

I've put up the simple filter function alternative. I also considered a version that used

type HostPort struct {
    Host string
    Port int
}

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?

@mreiferson
Copy link
Member

net.TCPAddr is exactly that type, I like the idea of not having to parse the addresses in the callback.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 7, 2014

right, I was going to ask where that was if it already existed

@ploxiln
Copy link
Member Author

ploxiln commented Oct 7, 2014

Well TCPAddr contains an IP, not a dns name

@mreiferson
Copy link
Member

Ahh, bummer.

Guess it would need a custom type then, in which case I probably prefer passing around just the string.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 7, 2014

do we think this is as good as we can agree on? until unspoken eventualities transform the lookupd problem space?

@mreiferson
Copy link
Member

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?

@oliver-exbitly
Copy link

DiscoveryFilter is fine. Alternatively you could name it NSQDAddrFilter.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 9, 2014

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...

@ploxiln
Copy link
Member Author

ploxiln commented Oct 9, 2014

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 {
Copy link
Member

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

Copy link
Member

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...

@mreiferson
Copy link
Member

Yes, this is what I had in mind, just gonna simmer on the naming for a bit... nice work

@mreiferson
Copy link
Member

should we get this in?

@ploxiln
Copy link
Member Author

ploxiln commented Oct 20, 2014

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{}) {
Copy link
Member

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.

Copy link
Member

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 😁

Copy link
Member Author

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.

@ploxiln ploxiln force-pushed the pluggable_lookup_provider_86 branch from 9d2e856 to 20632a4 Compare October 20, 2014 20:45
@ploxiln
Copy link
Member Author

ploxiln commented Oct 20, 2014

renamed. could still move the setting of it to the Config struct if desired

@mreiferson
Copy link
Member

Yea, I like that idea (panic if it does not satisfy at least one of the valid interfaces)

@mreiferson
Copy link
Member

That is one benefit of it being a function rather than a field on Config, so perhaps that settles it.

@ploxiln
Copy link
Member Author

ploxiln commented Oct 21, 2014

I pushed up the panic() addition.

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).

@mreiferson
Copy link
Member

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).

@ploxiln ploxiln force-pushed the pluggable_lookup_provider_86 branch 2 times, most recently from 8b286b2 to 6d83da1 Compare October 21, 2014 17:23
@ploxiln
Copy link
Member Author

ploxiln commented Oct 21, 2014

squashed

@ploxiln
Copy link
Member Author

ploxiln commented Oct 21, 2014

I pushed up another tweak. Are we all agreed? Shall I final squash?

@oliver-exbitly
Copy link

LGTM

@mreiferson
Copy link
Member

I don't like the tone of your voice plo

@mreiferson
Copy link
Member

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)
@ploxiln ploxiln force-pushed the pluggable_lookup_provider_86 branch from b811579 to 72faeb5 Compare October 21, 2014 23:29
@ploxiln
Copy link
Member Author

ploxiln commented Oct 21, 2014

jeez, I have to walk on eggshells around here these days

@mreiferson
Copy link
Member

❤️

@oliver-exbitly
Copy link

Welcome to funemployment

mreiferson added a commit that referenced this pull request Oct 22, 2014
@mreiferson mreiferson merged commit 61012eb into nsqio:master Oct 22, 2014
@ploxiln ploxiln removed their assignment Aug 31, 2015
@ploxiln ploxiln deleted the pluggable_lookup_provider_86 branch October 17, 2021 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants