Skip to content
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

feat: add WaitUntilEmpty to LogSender #12159

Merged
merged 1 commit into from
Feb 20, 2024
Merged

Conversation

spikecurtis
Copy link
Contributor

@spikecurtis spikecurtis commented Feb 15, 2024

We'll need this to be able to tell when all outstanding logs have been sent, as part of graceful shutdown.

@spikecurtis spikecurtis marked this pull request as ready for review February 15, 2024 12:53
case <-nevermind:
return
}
}()
Copy link
Member

@mafredri mafredri Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we duplicating logic from SendLoop here? Since this method doesn't attempt to send, it's quite pointless unless the signaling is happening from a running SendLoop anyway.

Edit: Ah, nevermind, just realized this is only here to handle the user provided context.

I think this could be greatly simplified:

func (l *LogSender) WaitUntilEmpty(ctx context.Context) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case <-l.allSent:
		return nil
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with an allSent channel is how to arrange when it should read. Closing the channel won't work, because you can't "unclose" it if more data gets queued.

Writing to the channel won't work if there are more than one caller to WaitUntilEmpty.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, it would work better/simpler if the send loop was channel-based as well. In that case, one approach could be this:

func (l *LogSender) WaitUntilEmpty(ctx context.Context) error {
	wait := make(chan struct{})
	l.waitUntilEmpty <- wait

	select {
	case <-ctx.Done():
		return ctx.Err()
	case <-wait:
		return nil
	}
}

// SendLoop
	var waiters []chan struct{}
	for {
		select {
		case <-tick:
		case <-l.waitUntilEmpty:
			waiters = append(waiters, wait)
		}

		// ...

		if len(l.queues) == 0 {
			for _, wait := range waiters {
				close(wait)
			}
			waiters = nil
		}

But it's not quite as nice when retrofitted into the mutex style loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem there is that it requires SendLoop to actually be running in order for WaitUntilEmpty() to return, which it might not be but we are still empty.

Channels are great for communicating between goroutines. Here what we really, actually want is to know when a condition is satisfied, regardless of other running goroutines, and for that sync.Cond is your friend.

Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a suggestion for changing WaitUntilEmpty, but I'll leave it up to you whether or not to implement. Works as-is, too, although I feel mutexes are starting to make this service overly complex (vs using channel based communication).

Comment on lines +508 to +517
if len(l.queues) == 0 {
return nil
}
return ctx.Err()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(l.queues) == 0 {
return nil
}
return ctx.Err()
return ctx.Err()

We don't actually need this check, this way we give priority to the context cancellation, even if we happen to be done at the same time (this can be preferable in some cases).

@spikecurtis spikecurtis force-pushed the spike/10534-log-sender-agentsdk branch from 2a2203e to 900e32a Compare February 16, 2024 10:12
Base automatically changed from spike/10534-log-sender-agentsdk to main February 20, 2024 06:44
@spikecurtis spikecurtis merged commit ab4cb66 into main Feb 20, 2024
22 checks passed
@spikecurtis spikecurtis deleted the spike/10534-wait-until-empty branch February 20, 2024 07:11
Copy link
Contributor Author

Merge activity

@github-actions github-actions bot locked and limited conversation to collaborators Feb 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants