-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added api structure, container and health endpoint
- Loading branch information
aorticweb
committed
Jan 27, 2022
1 parent
386fbdd
commit 1162f72
Showing
9 changed files
with
441 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
root = "." | ||
testdata_dir = "testdata" | ||
tmp_dir = "tmp" | ||
|
||
[build] | ||
bin = "./tmp/main" | ||
cmd = "go build -o ./tmp/main ./app/cmd" | ||
delay = 1000 | ||
exclude_dir = ["assets", "tmp", "vendor", "testdata"] | ||
exclude_file = [] | ||
exclude_regex = ["_test.go"] | ||
exclude_unchanged = false | ||
follow_symlink = false | ||
full_bin = "" | ||
include_dir = [] | ||
include_ext = ["go", "tpl", "tmpl", "html"] | ||
kill_delay = "0s" | ||
log = "build-errors.log" | ||
send_interrupt = false | ||
stop_on_error = true | ||
|
||
[color] | ||
app = "" | ||
build = "yellow" | ||
main = "magenta" | ||
runner = "green" | ||
watcher = "cyan" | ||
|
||
[log] | ||
time = false | ||
|
||
[misc] | ||
clean_on_exit = false | ||
|
||
[screen] | ||
clear_on_rebuild = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ create-migration: | |
|
||
init-db: | ||
docker-compose run migration | ||
docker-compose up api |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
"time" | ||
|
||
api "github.com/aorticweb/msg-app/app/handlers" | ||
"github.com/sirupsen/logrus" | ||
"gorm.io/driver/postgres" | ||
"gorm.io/gorm" | ||
) | ||
|
||
var dbConnectionWaitTime time.Duration = 5 * time.Minute | ||
var shutdownTimeout time.Duration = 3 * time.Second | ||
var serverListenAddr string = ":8080" | ||
|
||
func dbConnection(url string) (*gorm.DB, error) { | ||
return gorm.Open(postgres.Open(url), &gorm.Config{}) | ||
} | ||
|
||
func dbUrl() (string, error) { | ||
url, exist := os.LookupEnv("POSTGRES_URL") | ||
if !exist { | ||
return "", errors.New("Env varialbe POSTGRES_URL is not set") | ||
} | ||
return url, nil | ||
} | ||
|
||
// waitForDB ... wait up to timeout for database to be up then return connection | ||
func waitForDB(timeout time.Duration) (*gorm.DB, error) { | ||
url, err := dbUrl() | ||
if err != nil { | ||
return nil, err | ||
} | ||
db, err := dbConnection(url) | ||
for start := time.Now(); time.Since(start) < timeout; { | ||
if err == nil { | ||
break | ||
} | ||
db, err = dbConnection(url) | ||
time.Sleep(1 * time.Second) | ||
} | ||
return db, err | ||
} | ||
|
||
func registerKillSwitch() chan os.Signal { | ||
shutdown := make(chan os.Signal, 1) | ||
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) | ||
return shutdown | ||
} | ||
|
||
func gracefullyShutdown(server *http.Server) error { | ||
ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) | ||
defer cancel() | ||
|
||
err := server.Shutdown(ctx) | ||
if err == nil { | ||
return nil | ||
} | ||
logrus.Error("Server shutdown did not succeed in %v: %v", shutdownTimeout, err) | ||
err = server.Close() | ||
|
||
if err != nil { | ||
return fmt.Errorf("Server close failed: %v", err) | ||
} | ||
logrus.Info("Bye Bye") | ||
return nil | ||
} | ||
|
||
func waitForKillSwitch(kill chan os.Signal, server *http.Server) { | ||
<-kill | ||
gracefullyShutdown(server) | ||
} | ||
|
||
func setupServer(logger *logrus.Logger) (*http.Server, error) { | ||
db, err := waitForDB(dbConnectionWaitTime) | ||
if err != nil { | ||
logger.Error("Failed to fetch database connection") | ||
return nil, err | ||
} | ||
killSwitch := registerKillSwitch() | ||
API := api.NewAPI(db, logger) | ||
server := http.Server{ | ||
Addr: serverListenAddr, | ||
Handler: API, | ||
ReadTimeout: 10 * time.Second, | ||
WriteTimeout: 10 * time.Second, | ||
} | ||
go waitForKillSwitch(killSwitch, &server) | ||
return &server, nil | ||
} | ||
|
||
func must(err error, logger *logrus.Logger) { | ||
if err != nil { | ||
logger.Fatal(err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func main() { | ||
logger := logrus.New() | ||
server, err := setupServer(logger) | ||
must(err, logger) | ||
logger.Info("API says Hello\n") | ||
err = server.ListenAndServe() | ||
if err == http.ErrServerClosed { | ||
logger.Info("API says Goodbye\n") | ||
os.Exit(0) | ||
} | ||
must(err, logger) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package api | ||
|
||
import ( | ||
"net/http" | ||
) | ||
|
||
func (a *API) handleHealth() http.HandlerFunc { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
var c int | ||
a.db.Raw("SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'user';").Scan(&c) | ||
if c != 1 { | ||
a.logger.Error("Health check failed, could not reach database") | ||
w.WriteHeader(http.StatusExpectationFailed) | ||
return | ||
} | ||
w.WriteHeader(http.StatusOK) | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package api | ||
|
||
import ( | ||
"net/http" | ||
|
||
"github.com/gorilla/mux" | ||
"github.com/sirupsen/logrus" | ||
"gorm.io/gorm" | ||
) | ||
|
||
type API struct { | ||
db *gorm.DB | ||
router *mux.Router | ||
logger *logrus.Logger | ||
} | ||
|
||
func (a *API) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||
a.router.ServeHTTP(w, r) | ||
} | ||
|
||
func NewAPI(db *gorm.DB, logger *logrus.Logger) *API { | ||
a := &API{db, mux.NewRouter(), logger} | ||
a.routes() | ||
return a | ||
} | ||
|
||
func (a *API) routes() { | ||
a.router.HandleFunc("/health", a.handleHealth()).Methods("GET") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
FROM golang:latest as dev | ||
|
||
EXPOSE 8080 | ||
|
||
COPY . /msg-app | ||
WORKDIR /msg-app | ||
|
||
RUN curl -sSfL https://raw.githubusercontent.com/cosmtrek/air/master/install.sh | sh -s -- -b $(go env GOPATH)/bin | ||
RUN cd app/cmd/ && CGO_ENABLED=0 GOOS=linux go build -v -o api | ||
|
||
CMD ["air"] | ||
|
||
FROM scratch as prod | ||
|
||
# FROM ubuntu:bionic as prod | ||
|
||
EXPOSE 8080 | ||
|
||
COPY --from=dev /msg-app/app/cmd/api /bin/api | ||
|
||
CMD ["/bin/api"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,23 @@ | ||
module github.com/aorticweb/msg-app.git | ||
module github.com/aorticweb/msg-app | ||
|
||
go 1.17 | ||
|
||
require github.com/gorilla/mux v1.8.0 // indirect | ||
require ( | ||
github.com/gorilla/mux v1.8.0 // indirect | ||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect | ||
github.com/jackc/pgconn v1.10.1 // indirect | ||
github.com/jackc/pgio v1.0.0 // indirect | ||
github.com/jackc/pgpassfile v1.0.0 // indirect | ||
github.com/jackc/pgproto3/v2 v2.2.0 // indirect | ||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect | ||
github.com/jackc/pgtype v1.9.0 // indirect | ||
github.com/jackc/pgx/v4 v4.14.0 // indirect | ||
github.com/jinzhu/inflection v1.0.0 // indirect | ||
github.com/jinzhu/now v1.1.4 // indirect | ||
github.com/sirupsen/logrus v1.8.1 // indirect | ||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect | ||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect | ||
golang.org/x/text v0.3.7 // indirect | ||
gorm.io/driver/postgres v1.2.3 // indirect | ||
gorm.io/gorm v1.22.5 // indirect | ||
) |
Oops, something went wrong.