[Flyte 7757] Prevent NOTIFY from blocking action writes - #7965
Conversation
| runNotifyCh chan string | ||
| notifyMu sync.Mutex | ||
| pendingActions map[string]struct{} | ||
| pendingRuns map[string]struct{} |
There was a problem hiding this comment.
Why do we change the data structure to map here? I think we will not be able to guarantee FIFO with a map
There was a problem hiding this comment.
Using a map alone does not guarantee FIFO ordering.
I'll add a slice to preserve the order when sending batch notifications.
| repo.actionNotifyCh = make(chan string, 256) | ||
| repo.runNotifyCh = make(chan string, 256) | ||
| repo.pendingActions = make(map[string]struct{}) | ||
| repo.pendingRuns = make(map[string]struct{}) |
There was a problem hiding this comment.
I think we should still set a boundary for the notification buffer. In case where db shut down, the buffer will keep accumulating the notifications to a point where the run service OOM. I think we can try to find out a buffer size that could pass our pressure test(e.g. 500k actions). WDYT?
There was a problem hiding this comment.
Good catch.
I think that set a boundary to prevent from OOM is a great idea.
When exceeding the boundary, LRU strategy remove the old notification.
|
This is pretty good |
notifyActionUpdate and notifyRunUpdate did a blocking send on a 256-slot channel from inside write RPCs, right after the row was already committed. Once the pump fell behind, a best-effort wakeup turned into user-visible write latency, and a cancelled request context discarded the notification outright, leaving other watchers on a stale phase. Replace the FIFO channels with a mutex-guarded pending set per notification kind plus a capacity-1 signal channel. The writer inserts a key and nudges the pump without ever blocking; the pump swaps the sets out and emits them. Because a payload is an identity and every listener re-reads state from the database when woken, repeated updates for one action collapse into a single delivery, and memory is bounded by distinct pending actions rather than by update volume. A failed pg_notify merges its keys back into the pending set and retries with backoff instead of dropping them, so a transient database problem costs a delay rather than a lost wakeup. Two limits keep that retry from becoming a new failure mode. A payload only spends its retry budget when the connection was healthy and it failed anyway, which is what happens to a payload Postgres will never accept, such as one of 8000 bytes or more; after enough of those attempts it is dropped with an error. And a drain that delivered anything resets the backoff, so one bad payload cannot slow every other watcher down. A lost connection aborts the current drain so the remaining payloads do not each trigger their own reconnect attempt. Fixes flyteorg#7757 Signed-off-by: stantheman0128 <stanshih888@gmail.com> Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
Signed-off-by: Yuteng Chen <a08h0283@gmail.com>
popojk
left a comment
There was a problem hiding this comment.
Looks really good. I just have a small comment. Then we are good to go. Thanks!
| notificationBufferLimit = 65_000 | ||
| pendingNotificationCapacity = 256 | ||
| notifyRetryMinBackoff = 50 * time.Millisecond | ||
| notifyRetryMaxBackoff = 5 * time.Second |
There was a problem hiding this comment.
Can we make these settings configurable in the config file while at the same time keeping the default settings? In this way it is easier for perf test.













Tracking issue
Close #7757
Why are the changes needed?
Action and run updates could block writes when the notification queue was full, or be lost when notification delivery failed.
This issue is addressed by PR-7787.
What changes were proposed in this pull request?
How was this patch tested?
go test ./runs/repository/implLabels
Setup process
A stable environment to run the performance have 24 core and 64G is better.
Or building a k3s cluster with multiple machines which provides 18core and 38G.
Updating k3s setting
Screenshots
Check all the applicable boxes
Related PRs
Stack
If you do use
git townto manage PR Stacks, the stack relevant to this PRwill show below. Otherwise, you can ignore this section.
Docs link