Untitled
unknown
plain_text
a year ago
7.2 kB
12
Indexable
database.go:
package config
import (
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectDatabase() {
dsn := "user:Password@1@tcp(127.0.0.1:3306)/choice_db?charset=utf8mb4&parseTime=True&loc=Local"
database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal("Failed to connect to database!", err)
}
DB = database
log.Println("Database connected successfully!")
}
redis.go:
package config
import (
"context"
"fmt"
"log"
"time"
"github.com/go-redis/redis/v8"
)
var (
RDB *redis.Client
Ctx = context.Background()
)
// ConnectRedis initializes the Redis client connection
func ConnectRedis() {
RDB = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
_, err := RDB.Ping(Ctx).Result()
if err != nil {
log.Fatal("Failed to connect to Redis!", err)
}
log.Println("Redis connected successfully!")
}
// ToDo: Test: SetKeyWithTTL sets a Redis key with a 5-minute TTL
func SetKeyWithTTL(key, value string) error {
err := RDB.Set(Ctx, key, value, 5*time.Minute).Err()
if err != nil {
return fmt.Errorf("failed to set key with TTL: %v", err)
}
log.Printf("Key '%s' set with a TTL of 5 minutes\n", key)
return nil
}
// ToDo: Test: CheckTTL retrieves the TTL of a key in Redis
func CheckTTL(key string) error {
ttl, err := RDB.TTL(Ctx, key).Result()
if err != nil {
return fmt.Errorf("failed to retrieve TTL: %v", err)
}
log.Printf("Key '%s' TTL: %v\n", key, ttl)
return nil
}
employees.go:
package models
import (
"time"
)
type Employee struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"type:varchar(255)"`
Age int
Position string `gorm:"type:varchar(255)"`
Department string `gorm:"type:varchar(255)"`
Salary float64 `gorm:"type:decimal(10,2)"`
CreatedAt time.Time
UpdatedAt time.Time
}
routes.go:
package routes
package routes
import (
"golang-assignment/config"
"golang-assignment/services"
"github.com/gin-gonic/gin"
)
func SetupRoutes(r *gin.Engine) {
r.POST("/upload", services.UploadExcel)
r.GET("/employees", services.GetEmployees)
r.PUT("/employee/:id", services.UpdateEmployee)
r.DELETE("/employee/:id", services.DeleteEmployee)
//ToDo : Verify this
r.GET("/set-key", func(c *gin.Context) {
key := "imported_data"
value := "test data"
if err := config.SetKeyWithTTL(key, value); err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "Key set in Redis with TTL"})
})
//ToDo : Verify this
r.GET("/check-ttl", func(c *gin.Context) {
key := "imported_data"
if err := config.CheckTTL(key); err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"message": "TTL checked in logs"})
})
}
delete.go:
package services
import (
"golang-assignment/config"
"golang-assignment/models"
"net/http"
"github.com/gin-gonic/gin"
)
// DeleteEmployee deletes a specific employee record
func DeleteEmployee(c *gin.Context) {
id := c.Param("id")
var employee models.Employee
if err := config.DB.First(&employee, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Employee not found"})
return
}
config.DB.Delete(&employee)
c.JSON(http.StatusOK, gin.H{"message": "Employee deleted successfully"})
}
get.go:
package services
import (
"encoding/json"
"golang-assignment/config"
"golang-assignment/models"
"net/http"
"time"
"github.com/gin-gonic/gin"
)
// GetEmployees retrieves employees data
func GetEmployees(c *gin.Context) {
var employees []models.Employee
cachedData, err := config.RDB.Get(config.Ctx, "employees_cache").Result()
if err == nil {
// If cache hit, return cached data
var cachedEmployees []models.Employee
json.Unmarshal([]byte(cachedData), &cachedEmployees)
c.JSON(http.StatusOK, cachedEmployees)
return
}
// Fallback to MySQL if Redis has no data
config.DB.Find(&employees)
// Cache the fetched data in Redis for 5 minutes
jsonData, _ := json.Marshal(employees)
config.RDB.Set(config.Ctx, "employees_cache", jsonData, 5*time.Minute)
c.JSON(http.StatusOK, employees)
}
update.go:
package services
import (
"golang-assignment/config"
"golang-assignment/models"
"net/http"
"github.com/gin-gonic/gin"
)
// UpdateEmployee updates a specific employee record
func UpdateEmployee(c *gin.Context) {
id := c.Param("id")
var employee models.Employee
if err := config.DB.First(&employee, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Employee not found"})
return
}
if err := c.ShouldBindJSON(&employee); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}
config.DB.Save(&employee)
c.JSON(http.StatusOK, gin.H{"message": "Employee updated successfully"})
}
upload.go:
package services
import (
"encoding/json"
"golang-assignment/config"
"golang-assignment/models"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/xuri/excelize/v2"
)
// UploadExcel handles the upload and parsing of Excel data
func UploadExcel(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "File upload failed"})
return
}
filePath := "./" + file.Filename
if err := c.SaveUploadedFile(file, filePath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file"})
return
}
f, err := excelize.OpenFile(filePath)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid Excel file"})
return
}
defer f.Close()
var employees []models.Employee
rows, err := f.GetRows("uk-500")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read rows"})
return
}
for _, row := range rows[1:] {
if len(row) < 5 {
continue
}
employee := models.Employee{
Name: row[0],
Age: parseAge(row[1]),
Position: row[2],
Department: row[3],
Salary: parseSalary(row[4]),
}
employees = append(employees, employee)
}
// Insert data into MySQL
if err := config.DB.Create(&employees).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to insert data into database",
"details": err.Error(),
})
return
}
// Cache data in Redis
jsonData, _ := json.Marshal(employees)
config.RDB.Set(config.Ctx, "employees_cache", jsonData, 5*time.Minute)
c.JSON(http.StatusOK, gin.H{"message": "File uploaded and data imported successfully"})
}
// Helper function to parse age as an integer, returns 0 if conversion fails
func parseAge(ageStr string) int {
age, err := strconv.Atoi(ageStr)
if err != nil {
return 0
}
return age
}
func parseSalary(salaryStr string) float64 {
salary, err := strconv.ParseFloat(salaryStr, 64)
if err != nil {
return 0.0
}
return salary
}
main.go:
package main
import (
"golang-assignment/config"
"golang-assignment/routes"
"log"
"github.com/gin-gonic/gin"
)
func main() {
config.ConnectDatabase()
config.ConnectRedis()
r := gin.Default()
routes.SetupRoutes(r)
if err := r.Run(":8081"); err != nil {
log.Fatal("Failed to start server:", err)
}
}Editor is loading...
Leave a Comment