writeV2 is similar to write, but it works with v2 proto message, allows partial 4xx writes and gathers statistics. writeV2 returns the statistics. In error cases, writeV2, also returns statistics, but also the error that should be propagated to the remote write sender and httpCode to use for status
(ctx context.Context, req *writev2.Request)
| 268 | // NOTE(bwplotka): TSDB storage is NOT idempotent, so we don't allow "partial retry-able" errors. |
| 269 | // Once we have 5xx type of error, we immediately stop and rollback all appends. |
| 270 | func (h *writeHandler) writeV2(ctx context.Context, req *writev2.Request) (_ remoteapi.WriteResponseStats, errHTTPCode int, _ error) { |
| 271 | app := &remoteWriteAppender{ |
| 272 | Appender: h.appendable.Appender(ctx), |
| 273 | maxTime: timestamp.FromTime(time.Now().Add(maxAheadTime)), |
| 274 | } |
| 275 | |
| 276 | s := remoteapi.WriteResponseStats{} |
| 277 | samplesWithoutMetadata, errHTTPCode, err := h.appendV2(app, req, &s) |
| 278 | if err != nil { |
| 279 | if errHTTPCode/5 == 100 { |
| 280 | // On 5xx, we always rollback, because we expect |
| 281 | // sender to retry and TSDB is not idempotent. |
| 282 | if rerr := app.Rollback(); rerr != nil { |
| 283 | h.logger.Error("writev2 rollback failed on retry-able error", "err", rerr) |
| 284 | } |
| 285 | return remoteapi.WriteResponseStats{}, errHTTPCode, err |
| 286 | } |
| 287 | |
| 288 | // Non-retriable (e.g. bad request error case). Can be partially written. |
| 289 | commitErr := app.Commit() |
| 290 | if commitErr != nil { |
| 291 | // Bad requests does not matter as we have internal error (retryable). |
| 292 | return remoteapi.WriteResponseStats{}, http.StatusInternalServerError, commitErr |
| 293 | } |
| 294 | // Bad request error happened, but rest of data (if any) was written. |
| 295 | h.samplesAppendedWithoutMetadata.Add(float64(samplesWithoutMetadata)) |
| 296 | return s, errHTTPCode, err |
| 297 | } |
| 298 | |
| 299 | // All good just commit. |
| 300 | if err := app.Commit(); err != nil { |
| 301 | return remoteapi.WriteResponseStats{}, http.StatusInternalServerError, err |
| 302 | } |
| 303 | h.samplesAppendedWithoutMetadata.Add(float64(samplesWithoutMetadata)) |
| 304 | return s, 0, nil |
| 305 | } |
| 306 | |
| 307 | func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs *remoteapi.WriteResponseStats) (samplesWithoutMetadata, errHTTPCode int, err error) { |
| 308 | var ( |