mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 00:55:32 +00:00
Lots of stuff
This commit is contained in:
12
controllers/controller.go
Normal file
12
controllers/controller.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/app"
|
||||||
|
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/templating"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ControllerFunc is a function that get injected all dependencies and returns a http.HandlerFunc
|
||||||
|
// A controller is resposible for executing all the neccessary middlewares and rendering the HTML
|
||||||
|
type ControllerFunc func(kgpz *app.KGPZ, layouts *templating.LayoutRegistry, templates *templating.TemplateRegistry) http.HandlerFunc
|
||||||
20
kgpz_web.go
20
kgpz_web.go
@@ -12,6 +12,11 @@ import (
|
|||||||
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/server"
|
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEFAULT_CONFIG = "config.json"
|
||||||
|
DEV_CONFIG = "config.dev.json"
|
||||||
|
)
|
||||||
|
|
||||||
// 1. Check if folder exists
|
// 1. Check if folder exists
|
||||||
// - If not, clone the repo, if possible or throw if error
|
// - If not, clone the repo, if possible or throw if error
|
||||||
// 2. If the folder exists, we try to serialize -- and spawn a goroutine to pull.
|
// 2. If the folder exists, we try to serialize -- and spawn a goroutine to pull.
|
||||||
@@ -24,7 +29,7 @@ import (
|
|||||||
// - Setup GitHub webhook if set
|
// - Setup GitHub webhook if set
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg := providers.NewConfigProvider([]string{"config.dev.json", "config.json"})
|
cfg := providers.NewConfigProvider([]string{DEV_CONFIG, DEFAULT_CONFIG})
|
||||||
if err := cfg.Read(); err != nil {
|
if err := cfg.Read(); err != nil {
|
||||||
helpers.MaybePanic(err, "Error reading config")
|
helpers.MaybePanic(err, "Error reading config")
|
||||||
}
|
}
|
||||||
@@ -32,7 +37,7 @@ func main() {
|
|||||||
kgpz := app.NewKGPZ(cfg)
|
kgpz := app.NewKGPZ(cfg)
|
||||||
Bootstrap(kgpz)
|
Bootstrap(kgpz)
|
||||||
|
|
||||||
server := server.Start(kgpz)
|
server := server.Start(kgpz, cfg)
|
||||||
Start(kgpz, server)
|
Start(kgpz, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +55,16 @@ func Start(k *app.KGPZ, s *server.Server) {
|
|||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
_ = <-sigs
|
sig := <-sigs
|
||||||
fmt.Println("Received signal. Cleaning up.")
|
fmt.Println("Received signal. Cleaning up.")
|
||||||
// INFO: here we add cleanup functions
|
// INFO: here we add cleanup functions
|
||||||
s.Stop()
|
if sig == syscall.SIGTERM {
|
||||||
fmt.Println("Server stopped. Waiting for FS.")
|
s.Stop()
|
||||||
|
fmt.Println("Server stopped. Waiting for FS.")
|
||||||
|
} else {
|
||||||
|
s.Kill()
|
||||||
|
fmt.Println("Server killed. Waiting for FS.")
|
||||||
|
}
|
||||||
k.Shutdown()
|
k.Shutdown()
|
||||||
fmt.Println("FS stopped. Exiting.")
|
fmt.Println("FS stopped. Exiting.")
|
||||||
done <- true
|
done <- true
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ const (
|
|||||||
DEFAULT_GIT_DIR = "data_git"
|
DEFAULT_GIT_DIR = "data_git"
|
||||||
DEFAULT_GND_DIR = "cache_gnd"
|
DEFAULT_GND_DIR = "cache_gnd"
|
||||||
DEFAULT_GEO_DIR = "cache_geo"
|
DEFAULT_GEO_DIR = "cache_geo"
|
||||||
|
|
||||||
|
DEFAULT_PORT = "8080"
|
||||||
|
DEFAULT_ADDR = "localhost"
|
||||||
|
DEFAULT_HTTPS = false
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigProvider struct {
|
type ConfigProvider struct {
|
||||||
@@ -34,6 +38,10 @@ type Config struct {
|
|||||||
WebHookSecret string `json:"webhook_secret" envconfig:"WEBHOOK_SECRET"`
|
WebHookSecret string `json:"webhook_secret" envconfig:"WEBHOOK_SECRET"`
|
||||||
Debug bool `json:"debug" envconfig:"DEBUG"`
|
Debug bool `json:"debug" envconfig:"DEBUG"`
|
||||||
LogData bool `json:"log_data" envconfig:"LOG_DATA"`
|
LogData bool `json:"log_data" envconfig:"LOG_DATA"`
|
||||||
|
|
||||||
|
Address string `json:"address" envconfig:"ADDRESS"`
|
||||||
|
Port string `json:"port" envconfig:"PORT"`
|
||||||
|
Https bool `json:"https" envconfig:"HTTPS"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfigProvider(files []string) *ConfigProvider {
|
func NewConfigProvider(files []string) *ConfigProvider {
|
||||||
@@ -91,6 +99,14 @@ func readDefaults(cfg *Config) *Config {
|
|||||||
cfg.GeoPath = DEFAULT_GEO_DIR
|
cfg.GeoPath = DEFAULT_GEO_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(cfg.Address) == "" {
|
||||||
|
cfg.Address = DEFAULT_ADDR
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(cfg.Port) == "" {
|
||||||
|
cfg.Port = DEFAULT_PORT
|
||||||
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
server/middleware.go
Normal file
5
server/middleware.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Middleware func(http.Handler) http.Handler
|
||||||
17
server/mux.go
Normal file
17
server/mux.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type Mux struct {
|
||||||
|
sm http.ServeMux
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMux() *Mux {
|
||||||
|
return &Mux{
|
||||||
|
sm: http.ServeMux{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mux) Router() *http.ServeMux {
|
||||||
|
return &m.sm
|
||||||
|
}
|
||||||
@@ -1,26 +1,15 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/app"
|
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/app"
|
||||||
)
|
"githib.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
|
||||||
|
|
||||||
type ServerState int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Created ServerState = iota
|
|
||||||
Running
|
|
||||||
Restarting
|
|
||||||
ShuttingDown
|
|
||||||
ShutDown
|
|
||||||
ShuttedDown
|
|
||||||
Kill
|
|
||||||
Killing
|
|
||||||
Killed
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// INFO: Server is a meta-package that handles the current router, which it starts in a goroutine.
|
// INFO: Server is a meta-package that handles the current router, which it starts in a goroutine.
|
||||||
@@ -31,16 +20,19 @@ const (
|
|||||||
// - we reload all clients
|
// - we reload all clients
|
||||||
// - if data validity catastrophically fails, we restart the router to map error pages.
|
// - if data validity catastrophically fails, we restart the router to map error pages.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
running *sync.WaitGroup
|
Config *providers.ConfigProvider
|
||||||
|
running chan bool
|
||||||
shutdown *sync.WaitGroup
|
shutdown *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(k *app.KGPZ) *Server {
|
func Start(k *app.KGPZ, c *providers.ConfigProvider) *Server {
|
||||||
return &Server{}
|
return &Server{
|
||||||
|
Config: c,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Start() {
|
func (s *Server) Start() {
|
||||||
srv := &http.Server{Addr: ":8081"}
|
srv := &http.Server{Addr: s.Config.Address + ":" + s.Config.Port}
|
||||||
s.runner(srv)
|
s.runner(srv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,23 +41,28 @@ func (s *Server) Stop() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.running.Done()
|
s.running <- true
|
||||||
|
s.shutdown.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Kill() {
|
||||||
|
if s.running == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.running <- false
|
||||||
s.shutdown.Wait()
|
s.shutdown.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Restart() {
|
func (s *Server) Restart() {
|
||||||
if s.running != nil {
|
s.Stop()
|
||||||
s.running.Done()
|
|
||||||
s.shutdown.Wait()
|
|
||||||
}
|
|
||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) runner(srv *http.Server) {
|
func (s *Server) runner(srv *http.Server) {
|
||||||
s.running = &sync.WaitGroup{}
|
s.running = make(chan bool)
|
||||||
s.shutdown = &sync.WaitGroup{}
|
s.shutdown = &sync.WaitGroup{}
|
||||||
|
|
||||||
s.running.Add(1)
|
|
||||||
s.shutdown.Add(1)
|
s.shutdown.Add(1)
|
||||||
|
|
||||||
cleanup := sync.WaitGroup{}
|
cleanup := sync.WaitGroup{}
|
||||||
@@ -82,6 +79,7 @@ func (s *Server) runner(srv *http.Server) {
|
|||||||
srv.Handler = mux
|
srv.Handler = mux
|
||||||
|
|
||||||
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||||
|
fmt.Println(err)
|
||||||
fmt.Println("Error starting server")
|
fmt.Println("Error starting server")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -91,10 +89,20 @@ func (s *Server) runner(srv *http.Server) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer cleanup.Done()
|
defer cleanup.Done()
|
||||||
s.running.Wait()
|
clean := <-s.running
|
||||||
|
|
||||||
if err := srv.Shutdown(nil); err != nil {
|
if clean {
|
||||||
fmt.Println("Error shutting down server")
|
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(8*time.Second))
|
||||||
|
defer cancel()
|
||||||
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println("Error shutting down server")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := srv.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println("Error closing server")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
16
techstack.md
16
techstack.md
@@ -65,5 +65,21 @@
|
|||||||
- URL values YYYY/ST and YYYY/ST/P and YYYY/ST/B/P? Are they unique?
|
- URL values YYYY/ST and YYYY/ST/P and YYYY/ST/B/P? Are they unique?
|
||||||
- Which names of places should be used? Example: Mitau, Jelgava, Jelgava (Mitau), Mitau (Jelgava)
|
- Which names of places should be used? Example: Mitau, Jelgava, Jelgava (Mitau), Mitau (Jelgava)
|
||||||
- Informationen zur Vorlage: not saved yet
|
- Informationen zur Vorlage: not saved yet
|
||||||
|
- Titel der Werke: not saved yet
|
||||||
- Übersetzer in Werke: geht tatsächlich
|
- Übersetzer in Werke: geht tatsächlich
|
||||||
|
- Für die meisten Beiträge ist kein Akteur angegeben (Autor, Übersetzer etc.)
|
||||||
|
- Kurzzitat: KGPZ St. 2, 14 Januar 1774 ?
|
||||||
|
- Besser: KGPZ 2/1774, 14. Januar
|
||||||
|
- Die Seite ist sehr gelb????
|
||||||
|
- Übersicht nach Werken = Übersicht nach Personen
|
||||||
|
- Besser: Person
|
||||||
|
Autor
|
||||||
|
Rezensiert
|
||||||
|
Todesanzeige
|
||||||
|
Werke
|
||||||
|
- Ansicht ist nicht strukturiert genug, kann man fixen
|
||||||
|
- Navigation: Galerie / Durchklicken??
|
||||||
|
- Weniger Kästen / Volle Seitenbreite ausnutzen
|
||||||
|
- Horizontale Jahresnavigation durch vertikale ersetzen, so wie in der Einzelansicht
|
||||||
|
- Was ist "Link auf seite teilen"?
|
||||||
- Bevorzugtes Datumsformat
|
- Bevorzugtes Datumsformat
|
||||||
|
|||||||
Reference in New Issue
Block a user