fix: fixing caching and response api
This commit is contained in:
parent
170fc79148
commit
fc38a43050
|
@ -1,6 +1,8 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"mime/multipart"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
@ -43,7 +45,6 @@ func (h *ArticleHandler) CreateArticle(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {
|
func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {
|
||||||
|
|
||||||
page, err := strconv.Atoi(c.Query("page", "0"))
|
page, err := strconv.Atoi(c.Query("page", "0"))
|
||||||
if err != nil || page < 1 {
|
if err != nil || page < 1 {
|
||||||
page = 0
|
page = 0
|
||||||
|
@ -54,24 +55,17 @@ func (h *ArticleHandler) GetAllArticles(c *fiber.Ctx) error {
|
||||||
limit = 0
|
limit = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var articles []dto.ArticleResponseDTO
|
articles, totalArticles, err := h.ArticleService.GetAllArticles(page, limit)
|
||||||
var totalArticles int
|
|
||||||
|
|
||||||
if page == 0 && limit == 0 {
|
|
||||||
|
|
||||||
articles, totalArticles, err = h.ArticleService.GetAllArticles(0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch articles")
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.NonPaginatedResponse(c, articles, totalArticles, "Articles fetched successfully")
|
|
||||||
}
|
|
||||||
|
|
||||||
articles, totalArticles, err = h.ArticleService.GetAllArticles(page, limit)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch articles")
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch articles")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Total Articles: %d\n", totalArticles)
|
||||||
|
|
||||||
|
if page == 0 && limit == 0 {
|
||||||
|
return utils.NonPaginatedResponse(c, articles, totalArticles, "Articles fetched successfully")
|
||||||
|
}
|
||||||
|
|
||||||
return utils.PaginatedResponse(c, articles, page, limit, totalArticles, "Articles fetched successfully")
|
return utils.PaginatedResponse(c, articles, page, limit, totalArticles, "Articles fetched successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +77,8 @@ func (h *ArticleHandler) GetArticleByID(c *fiber.Ctx) error {
|
||||||
|
|
||||||
article, err := h.ArticleService.GetArticleByID(id)
|
article, err := h.ArticleService.GetArticleByID(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusNotFound, err.Error())
|
|
||||||
|
return utils.GenericResponse(c, fiber.StatusNotFound, "Article not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, article, "Article fetched successfully")
|
return utils.SuccessResponse(c, article, "Article fetched successfully")
|
||||||
|
@ -96,7 +91,6 @@ func (h *ArticleHandler) UpdateArticle(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var request dto.RequestArticleDTO
|
var request dto.RequestArticleDTO
|
||||||
|
|
||||||
if err := c.BodyParser(&request); err != nil {
|
if err := c.BodyParser(&request); err != nil {
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
||||||
}
|
}
|
||||||
|
@ -106,6 +100,7 @@ func (h *ArticleHandler) UpdateArticle(c *fiber.Ctx) error {
|
||||||
return utils.ValidationErrorResponse(c, errors)
|
return utils.ValidationErrorResponse(c, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var coverImage *multipart.FileHeader
|
||||||
coverImage, err := c.FormFile("coverImage")
|
coverImage, err := c.FormFile("coverImage")
|
||||||
if err != nil && err.Error() != "no such file" {
|
if err != nil && err.Error() != "no such file" {
|
||||||
return utils.GenericResponse(c, fiber.StatusBadRequest, "Cover image is required")
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Cover image is required")
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pahmiudahgede/senggoldong/model"
|
"github.com/pahmiudahgede/senggoldong/model"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
@ -28,7 +30,10 @@ func (r *articleRepository) FindArticleByID(id string) (*model.Article, error) {
|
||||||
var article model.Article
|
var article model.Article
|
||||||
err := r.DB.Where("id = ?", id).First(&article).Error
|
err := r.DB.Where("id = ?", id).First(&article).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
return nil, fmt.Errorf("article with ID %s not found", id)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to fetch article: %v", err)
|
||||||
}
|
}
|
||||||
return &article, nil
|
return &article, nil
|
||||||
}
|
}
|
||||||
|
@ -37,21 +42,21 @@ func (r *articleRepository) FindAllArticles(page, limit int) ([]model.Article, i
|
||||||
var articles []model.Article
|
var articles []model.Article
|
||||||
var total int64
|
var total int64
|
||||||
|
|
||||||
err := r.DB.Model(&model.Article{}).Count(&total).Error
|
if err := r.DB.Model(&model.Article{}).Count(&total).Error; err != nil {
|
||||||
if err != nil {
|
return nil, 0, fmt.Errorf("failed to count articles: %v", err)
|
||||||
return nil, 0, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Total Articles Count: %d\n", total)
|
||||||
|
|
||||||
if page > 0 && limit > 0 {
|
if page > 0 && limit > 0 {
|
||||||
err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(&articles).Error
|
err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(&articles).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, fmt.Errorf("failed to fetch articles: %v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
err := r.DB.Find(&articles).Error
|
err := r.DB.Find(&articles).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, fmt.Errorf("failed to fetch articles: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,5 +64,5 @@ func (r *articleRepository) FindAllArticles(page, limit int) ([]model.Article, i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *articleRepository) UpdateArticle(id string, article *model.Article) error {
|
func (r *articleRepository) UpdateArticle(id string, article *model.Article) error {
|
||||||
return r.DB.Save(article).Error
|
return r.DB.Model(&model.Article{}).Where("id = ?", id).Updates(article).Error
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
|
@ -36,8 +37,9 @@ func (s *articleService) CreateArticle(request dto.RequestArticleDTO, coverImage
|
||||||
return nil, fmt.Errorf("failed to create directory for cover image: %v", err)
|
return nil, fmt.Errorf("failed to create directory for cover image: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true}
|
||||||
extension := filepath.Ext(coverImage.Filename)
|
extension := filepath.Ext(coverImage.Filename)
|
||||||
if extension != ".jpg" && extension != ".jpeg" && extension != ".png" {
|
if !allowedExtensions[extension] {
|
||||||
return nil, fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
return nil, fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,83 +92,77 @@ func (s *articleService) CreateArticle(request dto.RequestArticleDTO, coverImage
|
||||||
cacheData := map[string]interface{}{
|
cacheData := map[string]interface{}{
|
||||||
"data": articleResponseDTO,
|
"data": articleResponseDTO,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
|
|
||||||
fmt.Printf("Error caching article to Redis: %v\n", err)
|
fmt.Printf("Error caching article to Redis: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
articlesCacheKey := "articles:all"
|
articles, total, err := s.ArticleRepo.FindAllArticles(0, 0)
|
||||||
if err := utils.DeleteData(articlesCacheKey); err != nil {
|
if err != nil {
|
||||||
|
fmt.Printf("Error fetching all articles: %v\n", err)
|
||||||
fmt.Printf("Error deleting articles cache: %v\n", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
articles, _, err := s.ArticleRepo.FindAllArticles(0, 0)
|
var articleDTOs []dto.ArticleResponseDTO
|
||||||
if err == nil {
|
for _, a := range articles {
|
||||||
var articleDTOs []dto.ArticleResponseDTO
|
createdAt, _ := utils.FormatDateToIndonesianFormat(a.PublishedAt)
|
||||||
for _, a := range articles {
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(a.UpdatedAt)
|
||||||
createdAt, _ := utils.FormatDateToIndonesianFormat(a.PublishedAt)
|
|
||||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(a.UpdatedAt)
|
|
||||||
|
|
||||||
articleDTOs = append(articleDTOs, dto.ArticleResponseDTO{
|
articleDTOs = append(articleDTOs, dto.ArticleResponseDTO{
|
||||||
ID: a.ID,
|
ID: a.ID,
|
||||||
Title: a.Title,
|
Title: a.Title,
|
||||||
CoverImage: a.CoverImage,
|
CoverImage: a.CoverImage,
|
||||||
Author: a.Author,
|
Author: a.Author,
|
||||||
Heading: a.Heading,
|
Heading: a.Heading,
|
||||||
Content: a.Content,
|
Content: a.Content,
|
||||||
PublishedAt: createdAt,
|
PublishedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheData = map[string]interface{}{
|
articlesCacheKey := "articles:all"
|
||||||
"data": articleDTOs,
|
cacheData = map[string]interface{}{
|
||||||
}
|
"data": articleDTOs,
|
||||||
if err := utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24); err != nil {
|
"total": total,
|
||||||
|
}
|
||||||
fmt.Printf("Error caching all articles to Redis: %v\n", err)
|
if err := utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
}
|
fmt.Printf("Error caching all articles to Redis: %v\n", err)
|
||||||
} else {
|
|
||||||
|
|
||||||
fmt.Printf("Error fetching all articles: %v\n", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return articleResponseDTO, nil
|
return articleResponseDTO, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseDTO, int, error) {
|
func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseDTO, int, error) {
|
||||||
|
var cacheKey string
|
||||||
|
|
||||||
cacheKey := fmt.Sprintf("articles_page:%d_limit:%d", page, limit)
|
if page == 0 && limit == 0 {
|
||||||
|
cacheKey = "articles:all"
|
||||||
|
cachedData, err := utils.GetJSONData(cacheKey)
|
||||||
|
if err == nil && cachedData != nil {
|
||||||
|
if data, ok := cachedData["data"].([]interface{}); ok {
|
||||||
|
var articles []dto.ArticleResponseDTO
|
||||||
|
for _, item := range data {
|
||||||
|
articleData, ok := item.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
articles = append(articles, dto.ArticleResponseDTO{
|
||||||
|
ID: articleData["article_id"].(string),
|
||||||
|
Title: articleData["title"].(string),
|
||||||
|
CoverImage: articleData["coverImage"].(string),
|
||||||
|
Author: articleData["author"].(string),
|
||||||
|
Heading: articleData["heading"].(string),
|
||||||
|
Content: articleData["content"].(string),
|
||||||
|
PublishedAt: articleData["publishedAt"].(string),
|
||||||
|
UpdatedAt: articleData["updatedAt"].(string),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cachedData, err := utils.GetJSONData(cacheKey)
|
if total, ok := cachedData["total"].(float64); ok {
|
||||||
if err == nil && cachedData != nil {
|
fmt.Printf("Cached Total Articles: %f\n", total)
|
||||||
var articles []dto.ArticleResponseDTO
|
return articles, int(total), nil
|
||||||
|
} else {
|
||||||
if data, ok := cachedData["data"].([]interface{}); ok {
|
fmt.Println("Total articles not found in cache, using 0 as fallback.")
|
||||||
for _, item := range data {
|
return articles, 0, nil
|
||||||
articleData, ok := item.(map[string]interface{})
|
|
||||||
if ok {
|
|
||||||
|
|
||||||
articles = append(articles, dto.ArticleResponseDTO{
|
|
||||||
ID: articleData["article_id"].(string),
|
|
||||||
Title: articleData["title"].(string),
|
|
||||||
CoverImage: articleData["coverImage"].(string),
|
|
||||||
Author: articleData["author"].(string),
|
|
||||||
Heading: articleData["heading"].(string),
|
|
||||||
Content: articleData["content"].(string),
|
|
||||||
PublishedAt: articleData["publishedAt"].(string),
|
|
||||||
UpdatedAt: articleData["updatedAt"].(string),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
total, ok := cachedData["total"].(float64)
|
|
||||||
if !ok {
|
|
||||||
return nil, 0, fmt.Errorf("invalid total count in cache")
|
|
||||||
}
|
|
||||||
return articles, int(total), nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +171,8 @@ func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseD
|
||||||
return nil, 0, fmt.Errorf("failed to fetch articles: %v", err)
|
return nil, 0, fmt.Errorf("failed to fetch articles: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Total Articles from Database: %d\n", total)
|
||||||
|
|
||||||
var articleDTOs []dto.ArticleResponseDTO
|
var articleDTOs []dto.ArticleResponseDTO
|
||||||
for _, article := range articles {
|
for _, article := range articles {
|
||||||
publishedAt, _ := utils.FormatDateToIndonesianFormat(article.PublishedAt)
|
publishedAt, _ := utils.FormatDateToIndonesianFormat(article.PublishedAt)
|
||||||
|
@ -192,12 +190,14 @@ func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseD
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cacheKey = fmt.Sprintf("articles_page:%d_limit:%d", page, limit)
|
||||||
cacheData := map[string]interface{}{
|
cacheData := map[string]interface{}{
|
||||||
"data": articleDTOs,
|
"data": articleDTOs,
|
||||||
"total": total,
|
"total": total,
|
||||||
}
|
}
|
||||||
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
|
|
||||||
if err != nil {
|
fmt.Printf("Setting cache with total: %d\n", total)
|
||||||
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
fmt.Printf("Error caching articles to Redis: %v\n", err)
|
fmt.Printf("Error caching articles to Redis: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,24 +205,15 @@ func (s *articleService) GetAllArticles(page, limit int) ([]dto.ArticleResponseD
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *articleService) GetArticleByID(id string) (*dto.ArticleResponseDTO, error) {
|
func (s *articleService) GetArticleByID(id string) (*dto.ArticleResponseDTO, error) {
|
||||||
cacheKey := fmt.Sprintf("article:%s", id)
|
|
||||||
|
|
||||||
|
cacheKey := fmt.Sprintf("article:%s", id)
|
||||||
cachedData, err := utils.GetJSONData(cacheKey)
|
cachedData, err := utils.GetJSONData(cacheKey)
|
||||||
if err == nil && cachedData != nil {
|
if err == nil && cachedData != nil {
|
||||||
articleData, ok := cachedData["data"].(map[string]interface{})
|
articleResponse := &dto.ArticleResponseDTO{}
|
||||||
if ok {
|
if data, ok := cachedData["data"].(string); ok {
|
||||||
|
if err := json.Unmarshal([]byte(data), articleResponse); err == nil {
|
||||||
article := dto.ArticleResponseDTO{
|
return articleResponse, nil
|
||||||
ID: articleData["article_id"].(string),
|
|
||||||
Title: articleData["title"].(string),
|
|
||||||
CoverImage: articleData["coverImage"].(string),
|
|
||||||
Author: articleData["author"].(string),
|
|
||||||
Heading: articleData["heading"].(string),
|
|
||||||
Content: articleData["content"].(string),
|
|
||||||
PublishedAt: articleData["publishedAt"].(string),
|
|
||||||
UpdatedAt: articleData["updatedAt"].(string),
|
|
||||||
}
|
}
|
||||||
return &article, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +239,7 @@ func (s *articleService) GetArticleByID(id string) (*dto.ArticleResponseDTO, err
|
||||||
cacheData := map[string]interface{}{
|
cacheData := map[string]interface{}{
|
||||||
"data": articleResponseDTO,
|
"data": articleResponseDTO,
|
||||||
}
|
}
|
||||||
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
|
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
fmt.Printf("Error caching article to Redis: %v\n", err)
|
fmt.Printf("Error caching article to Redis: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +247,7 @@ func (s *articleService) GetArticleByID(id string) (*dto.ArticleResponseDTO, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO, coverImage *multipart.FileHeader) (*dto.ArticleResponseDTO, error) {
|
func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO, coverImage *multipart.FileHeader) (*dto.ArticleResponseDTO, error) {
|
||||||
|
|
||||||
article, err := s.ArticleRepo.FindArticleByID(id)
|
article, err := s.ArticleRepo.FindArticleByID(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("article not found: %v", err)
|
return nil, fmt.Errorf("article not found: %v", err)
|
||||||
|
@ -270,39 +260,10 @@ func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO,
|
||||||
|
|
||||||
var coverImagePath string
|
var coverImagePath string
|
||||||
if coverImage != nil {
|
if coverImage != nil {
|
||||||
coverImageDir := "./public/uploads/articles"
|
coverImagePath, err = s.saveCoverImage(coverImage)
|
||||||
if _, err := os.Stat(coverImageDir); os.IsNotExist(err) {
|
|
||||||
err := os.MkdirAll(coverImageDir, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create directory for cover image: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension := filepath.Ext(coverImage.Filename)
|
|
||||||
if extension != ".jpg" && extension != ".jpeg" && extension != ".png" {
|
|
||||||
return nil, fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
coverImageFileName := fmt.Sprintf("%s_cover%s", uuid.New().String(), extension)
|
|
||||||
coverImagePath = filepath.Join(coverImageDir, coverImageFileName)
|
|
||||||
|
|
||||||
src, err := coverImage.Open()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to open uploaded file: %v", err)
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
|
|
||||||
dst, err := os.Create(coverImagePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create cover image file: %v", err)
|
|
||||||
}
|
|
||||||
defer dst.Close()
|
|
||||||
|
|
||||||
_, err = dst.ReadFrom(src)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to save cover image: %v", err)
|
return nil, fmt.Errorf("failed to save cover image: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
article.CoverImage = coverImagePath
|
article.CoverImage = coverImagePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,15 +292,7 @@ func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO,
|
||||||
}
|
}
|
||||||
|
|
||||||
articleCacheKey := fmt.Sprintf("article:%s", updatedArticle.ID)
|
articleCacheKey := fmt.Sprintf("article:%s", updatedArticle.ID)
|
||||||
err = utils.DeleteData(articleCacheKey)
|
err = utils.SetJSONData(articleCacheKey, map[string]interface{}{"data": articleResponseDTO}, time.Hour*24)
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error deleting old cache for article: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheData := map[string]interface{}{
|
|
||||||
"data": articleResponseDTO,
|
|
||||||
}
|
|
||||||
err = utils.SetJSONData(articleCacheKey, cacheData, time.Hour*24)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error caching updated article to Redis: %v\n", err)
|
fmt.Printf("Error caching updated article to Redis: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -371,7 +324,7 @@ func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheData = map[string]interface{}{
|
cacheData := map[string]interface{}{
|
||||||
"data": articleDTOs,
|
"data": articleDTOs,
|
||||||
}
|
}
|
||||||
err = utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24)
|
err = utils.SetJSONData(articlesCacheKey, cacheData, time.Hour*24)
|
||||||
|
@ -382,3 +335,39 @@ func (s *articleService) UpdateArticle(id string, request dto.RequestArticleDTO,
|
||||||
|
|
||||||
return articleResponseDTO, nil
|
return articleResponseDTO, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *articleService) saveCoverImage(coverImage *multipart.FileHeader) (string, error) {
|
||||||
|
coverImageDir := "./public/uploads/articles"
|
||||||
|
if _, err := os.Stat(coverImageDir); os.IsNotExist(err) {
|
||||||
|
if err := os.MkdirAll(coverImageDir, os.ModePerm); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create directory for cover image: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension := filepath.Ext(coverImage.Filename)
|
||||||
|
if extension != ".jpg" && extension != ".jpeg" && extension != ".png" {
|
||||||
|
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
coverImageFileName := fmt.Sprintf("%s_cover%s", uuid.New().String(), extension)
|
||||||
|
coverImagePath := filepath.Join(coverImageDir, coverImageFileName)
|
||||||
|
|
||||||
|
src, err := coverImage.Open()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
dst, err := os.Create(coverImagePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create cover image file: %v", err)
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
_, err = dst.ReadFrom(src)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to save cover image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return coverImagePath, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue