Skip to content

Commit 3dd8d13

Browse files
meili-bors[bot]Patrick de Kievitcurquiza
authored
Merge #523
523: Fix issue with ticker leaking CPU, optimize r=curquiza a=thisisdev-patrick #522 # Pull Request ## Related issue Fixes #522 ## What does this PR do? - fixes ticker CPU leakage on the WaitForTask method. I also optimized the method to first check and then start a ticker if needed. Also added some missing unit test for the GetTasks method using the the client package, which is totally unrelated but needed to get to the codecov threshold ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: Patrick de Kievit <patrick@tisgroup.nl> Co-authored-by: Clémentine <clementine@meilisearch.com>
2 parents 805c05a + 1505660 commit 3dd8d13

File tree

3 files changed

+376
-9
lines changed

3 files changed

+376
-9
lines changed

client.go

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515

1616
// ClientConfig configure the Client
1717
type ClientConfig struct {
18-
1918
// Host is the host of your Meilisearch database
2019
// Example: 'http://localhost:7700'
2120
Host string
@@ -64,6 +63,11 @@ type ClientInterface interface {
6463

6564
var _ ClientInterface = &Client{}
6665

66+
const (
67+
defaultWaitForTaskTimeout = 5 * time.Second
68+
defaultWaitForTaskInterval = 50 * time.Millisecond
69+
)
70+
6771
// NewFastHTTPCustomClient creates Meilisearch with custom fasthttp.Client
6872
func NewFastHTTPCustomClient(config ClientConfig, client *fasthttp.Client) *Client {
6973
c := &Client{
@@ -405,32 +409,72 @@ func (c *Client) SwapIndexes(param []SwapIndexesParams) (resp *TaskInfo, err err
405409
// If no ctx and interval are provided WaitForTask will check each 50ms the
406410
// status of a task.
407411
func (c *Client) WaitForTask(taskUID int64, options ...WaitParams) (*Task, error) {
412+
// extract closure to get the task and check the status first before the ticker
413+
fn := func() (*Task, error) {
414+
getTask, err := c.GetTask(taskUID)
415+
if err != nil {
416+
return nil, err
417+
}
418+
419+
if getTask.Status != TaskStatusEnqueued && getTask.Status != TaskStatusProcessing {
420+
return getTask, nil
421+
}
422+
return nil, nil
423+
}
424+
425+
// run first before the ticker, we do not want to wait for the first interval
426+
task, err := fn()
427+
if err != nil {
428+
// Return error if it exists
429+
return nil, err
430+
}
431+
432+
// Return task if it exists
433+
if task != nil {
434+
return task, nil
435+
}
436+
437+
// Check if options are provided, if not create a default context and interval
408438
if options == nil {
409-
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*5)
439+
ctx, cancelFunc := context.WithTimeout(context.Background(), defaultWaitForTaskTimeout)
410440
defer cancelFunc()
411441
options = []WaitParams{
412442
{
413443
Context: ctx,
414-
Interval: time.Millisecond * 50,
444+
Interval: defaultWaitForTaskInterval,
415445
},
416446
}
417447
}
448+
449+
// Create a ticker to check the task status, because our initial check was not successful
418450
ticker := time.NewTicker(options[0].Interval)
451+
452+
// Defer the stop of the ticker, help GC to cleanup
453+
defer func() {
454+
// we might want to revist this, go.mod now is 1.16
455+
// however I still encouter the issue on go 1.22.2
456+
// there are 2 issues regarding tickers
457+
// https://go-review.googlesource.com/c/go/+/512355
458+
// https://github.com/golang/go/issues/61542
459+
ticker.Stop()
460+
ticker = nil
461+
}()
462+
419463
for {
420464
select {
421465
case <-options[0].Context.Done():
422466
return nil, options[0].Context.Err()
423467
case <-ticker.C:
424-
getTask, err := c.GetTask(taskUID)
468+
task, err := fn()
425469
if err != nil {
426470
return nil, err
427471
}
428-
if getTask.Status != TaskStatusEnqueued && getTask.Status != TaskStatusProcessing {
429-
return getTask, nil
472+
473+
if task != nil {
474+
return task, nil
430475
}
431476
}
432477
}
433-
434478
}
435479

436480
// Generate a JWT token for the use of multitenancy

0 commit comments

Comments
 (0)