mirror of https://github.com/hashicorp/consul
add DeliverLatest as common function for use by Manager and ProxyTracker Open (#19564)
Open add DeliverLatest as common function for use by Manager and ProxyTrackerpull/19508/head
parent
8d6545ec43
commit
caaff73337
|
@ -5,6 +5,7 @@ package proxycfg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/hashicorp/consul/lib/channels"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -259,37 +260,15 @@ func (m *Manager) notify(snap *ConfigSnapshot) {
|
||||||
// it will drain the chan and then re-attempt delivery so that a slow consumer
|
// it will drain the chan and then re-attempt delivery so that a slow consumer
|
||||||
// gets the latest config earlier. This MUST be called from a method where m.mu
|
// gets the latest config earlier. This MUST be called from a method where m.mu
|
||||||
// is held to be safe since it assumes we are the only goroutine sending on ch.
|
// is held to be safe since it assumes we are the only goroutine sending on ch.
|
||||||
func (m *Manager) deliverLatest(snap *ConfigSnapshot, ch chan proxysnapshot.ProxySnapshot) {
|
func (m *Manager) deliverLatest(snap proxysnapshot.ProxySnapshot, ch chan proxysnapshot.ProxySnapshot) {
|
||||||
// Send if chan is empty
|
m.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", snap.(*ConfigSnapshot).ProxyID)
|
||||||
select {
|
err := channels.DeliverLatest(snap, ch)
|
||||||
case ch <- snap:
|
if err != nil {
|
||||||
return
|
m.Logger.Error("failed to deliver proxyState to proxy",
|
||||||
default:
|
"proxy", snap.(*ConfigSnapshot).ProxyID,
|
||||||
}
|
|
||||||
|
|
||||||
// Not empty, drain the chan of older snapshots and redeliver. For now we only
|
|
||||||
// use 1-buffered chans but this will still work if we change that later.
|
|
||||||
OUTER:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ch:
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
break OUTER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now send again
|
|
||||||
select {
|
|
||||||
case ch <- snap:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
// This should not be possible since we should be the only sender, enforced
|
|
||||||
// by m.mu but error and drop the update rather than panic.
|
|
||||||
m.Logger.Error("failed to deliver ConfigSnapshot to proxy",
|
|
||||||
"proxy", snap.ProxyID.String(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch registers a watch on a proxy. It might not exist yet in which case this
|
// Watch registers a watch on a proxy. It might not exist yet in which case this
|
||||||
|
|
|
@ -6,6 +6,7 @@ package proxytracker
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/hashicorp/consul/lib/channels"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/go-hclog"
|
"github.com/hashicorp/go-hclog"
|
||||||
|
@ -207,32 +208,8 @@ func (pt *ProxyTracker) PushChange(proxyID *pbresource.ID, proxyState proxysnaps
|
||||||
|
|
||||||
func (pt *ProxyTracker) deliverLatest(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot, ch chan proxysnapshot.ProxySnapshot) {
|
func (pt *ProxyTracker) deliverLatest(proxyID *pbresource.ID, proxyState proxysnapshot.ProxySnapshot, ch chan proxysnapshot.ProxySnapshot) {
|
||||||
pt.config.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", proxyID)
|
pt.config.Logger.Trace("delivering latest proxy snapshot to proxy", "proxyID", proxyID)
|
||||||
// Send if chan is empty
|
err := channels.DeliverLatest(proxyState, ch)
|
||||||
select {
|
if err != nil {
|
||||||
case ch <- proxyState:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not empty, drain the chan of older snapshots and redeliver. For now we only
|
|
||||||
// use 1-buffered chans but this will still work if we change that later.
|
|
||||||
OUTER:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ch:
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
break OUTER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now send again
|
|
||||||
select {
|
|
||||||
case ch <- proxyState:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
// This should not be possible since we should be the only sender, enforced
|
|
||||||
// by m.mu but error and drop the update rather than panic.
|
|
||||||
pt.config.Logger.Error("failed to deliver proxyState to proxy",
|
pt.config.Logger.Error("failed to deliver proxyState to proxy",
|
||||||
"proxy", proxyID.String(),
|
"proxy", proxyID.String(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
package channels
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// DeliverLatest will drain the channel discarding any messages if there are any and sends the current message.
|
||||||
|
func DeliverLatest[T any](val T, ch chan T) error {
|
||||||
|
// Send if chan is empty
|
||||||
|
select {
|
||||||
|
case ch <- val:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it falls through to here, the channel is not empty.
|
||||||
|
// Drain the channel.
|
||||||
|
done := false
|
||||||
|
for !done {
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to send again. If it is not empty, throw an error
|
||||||
|
select {
|
||||||
|
case ch <- val:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("failed to deliver latest event: chan full again after draining")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue