timer.go 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. package router
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "time"
  7. "github.com/imgproxy/imgproxy/v3/config"
  8. "github.com/imgproxy/imgproxy/v3/ierrors"
  9. "github.com/imgproxy/imgproxy/v3/metrics"
  10. )
  11. type timerSinceCtxKey = struct{}
  12. func startRequestTimer(r *http.Request) (*http.Request, context.CancelFunc) {
  13. ctx := r.Context()
  14. ctx = context.WithValue(ctx, timerSinceCtxKey{}, time.Now())
  15. ctx, cancel := context.WithTimeout(ctx, time.Duration(config.WriteTimeout)*time.Second)
  16. return r.WithContext(ctx), cancel
  17. }
  18. func ctxTime(ctx context.Context) time.Duration {
  19. if t, ok := ctx.Value(timerSinceCtxKey{}).(time.Time); ok {
  20. return time.Since(t)
  21. }
  22. return 0
  23. }
  24. func CheckTimeout(ctx context.Context) {
  25. select {
  26. case <-ctx.Done():
  27. d := ctxTime(ctx)
  28. if ctx.Err() != context.DeadlineExceeded {
  29. panic(ierrors.New(499, fmt.Sprintf("Request was cancelled after %v", d), "Cancelled"))
  30. }
  31. metrics.SendTimeout(ctx, d)
  32. panic(ierrors.New(503, fmt.Sprintf("Timeout after %v", d), "Timeout"))
  33. default:
  34. // Go ahead
  35. }
  36. }