experimental refactoring of channel communication#1378
experimental refactoring of channel communication#1378
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.
any better names NotifySatisfiedWatchers -> NotifyEligibleWatchers or anything else?
There was a problem hiding this comment.
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.
"Us" seems redundant in NotifyUsAfter?
There was a problem hiding this comment.
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