Add context

This commit adds and passes context around to (almost) every function.
This allows cancelling (almost) every function call globally.
This commit is contained in:
Tom Wiesing 2022-11-28 13:30:08 +01:00
parent 996ecb9f80
commit 3455f491ca
No known key found for this signature in database
104 changed files with 836 additions and 511 deletions

View file

@ -26,10 +26,10 @@ type Home struct {
func (*Home) Routes() []string { return []string{"/"} }
func (home *Home) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) {
home.updateRedirect(context, io)
home.updateInstances(context, io)
home.updateRender(context, io)
func (home *Home) Handler(ctx context.Context, route string, io stream.IOStream) (http.Handler, error) {
home.updateRedirect(ctx, io)
home.updateInstances(ctx, io)
home.updateRender(ctx, io)
return home, nil
}

View file

@ -19,14 +19,27 @@ func (home *Home) updateInstances(ctx context.Context, io stream.IOStream) {
for t := range timex.TickContext(ctx, home.RefreshInterval) {
io.Printf("[%s]: reloading instance list\n", t.Format(time.Stamp))
names, _ := home.instanceMap()
home.instanceNames.Set(names)
err := (func() error {
ctx, cancel := context.WithTimeout(ctx, home.RefreshInterval)
defer cancel()
names, err := home.instanceMap(ctx)
if err != nil {
return err
}
home.instanceNames.Set(names)
return nil
})()
if err != nil {
io.EPrintf("error reloading instances: ", err.Error())
}
}
}()
}
func (home *Home) instanceMap() (map[string]struct{}, error) {
wissKIs, err := home.Instances.All()
func (home *Home) instanceMap(ctx context.Context) (map[string]struct{}, error) {
wissKIs, err := home.Instances.All(ctx)
if err != nil {
return nil, err
}
@ -41,10 +54,23 @@ func (home *Home) instanceMap() (map[string]struct{}, error) {
func (home *Home) updateRender(ctx context.Context, io stream.IOStream) {
go func() {
for t := range timex.TickContext(ctx, home.RefreshInterval) {
io.Printf("[%s]: reloading home render\n", t.Format(time.Stamp))
io.Printf("[%s]: reloading home render list\n", t.Format(time.Stamp))
bytes, _ := home.homeRender()
home.homeBytes.Set(bytes)
err := (func() error {
ctx, cancel := context.WithTimeout(ctx, home.RefreshInterval)
defer cancel()
bytes, err := home.homeRender(ctx)
if err != nil {
return err
}
home.homeBytes.Set(bytes)
return nil
})()
if err != nil {
io.EPrintf("error reloading instances: ", err.Error())
}
}
}()
}
@ -53,7 +79,7 @@ func (home *Home) updateRender(ctx context.Context, io stream.IOStream) {
var homeHTMLStr string
var homeTemplate = static.AssetsHomeHome.MustParseShared("home.html", homeHTMLStr)
func (home *Home) homeRender() ([]byte, error) {
func (home *Home) homeRender(ctx context.Context) ([]byte, error) {
var context HomeContext
// setup a couple of static things
@ -61,7 +87,7 @@ func (home *Home) homeRender() ([]byte, error) {
context.SelfRedirect = home.Config.SelfRedirect.String()
// find all the WissKIs
wissKIs, err := home.Instances.All()
wissKIs, err := home.Instances.All(ctx)
if err != nil {
return nil, err
}
@ -73,7 +99,7 @@ func (home *Home) homeRender() ([]byte, error) {
i := i
wissKI := instance
eg.Go(func() (err error) {
context.Instances[i], err = wissKI.Info().Information(false)
context.Instances[i], err = wissKI.Info().Information(ctx, false)
return
})
}

View file

@ -16,13 +16,27 @@ func (home *Home) updateRedirect(ctx context.Context, io stream.IOStream) {
for t := range timex.TickContext(ctx, home.RefreshInterval) {
io.Printf("[%s]: reloading overrides\n", t.Format(time.Stamp))
redirect, _ := home.loadRedirect()
home.redirect.Set(&redirect)
err := (func() error {
ctx, cancel := context.WithTimeout(ctx, home.RefreshInterval)
defer cancel()
redirect, err := home.loadRedirect(ctx)
if err != nil {
return err
}
home.redirect.Set(&redirect)
return nil
})()
if err != nil {
io.EPrintf("error reloading overrides: ", err.Error())
}
}
}()
}
func (home *Home) loadRedirect() (redirect Redirect, err error) {
func (home *Home) loadRedirect(ctx context.Context) (redirect Redirect, err error) {
if redirect.Overrides == nil {
redirect.Overrides = make(map[string]string)
}

View file

@ -52,7 +52,7 @@ func (info *Info) ingredients(r *http.Request) (cp ingredientsContext, err error
cp.Time = time.Now().UTC()
// find the instance itself!
instance, err := info.Instances.WissKI(mux.Vars(r)["slug"])
instance, err := info.Instances.WissKI(r.Context(), mux.Vars(r)["slug"])
if err == instances.ErrWissKINotFound {
return cp, httpx.ErrNotFound
}

View file

@ -1,6 +1,7 @@
package info
import (
"context"
"net/http"
"time"
@ -25,18 +26,18 @@ type indexContext struct {
}
func (info *Info) index(r *http.Request) (idx indexContext, err error) {
idx.Distillery, idx.Instances, err = info.Status(true)
idx.Distillery, idx.Instances, err = info.Status(r.Context(), true)
return
}
// Status produces a new observation of the distillery, and a new information of all instances
// The information on all instances is passed the given quick flag.
func (info *Info) Status(QuickInformation bool) (target status.Distillery, information []status.WissKI, err error) {
func (info *Info) Status(ctx context.Context, QuickInformation bool) (target status.Distillery, information []status.WissKI, err error) {
var group errgroup.Group
group.Go(func() error {
// list all the instances
all, err := info.Instances.All()
all, err := info.Instances.All(ctx)
if err != nil {
return err
}
@ -50,7 +51,7 @@ func (info *Info) Status(QuickInformation bool) (target status.Distillery, infor
// store the info for this group!
group.Go(func() (err error) {
information[i], err = instance.Info().Information(true)
information[i], err = instance.Info().Information(ctx, true)
return err
})
}
@ -59,7 +60,9 @@ func (info *Info) Status(QuickInformation bool) (target status.Distillery, infor
})
// gather all the observations
var flags component.FetcherFlags
flags := component.FetcherFlags{
Context: ctx,
}
for _, o := range info.Fetchers {
o := o
group.Go(func() error {

View file

@ -28,11 +28,11 @@ type Info struct {
func (*Info) Routes() []string { return []string{"/dis/"} }
func (info *Info) Handler(route string, context context.Context, io stream.IOStream) (handler http.Handler, err error) {
func (info *Info) Handler(ctx context.Context, route string, io stream.IOStream) (handler http.Handler, err error) {
router := mux.NewRouter()
{
socket := &httpx.WebSocket{
Context: context,
Context: ctx,
Fallback: router,
Handler: info.serveSocket,
}
@ -82,12 +82,12 @@ func (info *Info) Handler(route string, context context.Context, io stream.IOStr
}
// get the instance
instance, err := info.Instances.WissKI(r.PostFormValue("slug"))
instance, err := info.Instances.WissKI(r.Context(), r.PostFormValue("slug"))
if err != nil {
return "", httpx.ErrNotFound
}
target, err := instance.Users().Login(nil, r.PostFormValue("user"))
target, err := instance.Users().Login(r.Context(), nil, r.PostFormValue("user"))
if err != nil {
return "", err
}

View file

@ -29,7 +29,7 @@ type instanceContext struct {
func (info *Info) instance(r *http.Request) (is instanceContext, err error) {
// find the instance itself!
instance, err := info.Instances.WissKI(mux.Vars(r)["slug"])
instance, err := info.Instances.WissKI(r.Context(), mux.Vars(r)["slug"])
if err == instances.ErrWissKINotFound {
return is, httpx.ErrNotFound
}
@ -39,7 +39,7 @@ func (info *Info) instance(r *http.Request) (is instanceContext, err error) {
is.Instance = instance.Instance
// get some more info about the wisski
is.Info, err = instance.Info().Information(false)
is.Info, err = instance.Info().Information(r.Context(), false)
if err != nil {
return is, err
}

View file

@ -1,6 +1,7 @@
package info
import (
"context"
"encoding/json"
"time"
@ -14,14 +15,15 @@ import (
type InstanceAction struct {
NumParams int
HandleInteractive func(info *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error
HandleResult func(info *Info, instance *wisski.WissKI, params ...string) (value any, err error)
HandleInteractive func(ctx context.Context, info *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error
HandleResult func(ctx context.Context, info *Info, instance *wisski.WissKI, params ...string) (value any, err error)
}
var socketInstanceActions = map[string]InstanceAction{
"snapshot": {
HandleInteractive: func(info *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
HandleInteractive: func(ctx context.Context, info *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return info.Exporter.MakeExport(
ctx,
str,
exporter.ExportTask{
Dest: "",
@ -33,18 +35,18 @@ var socketInstanceActions = map[string]InstanceAction{
},
},
"rebuild": {
HandleInteractive: func(_ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Barrel().Build(str, true)
HandleInteractive: func(ctx context.Context, _ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Barrel().Build(ctx, str, true)
},
},
"update": {
HandleInteractive: func(_ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Drush().Update(str)
HandleInteractive: func(ctx context.Context, _ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Drush().Update(ctx, str)
},
},
"cron": {
HandleInteractive: func(_ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Drush().Cron(str)
HandleInteractive: func(ctx context.Context, _ *Info, instance *wisski.WissKI, str stream.IOStream, params ...string) error {
return instance.Drush().Cron(ctx, str)
},
},
}
@ -75,7 +77,7 @@ func (info *Info) handleInstanceAction(conn httpx.WebSocketConnection, action In
}
// resolve the instance
instance, err := info.Instances.WissKI(string(slug.Bytes))
instance, err := info.Instances.WissKI(conn.Context(), string(slug.Bytes))
if err != nil {
<-conn.WriteText("Instance not found")
return
@ -110,7 +112,7 @@ func (info *Info) handleInstanceAction(conn httpx.WebSocketConnection, action In
// handle the interactive action
if action.HandleInteractive != nil {
err := action.HandleInteractive(info, instance, str, params...)
err := action.HandleInteractive(conn.Context(), info, instance, str, params...)
if err != nil {
str.EPrintln(err)
return
@ -120,7 +122,7 @@ func (info *Info) handleInstanceAction(conn httpx.WebSocketConnection, action In
// handle the result computation
if action.HandleResult != nil {
result, err := action.HandleResult(info, instance, params...)
result, err := action.HandleResult(conn.Context(), info, instance, params...)
if err != nil {
str.Println("false")
return

View file

@ -11,7 +11,7 @@ import (
// The server may spawn background tasks, but these should be terminated once context closes.
//
// Logging messages are directed to io.
func (control *Control) Server(context context.Context, io stream.IOStream) (*http.ServeMux, error) {
func (control *Control) Server(ctx context.Context, io stream.IOStream) (*http.ServeMux, error) {
// create a new mux
mux := http.NewServeMux()
@ -19,7 +19,7 @@ func (control *Control) Server(context context.Context, io stream.IOStream) (*ht
for _, s := range control.Servables {
for _, route := range s.Routes() {
io.Printf("mounting %s\n", route)
handler, err := s.Handler(route, context, io)
handler, err := s.Handler(ctx, route, io)
if err != nil {
return nil, err
}

View file

@ -20,7 +20,7 @@ func (*Static) Routes() []string { return []string{"/static/"} }
//go:embed dist
var staticFS embed.FS
func (static *Static) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) {
func (static *Static) Handler(ctx context.Context, route string, io stream.IOStream) (http.Handler, error) {
// take the filesystem
fs, err := fs.Sub(staticFS, "dist")
if err != nil {