-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
140 lines (124 loc) · 3.95 KB
/
Copy pathmain.go
File metadata and controls
140 lines (124 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
valkeyq "linkra/queue/valkey"
"linkra/server"
"linkra/server/components"
"linkra/services"
"linkra/storage"
gormStorage "linkra/storage/gorm"
"linkra/utils"
"log/slog"
"net"
"os"
"os/signal"
"runtime"
"strings"
"syscall"
"time"
"github.com/labstack/echo/v5"
"github.com/valkey-io/valkey-go"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
e := echo.New()
// Use echo logger
log := e.Logger
const defaultDBPath = "storage.db"
sqlitePath, ok := os.LookupEnv("DB_PATH")
if !ok {
log.Warn("the database path is not set, using default " + defaultDBPath)
sqlitePath = defaultDBPath
}
// Prepare db connection.
db, err := gorm.Open(sqlite.Open(sqlitePath), &gorm.Config{})
if err != nil {
log.Error("could not open database connection", slog.String("error", err.Error()))
os.Exit(1)
}
// Prepare queue client
valkeyOptions := valkeyq.NewValkeyOptionsFromEnv()
client, err := valkey.NewClient(valkey.ClientOption{InitAddress: []string{net.JoinHostPort(valkeyOptions.Addr, valkeyOptions.Port)}})
if err != nil {
log.Error("failed to create valkey client", "error", err.Error())
os.Exit(1)
}
// Get server address
const defaultServerAddress = "localhost:8080"
serverAddress, ok := os.LookupEnv("SERVER_ADDRESS")
if !ok {
log.Warn("the SERVER_ADDRESS is not set, using default " + defaultServerAddress)
serverAddress = defaultServerAddress
}
// Prepare constants for templ components.
// This needs to be done before the server starts listening
serverHost, ok := os.LookupEnv("SERVER_HOST")
if !ok {
serverHost = serverAddress
log.Warn("the SERVER_HOST is not set, using server address " + serverHost)
}
if !strings.HasPrefix(serverHost, "http") {
serverHost = "http://" + serverHost
log.Warn("added http:// prefix to SERVER_HOST because it was missing")
}
const (
staticPathSegment = "/static/"
seedDetailPathSegment = "/seed/"
groupDetailPathSegment = "/seeds/"
waybackRedirectPathSegment = "/wa/"
)
components.SetComponentConstants(components.NewComponentConstants(
serverHost,
staticPathSegment,
seedDetailPathSegment,
groupDetailPathSegment,
waybackRedirectPathSegment,
))
// Catch SIGINT and SIGHUP. Prepare gentle shutdown.
// TODO: There are more signals that need catching
signals := []os.Signal{os.Interrupt}
if runtime.GOOS == "linux" {
signals = append(signals, syscall.SIGHUP, syscall.SIGTERM)
}
stopSignal, stop := signal.NotifyContext(context.Background(), signals...)
defer stop()
utils.ShutdownFunc = stop // Setup function, that can be used in cases, where shutdown of the server is necessary.
// Prepare repository
seedRepository := gormStorage.NewSeedRepository(log, db)
idListRepository := gormStorage.NewIdListRepository(db)
repository := storage.NewRepository(seedRepository, idListRepository)
// Prepare services
queue := valkeyq.NewQueue(log, client)
serviceSettings := &services.ServiceSettings{
ServerHost: serverHost,
SeedDetailPath: seedDetailPathSegment,
WaybackRedirectPath: waybackRedirectPathSegment,
}
initiatedServices := services.NewServices(stopSignal, log, repository, queue, serviceSettings)
// Prepare server
server := server.NewServer(
stopSignal,
log,
serverAddress,
initiatedServices,
e,
)
// Start the server in new goroutine
// TODO: See if it makes sense to cath this error.
go server.ListenAndServe()
log.Info("Server is listening at http://" + serverAddress)
// Start listening for results from queue
initiatedServices.CaptureService.ListenForResults(stopSignal)
log.Info("CaptureService is listening for CaptureResults")
// Wait for interrupt
<-stopSignal.Done()
// Wait for shutdown (or timeout and go eat dirt)
shutdownTimeout, stop := context.WithTimeout(context.Background(), 120*time.Second)
defer stop()
err = server.Shutdown(shutdownTimeout)
if err != nil {
log.Error("shutdown timeout run out", slog.String("error", err.Error()))
}
log.Info("Server shutdown")
}