Skip to content

Commit

Permalink
fix(query): allow multiple calls to Release proxy bridge iterator
Browse files Browse the repository at this point in the history
The asyncStatsResultIterator used inside QueryServiceProxyBridge assumed
that Release would only be called once. The godoc for ResultIterator
specifies that it is safe to call Release multiple times. Now, you can
do that without causing Release to block indefinitely.
  • Loading branch information
mark-rushakoff committed Mar 19, 2019
1 parent 1797ec6 commit 4904992
Showing 1 changed file with 15 additions and 11 deletions.
26 changes: 15 additions & 11 deletions query/bridges.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,38 @@ func (b QueryServiceProxyBridge) Query(ctx context.Context, req *Request) (flux.
}

r, w := io.Pipe()
statsChan := make(chan flux.Statistics, 1)
asri := &asyncStatsResultIterator{statsReady: make(chan struct{})}

go func() {
stats, err := b.ProxyQueryService.Query(ctx, w, preq)
_ = w.CloseWithError(err)
statsChan <- stats
asri.stats = stats
close(asri.statsReady)
}()

dec := csv.NewMultiResultDecoder(csv.ResultDecoderConfig{})
ri, err := dec.Decode(r)
return asyncStatsResultIterator{
ResultIterator: ri,
statsChan: statsChan,
}, err
asri.ResultIterator = ri
return asri, err
}

type asyncStatsResultIterator struct {
flux.ResultIterator
statsChan chan flux.Statistics
stats flux.Statistics

// Channel that is closed when stats have been written.
statsReady chan struct{}

// Statistics gathered from calling the proxy query service.
// This field must not be read until statsReady is closed.
stats flux.Statistics
}

func (i asyncStatsResultIterator) Release() {
func (i *asyncStatsResultIterator) Release() {
i.ResultIterator.Release()
i.stats = <-i.statsChan
}

func (i asyncStatsResultIterator) Statistics() flux.Statistics {
func (i *asyncStatsResultIterator) Statistics() flux.Statistics {
<-i.statsReady
return i.stats
}

Expand Down

0 comments on commit 4904992

Please sign in to comment.