MCPcopy
hub / github.com/grafana/tempo / PreparePartitionDownscaleHandler

Method PreparePartitionDownscaleHandler

modules/livestore/downscale.go:33–129  ·  view source on GitHub ↗

PreparePartitionDownscaleHandler prepares the live-store's partition downscaling. The partition owned by the live-store will switch to INACTIVE state (read-only). Following methods are supported: - GET Returns timestamp when partition was switched to INACTIVE state, or 0, if partition is not in IN

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

31// - DELETE
32// Sets partition back from INACTIVE to ACTIVE state.
33func (s *LiveStore) PreparePartitionDownscaleHandler(w http.ResponseWriter, r *http.Request) {
34 logger := log.With(s.logger, "partition", s.ingestPartitionID)
35
36 // Don't allow callers to change the shutdown configuration while we're in the middle
37 // of starting or shutting down.
38 if s.State() != services.Running {
39 w.WriteHeader(http.StatusServiceUnavailable)
40 return
41 }
42
43 if s.ingestPartitionLifecycler == nil {
44 w.WriteHeader(http.StatusInternalServerError)
45 return
46 }
47
48 switch r.Method {
49 case http.MethodPost:
50 // It's not allowed to prepare the downscale while in PENDING state. Why? Because if the downscale
51 // will be later cancelled, we don't know if it was requested in PENDING or ACTIVE state, so we
52 // don't know to which state reverting back. Given a partition is expected to stay in PENDING state
53 // for a short period, we simply don't allow this case.
54 state, _, err := s.ingestPartitionLifecycler.GetPartitionState(r.Context())
55 if err != nil {
56 level.Error(logger).Log("msg", "cannot downscale: failed to check partition state in the ring", "err", err)
57 w.WriteHeader(http.StatusInternalServerError)
58 return
59 }
60
61 if state == ring.PartitionPending {
62 level.Warn(logger).Log("msg", "received a request to prepare partition for shutdown, but the request can't be satisfied because the partition is in PENDING state")
63 w.WriteHeader(http.StatusConflict)
64 return
65 }
66 if state == ring.PartitionInactive {
67 level.Debug(logger).Log("msg", "partition is already set to INACTIVE state")
68 break
69 }
70
71 if err := s.ingestPartitionLifecycler.ChangePartitionState(r.Context(), ring.PartitionInactive); err != nil {
72 level.Error(logger).Log("msg", "failed to change partition state to inactive", "err", err)
73 w.WriteHeader(http.StatusInternalServerError)
74 return
75 }
76
77 level.Info(logger).Log("msg", "partition prepared for downscaling")
78
79 case http.MethodDelete:
80 state, _, err := s.ingestPartitionLifecycler.GetPartitionState(r.Context())
81 if err != nil {
82 level.Error(logger).Log("msg", "cannot cancel downscaling: failed to check partition state in the ring", "err", err)
83 w.WriteHeader(http.StatusInternalServerError)
84 return
85 }
86
87 // If partition is inactive, make it active. We ignore other states Active and especially Pending.
88 if state == ring.PartitionInactive {
89 // We don't switch it back to PENDING state if there are not enough owners because we want to guarantee consistency
90 // in the read path. If the partition is within the lookback period we need to guarantee that partition will be queried.

Callers

nothing calls this directly

Calls 6

WriteJSONResponseFunction · 0.92
ContextMethod · 0.65
LogMethod · 0.65
ErrorMethod · 0.65
WriteHeaderMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected