Skip to content

Commit

Permalink
fix(joke): added mutex for set activation flag for external APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Wittano committed Jun 2, 2024
1 parent b804c10 commit b61c24a
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 13 deletions.
8 changes: 6 additions & 2 deletions bot/joke/humorapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"log/slog"
"net/http"
"os"
"sync"
"time"
)

Expand All @@ -30,10 +31,11 @@ var HumorAPILimitExceededErr = errors.New("humorAPI: daily limit of jokes was ex
type HumorAPIService struct {
client http.Client
active bool
m sync.Mutex
globalCtx context.Context
}

func (h HumorAPIService) Active(ctx context.Context) (active bool) {
func (h *HumorAPIService) Active(ctx context.Context) (active bool) {
select {
case <-ctx.Done():
active = false
Expand Down Expand Up @@ -77,10 +79,12 @@ func (h *HumorAPIService) RandomJoke(ctx context.Context, search joke.SearchPara
limitExceeded := len(res.Header[xAPIQuotaLeftHeaderName]) > 0 && res.Header[xAPIQuotaLeftHeaderName][0] == "0"

if res.StatusCode == http.StatusTooManyRequests || res.StatusCode == http.StatusPaymentRequired || limitExceeded {
h.m.Lock()
h.active = false
resetTime := time.Now().Add(time.Hour * 24)

go unlockService(h.globalCtx, &h.active, resetTime)
go unlockService(h.globalCtx, &h.m, &h.active, resetTime)
h.m.Unlock()

return joke.Joke{}, HumorAPILimitExceededErr
} else if res.StatusCode != http.StatusOK {
Expand Down
8 changes: 6 additions & 2 deletions bot/joke/jokedev.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/wittano/komputer/db/joke"
"io"
"net/http"
"sync"
"time"
)

Expand Down Expand Up @@ -74,10 +75,11 @@ var DevServiceLimitExceededErr = errors.New("jokedev: current limit exceeded")
type DevService struct {
client http.Client
active bool
m sync.Mutex
globalCtx context.Context
}

func (d DevService) Active(ctx context.Context) (active bool) {
func (d *DevService) Active(ctx context.Context) (active bool) {
select {
case <-ctx.Done():
active = false
Expand Down Expand Up @@ -121,10 +123,12 @@ func (d *DevService) RandomJoke(ctx context.Context, params joke.SearchParams) (

if res.StatusCode == http.StatusTooManyRequests || isLimitExceeded {
const rateLimitReset = "RateLimit-Reset"
d.m.Lock()
resetTime := resetTime(res.Header[rateLimitReset])
d.active = false

go unlockService(d.globalCtx, &d.active, resetTime)
go unlockService(d.globalCtx, &d.m, &d.active, resetTime)
d.m.Unlock()

return joke.Joke{}, DevServiceLimitExceededErr
}
Expand Down
24 changes: 15 additions & 9 deletions bot/joke/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,33 @@ import (
"github.com/wittano/komputer/db/joke"
"net/http"
"os"
"sync"
"time"
)

func NewJokeDevService(globalCtx context.Context) joke.SearchService {
client := http.Client{Timeout: time.Second * 1}

return &DevService{client, true, globalCtx}
return &DevService{
client: http.Client{Timeout: time.Second},
active: true,
globalCtx: globalCtx,
}
}

func NewHumorAPIService(globalCtx context.Context) joke.SearchService {
client := http.Client{Timeout: time.Second * 1}

env, ok := os.LookupEnv(humorAPIKey)
active := ok || env != ""

return &HumorAPIService{client, active, globalCtx}
return &HumorAPIService{
client: http.Client{Timeout: time.Second},
active: ok || env != "",
globalCtx: globalCtx,
}
}

func NewDatabaseJokeService(database db.MongodbService) joke.Database {
func NewJokeDatabase(database db.MongodbService) joke.Database {
return joke.Database{Mongodb: database}
}

func unlockService(ctx context.Context, activeFlag *bool, resetTime time.Time) {
func unlockService(ctx context.Context, m *sync.Mutex, activeFlag *bool, resetTime time.Time) {
deadlineCtx, cancel := context.WithDeadline(ctx, resetTime)
defer cancel()

Expand All @@ -39,7 +43,9 @@ func unlockService(ctx context.Context, activeFlag *bool, resetTime time.Time) {

select {
case <-deadlineCtx.Done():
m.Lock()
*activeFlag = true
m.Unlock()
return
default:
}
Expand Down

0 comments on commit b61c24a

Please sign in to comment.