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