feat: periodically reload underlying repository

This commit is contained in:
Mya 2022-10-06 12:04:39 -05:00
parent f71c1e5c5a
commit 4ed75d2c7e
No known key found for this signature in database
GPG Key ID: C3ECFA648DAD27FA
5 changed files with 45 additions and 14 deletions

1
.gitignore vendored
View File

@ -22,4 +22,5 @@ go.work
dist/ dist/
.coverprofile
pages pages

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"mime" "mime"
"net/http" "net/http"
"time"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.uber.org/zap" "go.uber.org/zap"
@ -97,6 +98,21 @@ var (
group, c := errgroup.WithContext(ctx.Context) group, c := errgroup.WithContext(ctx.Context)
group.Go(server.ListenAndServe) group.Go(server.ListenAndServe)
group.Go(func() error {
timer := time.NewTimer(hostConfig.Git.SyncInterval)
defer timer.Stop()
for {
select {
case <-c.Done():
return nil
case <-timer.C:
_ = gitService.Sync(ctx.Context)
timer.Reset(hostConfig.Git.SyncInterval)
}
}
})
<-c.Done() <-c.Done()

View File

@ -19,6 +19,7 @@ package git
import ( import (
"context" "context"
"os" "os"
"time"
"github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/osfs" "github.com/go-git/go-billy/v5/osfs"
@ -34,11 +35,12 @@ import (
// Config encapsulates the elements that can be configured about the git service. // Config encapsulates the elements that can be configured about the git service.
type Config struct { type Config struct {
URL string `json:"url" usage:"the git url used to clone the repository"` URL string `json:"url" usage:"the git url used to clone the repository"`
Branch string `json:"branch" usage:"the name of the git branch to clone"` Branch string `json:"branch" usage:"the name of the git branch to clone"`
Tag string `json:"tag" usage:"the name of the git tag to clone"` Tag string `json:"tag" usage:"the name of the git tag to clone"`
Username string `json:"username" usage:"the username used to authenticate with the git service"` Username string `json:"username" usage:"the username used to authenticate with the git service"`
Password string `json:"password" usage:"the password used to authenticate with the git service"` Password string `json:"password" usage:"the password used to authenticate with the git service"`
SyncInterval time.Duration `json:"sync_interval" usage:"how frequently the git repository is pulled for changes" default:"1h"`
} }
// NewService constructs a Service that manages the underlying git repository. // NewService constructs a Service that manages the underlying git repository.

View File

@ -25,6 +25,16 @@ var (
namespace = "pages" namespace = "pages"
page = "page" page = "page"
// by default, summaries give us counts and sums which we can use to compute an average (not great, but it can work)
// in addition to the default information, we report on the following quantiles:
defaultObjectives = map[float64]float64{
0.25: 0, // lower quartile
0.5: 0, // median
0.75: 0, // upper quartile
0.90: 0, // One 9
0.99: 0, // Two 9s
}
// PageViewCount tracks page views by how often they're loaded. // PageViewCount tracks page views by how often they're loaded.
PageViewCount = promauto.NewCounterVec( PageViewCount = promauto.NewCounterVec(
prometheus.CounterOpts{ prometheus.CounterOpts{
@ -37,12 +47,13 @@ var (
) )
// PageSessionDuration tracks how long someone spends on an individual page. // PageSessionDuration tracks how long someone spends on an individual page.
PageSessionDuration = promauto.NewHistogramVec( PageSessionDuration = promauto.NewSummaryVec(
prometheus.HistogramOpts{ prometheus.SummaryOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: page, Subsystem: page,
Name: "session_seconds", Name: "session_seconds",
Help: "how long someone spent on a given page", Help: "how long someone spent on a given page",
Objectives: defaultObjectives,
}, },
[]string{"domain", "path", "country"}, []string{"domain", "path", "country"},
) )

View File

@ -19,7 +19,6 @@ package session
import ( import (
"net/http" "net/http"
"net/url" "net/url"
"time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"go.uber.org/zap" "go.uber.org/zap"
@ -27,6 +26,7 @@ import (
"code.pitz.tech/mya/pages/internal/geoip" "code.pitz.tech/mya/pages/internal/geoip"
"code.pitz.tech/mya/pages/internal/metrics" "code.pitz.tech/mya/pages/internal/metrics"
"github.com/mjpitz/myago/clocks"
"github.com/mjpitz/myago/zaputil" "github.com/mjpitz/myago/zaputil"
) )
@ -62,6 +62,7 @@ type Handle struct {
func (h *Handle) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *Handle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() ctx := r.Context()
log := zaputil.Extract(ctx) log := zaputil.Extract(ctx)
clock := clocks.Extract(ctx)
conn, err := h.upgrader.Upgrade(w, r, nil) conn, err := h.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
@ -91,9 +92,9 @@ func (h *Handle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
active.Inc() active.Inc()
defer func() { active.Dec() }() defer func() { active.Dec() }()
start := time.Now() start := clock.Now()
defer func() { defer func() {
metrics.PageSessionDuration.WithLabelValues(domain, path, geoInfo.CountryCode).Observe(time.Since(start).Seconds()) metrics.PageSessionDuration.WithLabelValues(domain, path, geoInfo.CountryCode).Observe(clock.Since(start).Seconds())
}() }()
for { for {