/
main.go
128 lines (98 loc) · 2.81 KB
/
main.go
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
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/thepabloaguilar/moki/cmd/server/api"
"github.com/thepabloaguilar/moki/core/mock"
"github.com/thepabloaguilar/moki/core/http_operations"
"github.com/rs/zerolog"
"github.com/google/uuid"
"github.com/thepabloaguilar/moki/core/projects"
"github.com/thepabloaguilar/moki/gateways/postgres"
_ "go.uber.org/automaxprocs"
)
func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
// TODO: Change the argument to `os.Stdout` when releasing the first version
logger := zerolog.New(zerolog.NewConsoleWriter()).With().Timestamp().Logger()
if err := run(logger); err != nil {
logger.Fatal().Err(err).Msg("error running application")
}
}
func run(logger zerolog.Logger) error {
ctx := context.Background()
// Postgres
pgPool, err := postgres.NewConnectionPool(ctx, "postgresql://moki:moki@localhost:5432/moki?sslmode=disable", 1, 2)
if err != nil {
return err
}
defer pgPool.Close()
projectsRepo := postgres.NewProjects(pgPool)
httpOperationsRepo := postgres.NewHTTPOperations(pgPool)
now := func() time.Time {
return time.Now().UTC()
}
// Use Cases
createProject := projects.NewCreateProject(now, uuid.New, projectsRepo)
createHTTPOperation := http_operations.NewCreateHTTPOperation(now, uuid.New, &struct {
*postgres.Projects
*postgres.HTTPOperations
}{
Projects: projectsRepo,
HTTPOperations: httpOperationsRepo,
})
executeMock := mock.NewExecuteMock(&struct {
*postgres.Projects
*postgres.HTTPOperations
}{
Projects: projectsRepo,
HTTPOperations: httpOperationsRepo,
})
// Use Cases Collection
projectsCollection := &struct {
*projects.CreateProjectUseCase
*http_operations.CreateHTTPOperationUseCase
}{
CreateProjectUseCase: createProject,
CreateHTTPOperationUseCase: createHTTPOperation,
}
server := api.New(api.Config{
Address: ":8000",
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
UseCases: api.UseCasesCollection{
MockUseCases: executeMock,
ProjectUseCases: projectsCollection,
},
})
ctx, cancel := context.WithCancel(ctx)
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
go func() {
sig := <-signals
log.Printf("received signal %s", sig)
timeoutCtx, cancelTimeoutCtx := context.WithTimeout(ctx, 10*time.Second)
go func() {
<-timeoutCtx.Done()
if errors.Is(timeoutCtx.Err(), context.DeadlineExceeded) {
logger.Fatal().Msg("forcing application shutdown")
}
}()
pgPool.Close()
if err := server.Shutdown(timeoutCtx); err != nil {
logger.Error().Err(err).Msg("error shutingdown server")
}
cancel()
cancelTimeoutCtx()
}()
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
return err
}
return nil
}