# #go #caching #locking #access-token
Вопрос:
У меня есть случай использования, когда api нуждается в api_access_token…Я думаю о кэшировании токена и отслеживании времени истечения срока действия или блокировки на запрос для обработки параллельных запросов, любые предложения о том, как я могу реализовать или каким-либо идеальным способом?
apiAccessToken = createAPIAccessToken(ctx, userId)
url := "https://<hostname>/<api>"
c := http.Client{Timeout: time.Duration(5) * time.Second}
myJson := bytes.NewBuffer([]byte(`{"key":"set.table.attr","Custom_Field":"yes"}`))
req, err := http.NewRequest("POST", url, myJson)
if err != nil {
return
}
req.Header.Add("token", apiAccessToken)
res, err := c.Do(req)
defer res.Body.Close()
Комментарии:
1. вы можете оформить заказ github.com/patrickmn/go-cache если у вас есть небольшое количество значений, которые должны храниться локально в памяти, в противном случае необходимо искать внешнее кэширование, например redis
Ответ №1:
Может быть, что-то вроде этого поможет вам начать. Это возвращает все запросы из кэша и обновляет кэш в фоновом режиме асинхронно по расписанию time.Ticker
package main
import(
"fmt"
"time"
"sync"
)
type Cache struct {
data interface{}
update func(interface{})interface{}
l sync.Mutex
wg sync.WaitGroup
update_period time.Duration
done chan struct{}
}
func (c *Cache)Get() interface{} {
c.l.Lock()
defer c.l.Unlock()
return c.data
}
func (c *Cache)periodicUpdater() {
c.wg.Add(1)
defer c.wg.Done()
t := time.NewTicker(c.update_period)
for {
select{
case <-t.C:
fmt.Println("Updating")
newdata := c.update(c.data)
c.l.Lock()
c.data = newdata
c.l.Unlock()
case <-c.done:
t.Stop()
return
}
}
}
func main() {
c := amp;Cache{
update: func(data interface{}) interface{} {
if d, ok := data.(int); !ok {
panic("unexpected type")
} else {
return d 1
}
},
update_period: 1 * time.Second,
done: make(chan struct{}),
}
c.data = c.update(0)
defer c.wg.Wait()
go c.periodicUpdater()
gt := time.NewTicker(773*time.Millisecond)
for {
select {
case <-gt.C:
x := c.Get()
fmt.Println(x)
if i, ok := x.(int); !ok {
panic("how was this not an int!?!")
} else if i > 15 {
c.done <- struct{}{}
return
}
}
}
}