diff --git a/go.mod b/go.mod
index 5375841..18fc7d5 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,6 @@ require (
github.com/gliderlabs/ssh v0.3.5
github.com/go-sql-driver/mysql v1.6.0
github.com/gorilla/csrf v1.7.1
- github.com/gorilla/mux v1.8.0
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.5.0
github.com/julienschmidt/httprouter v1.3.0
diff --git a/go.sum b/go.sum
index 31e6ee8..cf131af 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,6 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gorilla/csrf v1.7.1 h1:Ir3o2c1/Uzj6FBxMlAUB6SivgVMy1ONXwYgXn+/aHPE=
github.com/gorilla/csrf v1.7.1/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
@@ -99,6 +97,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/internal/dis/component/server/cron/cron.go b/internal/dis/component/server/cron/cron.go
index 36b2584..56f92f3 100644
--- a/internal/dis/component/server/cron/cron.go
+++ b/internal/dis/component/server/cron/cron.go
@@ -119,18 +119,18 @@ func (control *Cron) Start(ctx context.Context, signal <-chan struct{}) <-chan s
run()
zerolog.Ctx(ctx).Debug().Msg("Cron() beginnning scheduling")
- timer := timex.NewTimer()
+ t := timex.NewTimer()
+ defer timex.ReleaseTimer(t)
for {
- timex.StopTimer(timer)
- timer.Reset(control.Config.CronInterval)
+ timex.StopTimer(t)
+ t.Reset(control.Config.CronInterval)
select {
- case <-timer.C:
+ case <-t.C:
zerolog.Ctx(ctx).Debug().Msg("Cron() timer fired")
case <-signal:
zerolog.Ctx(ctx).Debug().Msg("Cron() received signal")
case <-ctx.Done():
- timex.StopTimer(timer)
return
}
diff --git a/internal/dis/component/server/templating/base.go b/internal/dis/component/server/templating/base.go
index 4ebffea..4247893 100644
--- a/internal/dis/component/server/templating/base.go
+++ b/internal/dis/component/server/templating/base.go
@@ -3,6 +3,7 @@ package templating
import (
"context"
_ "embed"
+ "encoding/json"
"fmt"
"html/template"
"net/http"
@@ -11,6 +12,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
"github.com/FAU-CDI/wisski-distillery/pkg/pools"
+ "github.com/FAU-CDI/wisski-distillery/pkg/timex"
"github.com/gorilla/csrf"
"github.com/rs/zerolog"
)
@@ -30,8 +32,21 @@ func (tpl *Template[C]) Template() *template.Template {
return baseTemplate
}
+// LazyContext is like the lazy context
+func (tpl *Template[C]) LazyContext(r *http.Request, f func() (C, error), funcs ...FlagFunc) (ctx *tContext[C]) {
+ ctx = tpl.context(r, funcs...)
+ ctx.startLazy(f)
+ return ctx
+}
+
// Context generates the context to pass to an instance of the template returned by Template.
func (tpl *Template[C]) Context(r *http.Request, c C, funcs ...FlagFunc) (ctx *tContext[C]) {
+ ctx = tpl.context(r, funcs...)
+ ctx.start(c, nil) // setup the request
+ return ctx
+}
+
+func (tpl *Template[C]) context(r *http.Request, funcs ...FlagFunc) (ctx *tContext[C]) {
// create a new context
ctx = new(tContext[C])
@@ -45,16 +60,9 @@ func (tpl *Template[C]) Context(r *http.Request, c C, funcs ...FlagFunc) (ctx *t
// generate the rest of the options
ctx.Runtime.Flags = ctx.Runtime.Flags.Apply(r, tpl.p.funcs...)
ctx.Runtime.Flags = ctx.Runtime.Flags.Apply(r, funcs...)
-
- // if the context has a runtime flags embed, then set the field properly
- if tpl.p.hasRuntimeFlagsEmbed {
- reflect.ValueOf(&c).Elem().
- FieldByName(runtimeFlagsName).
- Set(reflect.ValueOf(ctx.Runtime))
- }
+ ctx.updateEmbedded = tpl.p.hasRuntimeFlagsEmbed
// the main template
- ctx.cMain = c
ctx.tMain = tpl.p.tpl
// the footer template
@@ -126,22 +134,62 @@ func (tw *Template[C]) HTMLHandlerWithFlags(f func(r *http.Request) (C, []FlagFu
// Callers may not retain references beyond the invocation of the template.
// Callers must not rely on the internal structure of this tContext.
type tContext[C any] struct {
- Runtime RuntimeFlags // underlying flags
+ Runtime RuntimeFlags // underlying flags
+ updateEmbedded bool // should we automatically update an embedded RuntimeFlags inside the context?
ctx context.Context // underlying context for render
// the main template and context
- tMain *template.Template
- cMain C
+ eMain chan error // are we done?
+ cWaiting bool
+ tMain *template.Template
+ cMain C
// the footer template and context
tFooter *template.Template
cFooter RuntimeFlags
}
+func (ctx *tContext[C]) start(c C, err error) {
+ ctx.cMain = c
+ ctx.eMain = make(chan error, 1)
+ ctx.eMain <- err
+}
+
+func (ctx *tContext[C]) startLazy(f func() (C, error)) {
+ ctx.eMain = make(chan error, 1)
+ go func() {
+ defer close(ctx.eMain)
+
+ // compute the result, storing the error
+ var err error
+ ctx.cMain, err = f()
+ ctx.eMain <- err
+ }()
+}
+
+const mainDelay = time.Second
+
// Main renders the main template.
func (ctx *tContext[C]) Main() (template.HTML, error) {
- return ctx.renderSafe("main", ctx.tMain, ctx.cMain)
+ timer := timex.NewTimer()
+ defer timex.ReleaseTimer(timer)
+
+ timer.Reset(mainDelay)
+ select {
+
+ case err := <-ctx.eMain:
+ // we received the result within the given time
+ // so we can render it immediatly
+ ctx.cWaiting = false
+ return ctx.doMain(err)
+
+ case <-timer.C:
+ // the template is taking longer than expected.
+ // we should display a spinner, and do something later
+ ctx.cWaiting = true
+ return timeWait, nil
+ }
}
// Footer renders the footer template
@@ -149,6 +197,52 @@ func (ctx *tContext[C]) Footer() (template.HTML, error) {
return ctx.renderSafe("footer", ctx.tFooter, ctx.cFooter)
}
+const (
+ timeWait = "Loading"
+ errUnknown = "An unknown error occured, see the server log for details. "
+)
+
+func (ctx *tContext[C]) doMain(err error) (template.HTML, error) {
+ zerolog.Ctx(ctx.ctx).Info().Msg("doMain")
+ if err != nil {
+ zerolog.Ctx(ctx.ctx).Err(err).Msg("error lazy loading template")
+ return errUnknown, nil
+ }
+
+ // if the context has a runtime flags embed, then set the field properly
+ if ctx.updateEmbedded {
+ reflect.ValueOf(&ctx.cMain).Elem().
+ FieldByName(runtimeFlagsName).
+ Set(reflect.ValueOf(ctx.Runtime))
+ }
+
+ return ctx.renderSafe("main", ctx.tMain, ctx.cMain)
+}
+
+func (ctx *tContext[C]) AfterBody() (template.HTML, error) {
+ zerolog.Ctx(ctx.ctx).Info().Msg("AfterBody()")
+ // everything was done already
+ if !ctx.cWaiting {
+ return "", nil
+ }
+
+ // wait for the result to appear
+ res, err := ctx.doMain(<-ctx.eMain)
+ if err != nil {
+ return "", err
+ }
+
+ str, err := json.Marshal(string(res))
+ if err != nil {
+ return "", err
+ }
+
+ fix := ""
+
+ // hook that is called after the body is complete
+ return template.HTML(fix), nil
+}
+
const renderSafeError = "Error displaying page. See server log for details. "
func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (template.HTML, error) {
@@ -170,7 +264,7 @@ func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (te
Str("uri", ctx.Runtime.RequestURI).
Str("name", name).
Str("panic", fmt.Sprint(r)).
- Msg("templating.Main(): template panic()ed")
+ Msg("renderSafe: template panic()ed")
}
}()
diff --git a/internal/dis/component/server/templating/src/base.html b/internal/dis/component/server/templating/src/base.html
index f026ad4..f7ecde1 100644
--- a/internal/dis/component/server/templating/src/base.html
+++ b/internal/dis/component/server/templating/src/base.html
@@ -12,7 +12,7 @@