From 3848dc04f59c35f1c04827dd9b136faa64707319 Mon Sep 17 00:00:00 2001 From: gammazero Date: Wed, 31 May 2023 10:16:30 -0700 Subject: [PATCH 1/2] FindAsync returns error --- find/client/dhash_client.go | 40 ++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/find/client/dhash_client.go b/find/client/dhash_client.go index af69d3d..ef98f75 100644 --- a/find/client/dhash_client.go +++ b/find/client/dhash_client.go @@ -71,9 +71,11 @@ func NewDHashClient(dhstoreURL, stiURL string, options ...Option) (*DHashClient, // Find launches FindAsync in a separate go routine and assembles the result into FindResponse as if it was a synchronous invocation. func (c *DHashClient) Find(ctx context.Context, mh multihash.Multihash) (*model.FindResponse, error) { resChan := make(chan model.ProviderResult) - errChan := make(chan error, 2) + errChan := make(chan error, 1) - go c.FindAsync(ctx, mh, resChan, errChan) + go func() { + errChan <- c.FindAsync(ctx, mh, resChan) + }() mhr := model.MultihashResult{ Multihash: mh, @@ -90,58 +92,49 @@ func (c *DHashClient) Find(ctx context.Context, mh multihash.Multihash) (*model. }, nil } -// FindAsync implements double hashed lookup workflow. It submits results as they get decrypted and assembled into resChan. If an error occurs it is sent to errChan. -// Once the workflow is finished both channels are closed. -func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, resChan chan<- model.ProviderResult, errChan chan<- error) { - defer func() { - close(resChan) - close(errChan) - }() +// FindAsync implements double hashed lookup workflow. FindAsync returns +// results on resChan until there are no more results or error. When finished, +// resChan is closed and the error or nil is returned. +func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, resChan chan<- model.ProviderResult) error { + defer close(resChan) smh, err := dhash.SecondMultihash(mh) if err != nil { - errChan <- err - return + return err } u := c.dhFindURL.JoinPath(smh.B58String()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) if err != nil { - errChan <- err - return + return err } req.Header.Add("Accept", "application/json") resp, err := c.c.Do(req) if err != nil { - errChan <- err - return + return err } body, err := io.ReadAll(resp.Body) defer resp.Body.Close() if err != nil { - errChan <- err - return + return err } if resp.StatusCode != http.StatusOK { - errChan <- apierror.FromResponse(resp.StatusCode, body) - return + return apierror.FromResponse(resp.StatusCode, body) } encResponse := &model.FindResponse{} err = json.Unmarshal(body, encResponse) if err != nil { - errChan <- err - return + return err } for _, emhrs := range encResponse.EncryptedMultihashResults { for _, evk := range emhrs.EncryptedValueKeys { if ctx.Err() != nil { - errChan <- ctx.Err() - return + return ctx.Err() } vk, err := dhash.DecryptValueKey(evk, mh) // skip errors as we don't want to fail the whole query, warn instead. Same applies to the rest of the loop. @@ -174,6 +167,7 @@ func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, res } } } + return nil } // fetchMetadata fetches and decrypts metadata from a remote server. From e2c636df6613584ba77ffd2b8648bd40346cd6ef Mon Sep 17 00:00:00 2001 From: gammazero Date: Wed, 31 May 2023 11:04:53 -0700 Subject: [PATCH 2/2] Need to select for writing to results in case context is canceled --- find/client/dhash_client.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/find/client/dhash_client.go b/find/client/dhash_client.go index ef98f75..a57c935 100644 --- a/find/client/dhash_client.go +++ b/find/client/dhash_client.go @@ -133,9 +133,6 @@ func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, res for _, emhrs := range encResponse.EncryptedMultihashResults { for _, evk := range emhrs.EncryptedValueKeys { - if ctx.Err() != nil { - return ctx.Err() - } vk, err := dhash.DecryptValueKey(evk, mh) // skip errors as we don't want to fail the whole query, warn instead. Same applies to the rest of the loop. if err != nil { @@ -163,7 +160,11 @@ func (c *DHashClient) FindAsync(ctx context.Context, mh multihash.Multihash, res } for _, pr := range prs { - resChan <- pr + select { + case resChan <- pr: + case <-ctx.Done(): + return ctx.Err() + } } } }