Skip to content
This repository was archived by the owner on Jun 12, 2024. It is now read-only.

Commit 2867a05

Browse files
authored
chore: bump http kit (#817)
* use new httpkit runner * refactor out last httpkit changes * fix timeout defaults * fix wrong time input - closes #819
1 parent 77b4d59 commit 2867a05

File tree

10 files changed

+123
-69
lines changed

10 files changed

+123
-69
lines changed

backend/app/api/app.go

-14
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
package main
22

33
import (
4-
"time"
5-
64
"github.com/hay-kot/homebox/backend/internal/core/services"
75
"github.com/hay-kot/homebox/backend/internal/core/services/reporting/eventbus"
86
"github.com/hay-kot/homebox/backend/internal/data/ent"
97
"github.com/hay-kot/homebox/backend/internal/data/repo"
108
"github.com/hay-kot/homebox/backend/internal/sys/config"
119
"github.com/hay-kot/homebox/backend/pkgs/mailer"
12-
"github.com/hay-kot/httpkit/server"
1310
)
1411

1512
type app struct {
1613
conf *config.Config
1714
mailer mailer.Mailer
1815
db *ent.Client
19-
server *server.Server
2016
repos *repo.AllRepos
2117
services *services.AllServices
2218
bus *eventbus.EventBus
@@ -37,13 +33,3 @@ func new(conf *config.Config) *app {
3733

3834
return s
3935
}
40-
41-
func (a *app) startBgTask(t time.Duration, fn func()) {
42-
timer := time.NewTimer(t)
43-
44-
for {
45-
timer.Reset(t)
46-
a.server.Background(fn)
47-
<-timer.C
48-
}
49-
}

backend/app/api/bgrunner.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"time"
6+
)
7+
8+
type BackgroundTask struct {
9+
name string
10+
Interval time.Duration
11+
Fn func(context.Context)
12+
}
13+
14+
func (tsk *BackgroundTask) Name() string {
15+
return tsk.name
16+
}
17+
18+
func NewTask(name string, interval time.Duration, fn func(context.Context)) *BackgroundTask {
19+
return &BackgroundTask{
20+
Interval: interval,
21+
Fn: fn,
22+
}
23+
}
24+
25+
func (tsk *BackgroundTask) Start(ctx context.Context) error {
26+
timer := time.NewTimer(tsk.Interval)
27+
28+
for {
29+
select {
30+
case <-ctx.Done():
31+
return nil
32+
case <-timer.C:
33+
timer.Reset(tsk.Interval)
34+
tsk.Fn(ctx)
35+
}
36+
}
37+
}

backend/app/api/main.go

+49-25
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"github.com/hay-kot/homebox/backend/internal/sys/config"
2424
"github.com/hay-kot/homebox/backend/internal/web/mid"
2525
"github.com/hay-kot/httpkit/errchain"
26-
"github.com/hay-kot/httpkit/server"
26+
"github.com/hay-kot/httpkit/graceful"
2727
"github.com/rs/zerolog"
2828
"github.com/rs/zerolog/log"
2929
"github.com/rs/zerolog/pkgerrors"
@@ -178,41 +178,54 @@ func run(cfg *config.Config) error {
178178
middleware.StripSlashes,
179179
)
180180

181-
chain := errchain.New(mid.Errors(app.server, logger))
181+
chain := errchain.New(mid.Errors(logger))
182182

183183
app.mountRoutes(router, chain, app.repos)
184184

185-
app.server = server.NewServer(
186-
server.WithHost(app.conf.Web.Host),
187-
server.WithPort(app.conf.Web.Port),
188-
server.WithReadTimeout(app.conf.Web.ReadTimeout),
189-
server.WithWriteTimeout(app.conf.Web.WriteTimeout),
190-
server.WithIdleTimeout(app.conf.Web.IdleTimeout),
191-
)
192-
log.Info().Msgf("Starting HTTP Server on %s:%s", app.server.Host, app.server.Port)
185+
runner := graceful.NewRunner()
186+
187+
runner.AddFunc("server", func(ctx context.Context) error {
188+
httpserver := http.Server{
189+
Addr: fmt.Sprintf("%s:%s", cfg.Web.Host, cfg.Web.Port),
190+
Handler: router,
191+
ReadTimeout: cfg.Web.ReadTimeout,
192+
WriteTimeout: cfg.Web.WriteTimeout,
193+
IdleTimeout: cfg.Web.IdleTimeout,
194+
}
195+
196+
go func() {
197+
<-ctx.Done()
198+
_ = httpserver.Shutdown(context.Background())
199+
}()
200+
201+
log.Info().Msgf("Server is running on %s:%s", cfg.Web.Host, cfg.Web.Port)
202+
return httpserver.ListenAndServe()
203+
})
193204

194205
// =========================================================================
195206
// Start Reoccurring Tasks
196207

197-
go app.bus.Run()
208+
runner.AddFunc("eventbus", app.bus.Run)
198209

199-
go app.startBgTask(time.Duration(24)*time.Hour, func() {
200-
_, err := app.repos.AuthTokens.PurgeExpiredTokens(context.Background())
210+
runner.AddPlugin(NewTask("purge-tokens", time.Duration(24)*time.Hour, func(ctx context.Context) {
211+
_, err := app.repos.AuthTokens.PurgeExpiredTokens(ctx)
201212
if err != nil {
202213
log.Error().
203214
Err(err).
204215
Msg("failed to purge expired tokens")
205216
}
206-
})
207-
go app.startBgTask(time.Duration(24)*time.Hour, func() {
208-
_, err := app.repos.Groups.InvitationPurge(context.Background())
217+
}))
218+
219+
runner.AddPlugin(NewTask("purge-invitations", time.Duration(24)*time.Hour, func(ctx context.Context) {
220+
_, err := app.repos.Groups.InvitationPurge(ctx)
209221
if err != nil {
210222
log.Error().
211223
Err(err).
212224
Msg("failed to purge expired invitations")
213225
}
214-
})
215-
go app.startBgTask(time.Duration(1)*time.Hour, func() {
226+
}))
227+
228+
runner.AddPlugin(NewTask("send-notifications", time.Duration(1)*time.Hour, func(ctx context.Context) {
216229
now := time.Now()
217230

218231
if now.Hour() == 8 {
@@ -224,7 +237,7 @@ func run(cfg *config.Config) error {
224237
Msg("failed to send notifiers")
225238
}
226239
}
227-
})
240+
}))
228241

229242
// TODO: Remove through external API that does setup
230243
if cfg.Demo {
@@ -233,13 +246,24 @@ func run(cfg *config.Config) error {
233246
}
234247

235248
if cfg.Debug.Enabled {
236-
debugrouter := app.debugRouter()
237-
go func() {
238-
if err := http.ListenAndServe(":"+cfg.Debug.Port, debugrouter); err != nil {
239-
log.Fatal().Err(err).Msg("failed to start debug server")
249+
runner.AddFunc("debug", func(ctx context.Context) error {
250+
debugserver := http.Server{
251+
Addr: fmt.Sprintf("%s:%s", cfg.Web.Host, cfg.Debug.Port),
252+
Handler: app.debugRouter(),
253+
ReadTimeout: cfg.Web.ReadTimeout,
254+
WriteTimeout: cfg.Web.WriteTimeout,
255+
IdleTimeout: cfg.Web.IdleTimeout,
240256
}
241-
}()
257+
258+
go func() {
259+
<-ctx.Done()
260+
_ = debugserver.Shutdown(context.Background())
261+
}()
262+
263+
log.Info().Msgf("Debug server is running on %s:%s", cfg.Web.Host, cfg.Debug.Port)
264+
return debugserver.ListenAndServe()
265+
})
242266
}
243267

244-
return app.server.Start(router)
268+
return runner.Start(context.Background())
245269
}

backend/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ require (
1414
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
1515
github.com/google/uuid v1.6.0
1616
github.com/gorilla/schema v1.2.1
17-
github.com/hay-kot/httpkit v0.0.6
17+
github.com/hay-kot/httpkit v0.0.9
1818
github.com/mattn/go-sqlite3 v1.14.22
1919
github.com/olahol/melody v1.1.4
2020
github.com/pkg/errors v0.9.1

backend/go.sum

+6
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5R
8686
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
8787
github.com/hay-kot/httpkit v0.0.6 h1:BidC4UrkS7zRhoTdpKLeF8ODJPKcOZkJ2tk2t2ZIQjQ=
8888
github.com/hay-kot/httpkit v0.0.6/go.mod h1:1s/OJwWRyH6tBtTw76jTp6kwBYvjswziXaokPQH7eKQ=
89+
github.com/hay-kot/httpkit v0.0.7 h1:KxGi+MwXFavfFUfJEMpye5cnMef9TlFu3v7UZipUB8U=
90+
github.com/hay-kot/httpkit v0.0.7/go.mod h1:AD22YluZrvBDxmtB3Pw2SOyp3A2PZqcmBZa0+COrhoU=
91+
github.com/hay-kot/httpkit v0.0.8 h1:n+Z5z35YZcdD9cGwbnIPRbrgDw9LY6lqakH4zYr5z+A=
92+
github.com/hay-kot/httpkit v0.0.8/go.mod h1:AD22YluZrvBDxmtB3Pw2SOyp3A2PZqcmBZa0+COrhoU=
93+
github.com/hay-kot/httpkit v0.0.9 h1:hu2TPY9awmIYWXxWGubaXl2U61pPvaVsm9YwboBRGu0=
94+
github.com/hay-kot/httpkit v0.0.9/go.mod h1:AD22YluZrvBDxmtB3Pw2SOyp3A2PZqcmBZa0+COrhoU=
8995
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
9096
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
9197
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=

backend/internal/core/services/reporting/eventbus/eventbus.go

+18-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package eventbus
33

44
import (
5+
"context"
56
"sync"
67

78
"github.com/google/uuid"
@@ -43,24 +44,29 @@ func New() *EventBus {
4344
}
4445
}
4546

46-
func (e *EventBus) Run() {
47+
func (e *EventBus) Run(ctx context.Context) error {
4748
if e.started {
4849
panic("event bus already started")
4950
}
5051

5152
e.started = true
5253

53-
for event := range e.ch {
54-
e.mu.RLock()
55-
arr, ok := e.subscribers[event.event]
56-
e.mu.RUnlock()
57-
58-
if !ok {
59-
continue
60-
}
61-
62-
for _, fn := range arr {
63-
fn(event.data)
54+
for {
55+
select {
56+
case <-ctx.Done():
57+
return nil
58+
case event := <-e.ch:
59+
e.mu.RLock()
60+
arr, ok := e.subscribers[event.event]
61+
e.mu.RUnlock()
62+
63+
if !ok {
64+
continue
65+
}
66+
67+
for _, fn := range arr {
68+
fn(event.data)
69+
}
6470
}
6571
}
6672
}

backend/internal/data/repo/main_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ func TestMain(m *testing.M) {
4545
log.Fatalf("failed opening connection to sqlite: %v", err)
4646
}
4747

48-
go tbus.Run()
48+
go func() {
49+
_ = tbus.Run(context.Background())
50+
}()
4951

5052
err = client.Schema.Create(context.Background())
5153
if err != nil {

backend/internal/sys/config/conf.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"os"
9+
"time"
910

1011
"github.com/ardanlabs/conf/v3"
1112
)
@@ -39,12 +40,12 @@ type DebugConf struct {
3940
}
4041

4142
type WebConfig struct {
42-
Port string `yaml:"port" conf:"default:7745"`
43-
Host string `yaml:"host"`
44-
MaxUploadSize int64 `yaml:"max_file_upload" conf:"default:10"`
45-
ReadTimeout int `yaml:"read_timeout" conf:"default:10"`
46-
WriteTimeout int `yaml:"write_timeout" conf:"default:10"`
47-
IdleTimeout int `yaml:"idle_timeout" conf:"default:30"`
43+
Port string `yaml:"port" conf:"default:7745"`
44+
Host string `yaml:"host"`
45+
MaxUploadSize int64 `yaml:"max_file_upload" conf:"default:10"`
46+
ReadTimeout time.Duration `yaml:"read_timeout" conf:"default:10s"`
47+
WriteTimeout time.Duration `yaml:"write_timeout" conf:"default:10s"`
48+
IdleTimeout time.Duration `yaml:"idle_timeout" conf:"default:30s"`
4849
}
4950

5051
// New parses the CLI/Config file and returns a Config struct. If the file argument is an empty string, the

backend/internal/web/mid/errors.go

+1-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type ErrorResponse struct {
1616
Fields map[string]string `json:"fields,omitempty"`
1717
}
1818

19-
func Errors(svr *server.Server, log zerolog.Logger) errchain.ErrorHandler {
19+
func Errors(log zerolog.Logger) errchain.ErrorHandler {
2020
return func(h errchain.Handler) http.Handler {
2121
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2222
err := h.ServeHTTP(w, r)
@@ -71,14 +71,6 @@ func Errors(svr *server.Server, log zerolog.Logger) errchain.ErrorHandler {
7171
if err := server.JSON(w, code, resp); err != nil {
7272
log.Err(err).Msg("failed to write response")
7373
}
74-
75-
// If Showdown error, return error
76-
if server.IsShutdownError(err) {
77-
err := svr.Shutdown(err.Error())
78-
if err != nil {
79-
log.Err(err).Msg("failed to shutdown server")
80-
}
81-
}
8274
}
8375
})
8476
}

frontend/components/Form/DatePicker.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<label class="label">
44
<span class="label-text"> {{ label }}</span>
55
</label>
6-
<input ref="input" v-model="selected" type="date" class="input input-bordered w-full" />
6+
<VueDatePicker v-model="selected" :enable-time-picker="false" clearable :dark="isDark" />
77
</div>
88
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
99
<label class="label">

0 commit comments

Comments
 (0)