initial commit
This commit is contained in:
commit
a7c436fe4c
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
logs/
|
||||
28
Makefile
Normal file
28
Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
GO ?= go
|
||||
PG_VERSION := 17.6-alpine3.22
|
||||
MOD_NAME := nats-app
|
||||
DB_NAME := nats-db
|
||||
NATS_NAME := nats-sv
|
||||
NATS_VERSION := 2.12.0-alpine3.22
|
||||
|
||||
.PHONY: dockerize-db
|
||||
# Remove and create a development database.
|
||||
dockerize-db:
|
||||
docker rm -f $(DB_NAME)
|
||||
docker run --name $(DB_NAME) -e POSTGRES_PASSWORD=secret -e POSTGRES_USER=developer -e POSTGRES_DB=$(DB_NAME) -p 5432:5432 -d postgres:$(PG_VERSION)
|
||||
|
||||
.PHONY: dockerize-nats
|
||||
# Remove and create a NATS server.
|
||||
dockerize-nats:
|
||||
docker rm -f $(NATS_NAME)
|
||||
docker run --name $(NATS_NAME) -p 4222:4222 -d nats:$(NATS_VERSION)
|
||||
|
||||
.PHONY: run
|
||||
# Start app in development environment
|
||||
run:
|
||||
go run ./app/.
|
||||
|
||||
.PHONY: run-prod
|
||||
run-prod:
|
||||
# Start app in production environment
|
||||
go run ./app/. -env=prod
|
||||
36
README.md
Normal file
36
README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# NATS APP
|
||||
|
||||
Lectura de datos de sensores en un dispositivo IoT. Prueba técnica para optar
|
||||
por el puesto de programador Go.
|
||||
|
||||
## Requisitos previos
|
||||
|
||||
- Docker
|
||||
- NATS CLI
|
||||
- Make, si prefieres la comodidad de usar Makefile
|
||||
|
||||
## Consideraciones
|
||||
|
||||
Hay partes de códigos que son _snippets_ extraídos de una librería de autoría
|
||||
propia. [Repositorio GitHub](https://github.com/zepyrshut/gopher-toolbox). De
|
||||
las cuales son:
|
||||
|
||||
- El _logger_ usando la _stdlib log/slog_.
|
||||
|
||||
## Bitácora
|
||||
|
||||
### Quickstart y toma de contacto con NATS
|
||||
|
||||
Lo primero que he hecho es un _quickstart_ del proyecto, con lo que siempre o
|
||||
casi siempre pongo en mis experimentos. Y lo siguiente, en lugar de empezar a
|
||||
construir el proyecto como loco he tratado de entender cómo funciona NATS. Al
|
||||
final ha sido muy sencillo, siguiendo esos pasos:
|
||||
|
||||
1. Levantar el servidor NATS en Docker
|
||||
2. Instalar el CLI de NATS
|
||||
2. Abrir un puñado de terminales, y en un par de ellas escribir: `nats sub "hello"`
|
||||
lo cual significa que se está suscribiendo al canal `hello`. Y en otra escribir:
|
||||
`nats pub "hello" "Hola mundo!"`, lo cual significa que está escribiendo el
|
||||
mensaje `Hola mundo!` en el canal `hello`.
|
||||
|
||||

|
||||
19
app/main.go
Normal file
19
app/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log/slog"
|
||||
"nats-app/internal/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
environment := flag.String("env", "dev", "dev or prod")
|
||||
flag.Parse()
|
||||
|
||||
_ = app.NewApp(*environment)
|
||||
|
||||
slog.Debug("hello world debug")
|
||||
slog.Info("Hello world info")
|
||||
slog.Warn("Hello world warn")
|
||||
slog.Error("hello world error")
|
||||
}
|
||||
BIN
assets/nats-demo-1.png
Normal file
BIN
assets/nats-demo-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
11
internal/app/app.go
Normal file
11
internal/app/app.go
Normal file
@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
type App struct {
|
||||
}
|
||||
|
||||
func NewApp(environment string) *App {
|
||||
|
||||
startRotativeLogger(environment)
|
||||
|
||||
return &App{}
|
||||
}
|
||||
67
internal/app/logger.go
Normal file
67
internal/app/logger.go
Normal file
@ -0,0 +1,67 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
logFile *os.File
|
||||
)
|
||||
|
||||
func newLogger(environment string) {
|
||||
if err := os.MkdirAll("logs", 0755); err != nil {
|
||||
fmt.Println("error creating logs directory:", err)
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now().Format("2006-01-02")
|
||||
f, err := os.OpenFile(fmt.Sprintf("logs/log%s.log", now), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
fmt.Println("error opening log file:", err)
|
||||
return
|
||||
}
|
||||
|
||||
var level slog.Level
|
||||
var addSource bool
|
||||
|
||||
switch strings.ToLower(environment) {
|
||||
case "dev":
|
||||
level = slog.LevelDebug // -4
|
||||
addSource = true
|
||||
case "prod":
|
||||
level = slog.LevelInfo // 0
|
||||
addSource = false
|
||||
default:
|
||||
level = slog.LevelInfo
|
||||
addSource = false
|
||||
}
|
||||
|
||||
mw := io.MultiWriter(os.Stdout, f)
|
||||
logger := slog.New(slog.NewTextHandler(mw, &slog.HandlerOptions{
|
||||
AddSource: addSource,
|
||||
Level: level,
|
||||
}))
|
||||
|
||||
if logFile != nil {
|
||||
logFile.Close()
|
||||
}
|
||||
|
||||
logFile = f
|
||||
slog.SetDefault(logger)
|
||||
}
|
||||
|
||||
func startRotativeLogger(environment string) {
|
||||
newLogger(environment)
|
||||
|
||||
ticker := time.NewTicker(time.Hour * 24)
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
newLogger(environment)
|
||||
}
|
||||
}()
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user