| 1 | package console |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "log" |
| 6 | "time" |
| 7 | |
| 8 | "github.com/carlosframework/platform/internal/plans" |
| 9 | ) |
| 10 | |
| 11 | // plansMarkerRetry is the first wait between attempts; it doubles up to |
| 12 | // plansMarkerRetryMax. A var so a test can shrink it. |
| 13 | var plansMarkerRetry = 5 * time.Second |
| 14 | |
| 15 | const plansMarkerRetryMax = 5 * time.Minute |
| 16 | |
| 17 | // PublishPlansMarker tells boxes whether plans are on (plans 2). It runs once |
| 18 | // per console start. With a catalog it makes sure control/plans.json is |
| 19 | // enabled under this catalog's id; without one it touches nothing unless an |
| 20 | // enabled marker is left over, which it turns off so boxes stop applying |
| 21 | // limits within a pass. A self-hosted deployment that never configured a |
| 22 | // catalog never gets a marker. |
| 23 | func (s *Server) PublishPlansMarker(ctx context.Context) { |
| 24 | if s.cfg.Releases == nil { |
| 25 | return |
| 26 | } |
| 27 | // Retry until the marker is right: a bucket blip at start must not leave |
| 28 | // boxes applying limits after the catalog was removed, or never applying |
| 29 | // them after it was added (Astra plans-2 finding 1). |
| 30 | wait := plansMarkerRetry |
| 31 | for !s.publishPlansMarkerOnce(ctx) { |
| 32 | select { |
| 33 | case <-ctx.Done(): |
| 34 | return |
| 35 | case <-time.After(wait): |
| 36 | } |
| 37 | wait = min(2*wait, plansMarkerRetryMax) |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | // publishPlansMarkerOnce makes one attempt and reports whether the marker is |
| 42 | // now as it should be (including "nothing to do"). |
| 43 | func (s *Server) publishPlansMarkerOnce(ctx context.Context) bool { |
| 44 | cur, etag, err := plans.GetMarker(ctx, s.cfg.Releases) |
| 45 | if err != nil { |
| 46 | log.Printf("console: plans marker: read: %v", err) |
| 47 | return false |
| 48 | } |
| 49 | want := plans.Marker{UpdatedAt: time.Now().UTC().Truncate(time.Second)} |
| 50 | if cat := s.cfg.PlanCatalog; cat != nil { |
| 51 | if cur != nil && cur.Enabled && cur.CatalogID == cat.ID() { |
| 52 | return true |
| 53 | } |
| 54 | want.Enabled, want.CatalogID = true, cat.ID() |
| 55 | } else if cur == nil || !cur.Enabled { |
| 56 | return true |
| 57 | } |
| 58 | if _, err := plans.PutMarker(ctx, s.cfg.Releases, &want, etag); err != nil { |
| 59 | log.Printf("console: plans marker: write: %v", err) |
| 60 | return false |
| 61 | } |
| 62 | return true |
| 63 | } |
| 64 | |