matthews-totw-backend/main.go
2024-09-18 17:12:49 -05:00

247 lines
6.4 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log"
"log/slog"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
/* Variables */
var connPool *pgxpool.Pool
func Config() (*pgxpool.Config) {
const defaultMaxConns = int32(4)
const defaultMinConns = int32(0)
const defaultMaxConnLifetime = time.Hour
const defaultMaxConnIdleTime = time.Minute * 30
const defaultHealthCheckPeriod = time.Minute
const defaultConnectTimeout = time.Second * 5
// Your own Database URL
const DATABASE_URL string = "postgres://tooloftheweek:b4lKAuHRz3Xho6WUQq4YUGnfiAQs5zNg@10.0.100.172:5432/tooloftheweek"
dbConfig, err := pgxpool.ParseConfig(DATABASE_URL)
if err!=nil {
log.Fatal("Failed to create a config, error: ", err)
}
dbConfig.MaxConns = defaultMaxConns
dbConfig.MinConns = defaultMinConns
dbConfig.MaxConnLifetime = defaultMaxConnLifetime
dbConfig.MaxConnIdleTime = defaultMaxConnIdleTime
dbConfig.HealthCheckPeriod = defaultHealthCheckPeriod
dbConfig.ConnConfig.ConnectTimeout = defaultConnectTimeout
dbConfig.BeforeAcquire = func(ctx context.Context, c *pgx.Conn) bool {
slog.Info("Before acquiring the connection pool to the database")
return true
}
dbConfig.AfterRelease = func(c *pgx.Conn) bool {
slog.Info("After releasing the connection pool to the database")
return true
}
dbConfig.BeforeClose = func(c *pgx.Conn) {
slog.Info("Closed the connection pool to the database")
}
return dbConfig
}
/* Structs */
type tool struct {
Name string
Description string
Url string
Week_to_post int
}
/* Database Functions*/
func database_connection(url string) (*pgx.Conn, error) {
var err error
conn, err := pgx.Connect(context.Background(), url)
if err != nil {
slog.Error("Could not connect to database")
}
return conn, err
}
func insertTool(conn *pgx.Conn, new_tool tool) error {
_, err := conn.Exec(context.Background(), "INSERT INTO tool_tb(name,description) VALUES($1,$2)", new_tool.Name, new_tool.Description)
if err != nil {
slog.Error("Could not insert new tool into database")
if err.Error() == `ERROR: duplicate key value violates unique constraint "tool_tb_name_key" (SQLSTATE 23505)` {
slog.Error("Tool already in database.")
} else {
fmt.Println(err)
}
return err
}
return nil
}
func currentTool() (tool,error) {
var currenttool tool
var currentweek int
//Calculate current week
currenttime := int(time.Now().Unix()) + 259200
currentweek = currenttime/604800
fmt.Println(currentweek)
//Select current tool from database
rows, err := connPool.Query(context.Background(), "SELECT id,name,description,url,week_to_post FROM tool_tb WHERE week_to_post=$1", currentweek)
if err != nil {
slog.Error("Could not query tools_tb")
}
for rows.Next(){
var id int
var name string
var description string
var url string
var week_to_post int
//var currenttoolinloop tool
rows.Scan(&id, &name, &description, &url, &week_to_post)
if name == "" {
return currenttool, errors.New("Could not find tool for current week. Please update tool list.")
}
slog.Info("Found tool: " + name)
currenttool.Name = name
currenttool.Description = description
currenttool.Url = url
currenttool.Week_to_post = week_to_post
}
return currenttool, nil
}
func getTools() ([]tool,error) {
var err error
var tools []tool
rows, err := connPool.Query(context.Background(), "SELECT id,name,description,url,week_to_post FROM tool_tb")
if err != nil {
slog.Error("Could not query tool_tb")
return nil, err
}
for rows.Next(){
var id int
var name string
var description string
var url string
var week_to_post int
var currenttoolinloop tool
err := rows.Scan(&id, &name, &description, &url, &week_to_post)
if err != nil {
slog.Error("Could not scan query")
return nil, err
}
currenttoolinloop.Name = name
currenttoolinloop.Description = description
currenttoolinloop.Url = url
currenttoolinloop.Week_to_post = week_to_post
tools = append(tools, currenttoolinloop)
}
return tools, nil
}
/* Gin Functions */
func getToolsHandler(c *gin.Context) {
//var tools []tool
tools, err := getTools()
if err != nil {
fmt.Println(err)
}
fmt.Println(tools)
c.IndentedJSON(http.StatusOK, tools)
}
func currentToolHandler(c *gin.Context) {
var currenttool tool
//var tools []tool
currenttool, err := currentTool()
if err != nil {
fmt.Println(err)
}
fmt.Println(currenttool)
c.IndentedJSON(http.StatusOK, currenttool)
}
func insertToolHandler(c *gin.Context) {
var newTool tool
c.IndentedJSON(http.StatusCreated, newTool)
}
func updateToolHandler(c *gin.Context) {
var updatedTool tool
c.IndentedJSON(http.StatusOK, updatedTool)
}
func deleteToolHandler(c *gin.Context) {
var removedTool tool
c.IndentedJSON(http.StatusOK, removedTool)
}
func main() {
var err error
connPool, err = pgxpool.NewWithConfig(context.Background(), Config())
if err != nil {
log.Fatal("Error acquiring connection from database.")
}
conn, err := connPool.Acquire(context.Background())
if err!=nil {
log.Fatal("Error while acquiring connection from the database pool!!")
}
defer conn.Release()
err = conn.Ping(context.Background())
if err != nil {
log.Fatal("Could not ping database.")
}
slog.Info("Connection to database successful.")
_, err = conn.Exec(context.Background(), "CREATE TABLE IF NOT EXISTS tool_tb (id SERIAL, name TEXT UNIQUE, url TEXT, description TEXT, time_created TIMESTAMP, week_to_post INT)")
if err != nil {
slog.Error("Could not create tool table.")
}
router := gin.Default()
router.GET("/api/v0/tools", getToolsHandler)
router.GET("/api/v0/tooloftheweek", currentToolHandler)
router.POST("/api/v0/inserttool", insertToolHandler)
router.POST("/api/v0/updatetool", updateToolHandler)
router.POST("/api/v0/deletetool", deleteToolHandler)
router.Run("0.0.0.0:8080")
}