Download this file
| 1 | package activator |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "github.com/carlosframework/platform/internal/hostfiles" |
| 6 | "time" |
| 7 | ) |
| 8 | |
| 9 | // ServingFilesMissing preserves the ordinary no-evidence refusal while |
| 10 | // giving diagnostics a host-incarnation key. It is not a retry policy. |
| 11 | type ServingFilesMissing struct{ Incarnation string } |
| 12 | |
| 13 | func (e *ServingFilesMissing) Error() string { return hostfiles.ErrNoEvidence.Error() } |
| 14 | func (e *ServingFilesMissing) Unwrap() error { return hostfiles.ErrNoEvidence } |
| 15 | |
| 16 | type seedDiagnostic struct { |
| 17 | incarnation string |
| 18 | at map[string]time.Time |
| 19 | } |
| 20 | |
| 21 | func (a *Service) allowFilesDiagnostic(host string, err error, channel string) bool { |
| 22 | var missing *ServingFilesMissing |
| 23 | if !errors.As(err, &missing) { |
| 24 | return true |
| 25 | } |
| 26 | a.mu.Lock() |
| 27 | defer a.mu.Unlock() |
| 28 | if a.seedDiagnostics == nil { |
| 29 | a.seedDiagnostics = map[string]*seedDiagnostic{} |
| 30 | } |
| 31 | d := a.seedDiagnostics[host] |
| 32 | if d == nil || d.incarnation != missing.Incarnation { |
| 33 | d = &seedDiagnostic{incarnation: missing.Incarnation, at: map[string]time.Time{}} |
| 34 | a.seedDiagnostics[host] = d |
| 35 | } |
| 36 | return a.allowFilesDiagnosticLocked(d, channel) |
| 37 | } |
| 38 | func (a *Service) allowFilesDiagnosticLocked(d *seedDiagnostic, channel string) bool { |
| 39 | if d == nil { |
| 40 | return true |
| 41 | } |
| 42 | now := time.Now() |
| 43 | if a.now != nil { |
| 44 | now = a.now() |
| 45 | } |
| 46 | if at := d.at[channel]; !at.IsZero() && now.Before(at.Add(time.Minute)) { |
| 47 | return false |
| 48 | } |
| 49 | d.at[channel] = now |
| 50 | return true |
| 51 | } |
| 52 | |