json - Background Fetch in an API Library -
i'm writing api client (library) hits json end-point , populates in-memory cache.
thus far:
i kick off time.ticker loop in library's init() function hits api every minute, refreshes cache (a struct embeds json struct , timestamp). the public facing function calls in library fetch grab , hence don't need worry rate-limiting on own part, can check timestamp if want confirm freshness of datahowever, starting time.ticker in init() not sense quite right: haven't seen other libs this. want avoid bundle user having ton of work info few json endpoints.
my public api looks this:
// illustration usage: // rt := api.newrt() // err := rt.getlatest // tmpl.executetemplate(w, "my_page.tmpl", m{"results": rt.data}) func (rt *realtime) getlatest() error { rt = realtimecache.cached if rt == nil { homecoming errors.new("no cached response available.") } homecoming nil }
and internal fetcher below:
func fetchlatest() error { log.println("fetching latest rt results.") resp, err := http.get(realtimeendpoint) if err != nil { homecoming err } defer resp.body.close() body, err := ioutil.readall(resp.body) if err != nil { homecoming err } // lock our cache writes realtimecache.lock() defer realtimecache.unlock() var rt *realtime err = json.unmarshal(body, &rt) if err != nil { homecoming err } // update cache realtimecache.cached = rt homecoming nil } func init() { // populate cache on start-up fetchlatest() fetchhistorical() // refresh cache every min (default) ticker := time.newticker(time.second * interval) go func() { _ = range ticker.c { fetchlatest() fetchhistorical() } }() }
there similar functions other parts of api (which i'm modularising, i've kept simple start with), gist of it.
is there improve way have background worker fetch results that's still user-friendly?
like elwinar said, starting timer in init
bad idea, have constructor, "object construction" should happen in it, here's short example :
(check playground total code)
func newrt(interval int) (rt *realtime) { rt = &realtime{ tk: time.newticker(time.second * time.duration(interval)), } go func() { rt.fetch() _ = range rt.tk.c { rt.fetch() } }() homecoming } func (rt *realtime) fetch() { rt.lock() defer rt.unlock() rt.fetchlatest() rt.fetchhistory() }
......
func (rt *realtime) getlatest() error { rt.rlock() defer rt.runlock() if rt.cached == nil || len(rt.cached) == 0 { homecoming errnocachedresponse } homecoming nil } func (rt *realtime) stop() { rt.lock() defer rt.unlock() rt.tk.stop() }
json rest go
No comments:
Post a Comment