-
Notifications
You must be signed in to change notification settings - Fork 683
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
experimental refactoring of channel communication #1378
base: master
Are you sure you want to change the base?
Conversation
this is an attempt to improve the readability of some scorch goroutine communication by hiding some of the channel mechanics inside methods that better describe what they're doing
This is work in progress, I don't love all the nouns and verbs yet. But the idea was to see if I could remove some duplicated code, and replace sections that involved a lot of channel mechanics and replace them with types and methods that described what they were doing. Feedback welcome. |
I should mention one other thing. My ultimate goal is to rewrite the main loops of all of these to be a single select statement (not counting inner selects for non-blocking writes where necessary). The introducer is already there, the merger is close (though this PR actually takes a step back in one area), but the persister is currently two very weirdly arranged select statements (fall though one, then block on the other, in a way that ensures we fall through the first one again). |
Second commit cleans up the merger to now have just a single select. |
Possible bug while reviewing this stuff. There are 4 places where we do the following:
However, in 3 of the 4, we also do this:
But, in one case we do not: bleve/index/scorch/persister.go Lines 222 to 225 in fb361a7
The reason I'm asking is that I'd like to fold this into main select case at the top, so in my new version this would be added. I'm probably going to code it up anyway... |
Third commit attempts to apply the same process to the persister loop. A few more dicey changes in this version, but wanted to get the big picture in place. |
So, I realized I should try to explain the reasoning behind the transformation. In both the merger and the persister, the main select at the top had a "default" exit path. In one obvious case (the first time through) this seems necessary, we're not yet "waiting" for anything. However, in all subsequent cases, we've done some work, and are now actually "waiting" on something specific (persister waiting for introducer to give it something new to process, and merger waiting for persister to give it something new to process). These "waits" happen at the bottom of the loop, and the expectation is that it means we'll quickly fall through the top select again. So, with that in mind, the change I've made is to set up our "first time through" case to look like the other case. Both the persister and merger now take an initial root epoch (read from file for the open case, or 0 is fine for the new case). They do the same "wait" for this epoch, as they will after actually doing work to process an epoch later. By making these two cases work the same, we can fold things into a single select case. If we can agree this is actually correct, we can further refactor out all the long blocks of code for each case into functions. This should eventually create a separation between the logic of "when do to do something" from the "how to actually do something that is needed". |
*e = append(*e, watcher) | ||
} | ||
|
||
func (e *epochWatchers) NotifySatisfiedWatchers(epoch uint64) { |
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.
any better names NotifySatisfiedWatchers -> NotifyEligibleWatchers or anything else?
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, I dislike all the names.
|
||
type watcherChan chan *epochWatcher | ||
|
||
func (w watcherChan) NotifyUsAfter(epoch uint64, closeCh chan struct{}) (*epochWatcher, error) { |
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.
"Us" seems redundant in NotifyUsAfter?
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 added "us", because it felt wrong to me that both sides of this seemed to be something like "notify after epoch". But one side was waiting for something, and the other was telling you that it happened. I was trying to add a word that clarified which side of the fence we were on.
Because when you read the code, that part should be clear, but today it isn't.
Some notes from review with @sreekanth-cb this morning:
|
this is an attempt to improve the readability of
some scorch goroutine communication by hiding
some of the channel mechanics inside methods
that better describe what they're doing