[hw-1] implement cart service

This commit is contained in:
Никита Шубин
2025-05-25 15:49:17 +00:00
parent 3d3f10647b
commit 5077f04b0c
28 changed files with 1151 additions and 2 deletions

View File

@@ -0,0 +1,26 @@
package middlewares
import (
"net/http"
"time"
"github.com/rs/zerolog/log"
)
type TimerMiddleware struct {
h http.Handler
}
func NewTimerMiddleware(h http.Handler) http.Handler {
return &TimerMiddleware{
h: h,
}
}
func (m *TimerMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer func(now time.Time) {
log.Debug().Msgf("%s %s spent %s", r.Method, r.URL.String(), time.Since(now))
}(time.Now())
m.h.ServeHTTP(w, r)
}

View File

@@ -0,0 +1,23 @@
package round_trippers
import (
"net/http"
"github.com/rs/zerolog/log"
)
type LogRoundTripper struct {
rt http.RoundTripper
}
func NewLogRoundTripper(rt http.RoundTripper) http.RoundTripper {
return &LogRoundTripper{
rt: rt,
}
}
func (l *LogRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
log.Debug().Msgf("%s called", r.URL.String())
return l.rt.RoundTrip(r)
}

View File

@@ -0,0 +1,67 @@
package round_trippers
import (
"fmt"
"net/http"
"time"
"github.com/rs/zerolog/log"
)
type RetryRoundTripper struct {
rt http.RoundTripper
maxRetries int
initialDelaySec int
}
func NewRetryRoundTripper(rt http.RoundTripper, maxRetries int, initialDelaySec int) http.RoundTripper {
return &RetryRoundTripper{
rt: rt,
maxRetries: maxRetries,
initialDelaySec: initialDelaySec,
}
}
func (rrt *RetryRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
var resp *http.Response
var err error
for attempt := 0; attempt <= rrt.maxRetries; attempt++ {
if attempt > 0 {
// exponential retry time (e.g.: [1s, 2s, 4s])
delay := time.Duration(rrt.initialDelaySec<<uint(attempt-1)) * time.Second
log.Debug().Msgf("retrying, delay=%d", delay)
timer := time.NewTimer(delay)
select {
case <-timer.C:
case <-r.Context().Done():
timer.Stop()
return nil, r.Context().Err()
}
}
resp, err = rrt.rt.RoundTrip(r)
if err != nil {
return nil, err
}
switch resp.StatusCode {
case http.StatusTooManyRequests, 420:
resp.Body.Close()
if attempt == rrt.maxRetries {
return nil, fmt.Errorf("request returned %d after %d retries", resp.StatusCode, rrt.maxRetries)
}
continue
default:
return resp, nil
}
}
return resp, err
}