feat: add redis control in artcle feature
This commit is contained in:
parent
ef95e3bfbe
commit
ef94470eda
|
@ -9,6 +9,6 @@ type Article struct {
|
|||
Author string `gorm:"not null" json:"author"`
|
||||
Heading string `gorm:"not null" json:"heading"`
|
||||
Content string `gorm:"not null" json:"content"`
|
||||
PublishedAt time.Time `gorm:"not null" json:"publishedAt"`
|
||||
UpdatedAt time.Time `gorm:"not null" json:"updatedAt"`
|
||||
PublishedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
||||
|
|
|
@ -13,13 +13,12 @@ func CreateArticle(c *fiber.Ctx) error {
|
|||
if err := c.BodyParser(&articleRequest); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input",
|
||||
"Input tidak valid",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := articleRequest.ValidatePostArticle(); err != nil {
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
|
@ -31,7 +30,7 @@ func CreateArticle(c *fiber.Ctx) error {
|
|||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create article",
|
||||
"Gagal membuat artikel",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
@ -52,7 +51,7 @@ func CreateArticle(c *fiber.Ctx) error {
|
|||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Article created successfully",
|
||||
"Artikel berhasil dibuat",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
@ -63,7 +62,7 @@ func GetArticles(c *fiber.Ctx) error {
|
|||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch articles",
|
||||
"Gagal mengambil artikel",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
@ -71,14 +70,13 @@ func GetArticles(c *fiber.Ctx) error {
|
|||
if len(articles) == 0 {
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Articles fetched successfully but data is empty",
|
||||
"Artikel berhasil diambil tetapi data kosong",
|
||||
[]dto.FormattedResponse{},
|
||||
))
|
||||
}
|
||||
|
||||
var formattedArticles []dto.FormattedResponse
|
||||
for _, article := range articles {
|
||||
|
||||
article.PublishedAtFormatted = utils.FormatDateToIndonesianFormat(article.PublishedAt)
|
||||
article.UpdatedAtFormatted = utils.FormatDateToIndonesianFormat(article.UpdatedAt)
|
||||
|
||||
|
@ -96,19 +94,20 @@ func GetArticles(c *fiber.Ctx) error {
|
|||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Articles fetched successfully",
|
||||
"Artikel berhasil diambil",
|
||||
formattedArticles,
|
||||
))
|
||||
}
|
||||
|
||||
func GetArticleByID(c *fiber.Ctx) error {
|
||||
|
||||
id := c.Params("id")
|
||||
|
||||
article, err := services.GetArticleByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Article not found",
|
||||
"Artikel tidak ditemukan",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
@ -129,7 +128,7 @@ func GetArticleByID(c *fiber.Ctx) error {
|
|||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Article fetched successfully",
|
||||
"Artikel berhasil diambil",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
@ -142,13 +141,12 @@ func UpdateArticle(c *fiber.Ctx) error {
|
|||
if err := c.BodyParser(&articleUpdateRequest); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input",
|
||||
"Input tidak valid",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := articleUpdateRequest.ValidateUpdateArticle(); err != nil {
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
|
@ -158,9 +156,17 @@ func UpdateArticle(c *fiber.Ctx) error {
|
|||
|
||||
updatedArticle, err := services.UpdateArticle(id, &articleUpdateRequest)
|
||||
if err != nil {
|
||||
|
||||
if err.Error() == "record not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"id article tidak diketahui",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update article",
|
||||
"Gagal memperbarui artikel",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
@ -181,7 +187,7 @@ func UpdateArticle(c *fiber.Ctx) error {
|
|||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Article updated successfully",
|
||||
"Artikel berhasil diperbarui",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
@ -191,16 +197,24 @@ func DeleteArticle(c *fiber.Ctx) error {
|
|||
|
||||
err := services.DeleteArticle(id)
|
||||
if err != nil {
|
||||
|
||||
if err.Error() == "record not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"id article tidak diketahui",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete article",
|
||||
"Gagal menghapus artikel",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Article deleted successfully",
|
||||
"Artikel berhasil dihapus",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,49 +1,87 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
func CreateArticle(article *domain.Article) error {
|
||||
err := config.DB.Create(article).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetArticles() ([]domain.Article, error) {
|
||||
var articles []domain.Article
|
||||
err := config.DB.Find(&articles).Error
|
||||
|
||||
cachedArticles, err := config.RedisClient.Get(ctx, "articles").Result()
|
||||
if err == nil {
|
||||
err := json.Unmarshal([]byte(cachedArticles), &articles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
err = config.DB.Find(&articles).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
articlesJSON, _ := json.Marshal(articles)
|
||||
config.RedisClient.Set(ctx, "articles", articlesJSON, 10*time.Minute)
|
||||
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
func GetArticleByID(id string) (domain.Article, error) {
|
||||
var article domain.Article
|
||||
err := config.DB.Where("id = ?", id).First(&article).Error
|
||||
|
||||
cachedArticle, err := config.RedisClient.Get(ctx, "article:"+id).Result()
|
||||
if err == nil {
|
||||
err := json.Unmarshal([]byte(cachedArticle), &article)
|
||||
if err != nil {
|
||||
return article, err
|
||||
}
|
||||
return article, nil
|
||||
}
|
||||
|
||||
err = config.DB.Where("id = ?", id).First(&article).Error
|
||||
if err != nil {
|
||||
return article, err
|
||||
}
|
||||
|
||||
articleJSON, _ := json.Marshal(article)
|
||||
config.RedisClient.Set(ctx, "article:"+id, articleJSON, 10*time.Minute)
|
||||
|
||||
return article, nil
|
||||
}
|
||||
|
||||
func UpdateArticle(article *domain.Article) error {
|
||||
|
||||
err := config.DB.Save(article).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.RedisClient.Del(ctx, "article:"+article.ID)
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteArticle(id string) error {
|
||||
|
||||
var article domain.Article
|
||||
|
||||
err := config.DB.Where("id = ?", id).First(&article).Error
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -53,5 +91,9 @@ func DeleteArticle(id string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.RedisClient.Del(ctx, "article:"+id)
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
func CreateArticle(articleRequest *dto.ArticleRequest) (dto.ArticleResponse, error) {
|
||||
article := domain.Article{
|
||||
Title: articleRequest.Title,
|
||||
|
@ -15,8 +20,6 @@ func CreateArticle(articleRequest *dto.ArticleRequest) (dto.ArticleResponse, err
|
|||
Author: articleRequest.Author,
|
||||
Heading: articleRequest.Heading,
|
||||
Content: articleRequest.Content,
|
||||
PublishedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
|
||||
err := repositories.CreateArticle(&article)
|
||||
|
@ -24,6 +27,8 @@ func CreateArticle(articleRequest *dto.ArticleRequest) (dto.ArticleResponse, err
|
|||
return dto.ArticleResponse{}, err
|
||||
}
|
||||
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
|
||||
articleResponse := dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
|
@ -39,12 +44,22 @@ func CreateArticle(articleRequest *dto.ArticleRequest) (dto.ArticleResponse, err
|
|||
}
|
||||
|
||||
func GetArticles() ([]dto.ArticleResponse, error) {
|
||||
var response []dto.ArticleResponse
|
||||
|
||||
cachedArticles, err := config.RedisClient.Get(ctx, "articles").Result()
|
||||
if err == nil {
|
||||
err := json.Unmarshal([]byte(cachedArticles), &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
articles, err := repositories.GetArticles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response []dto.ArticleResponse
|
||||
for _, article := range articles {
|
||||
response = append(response, dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
|
@ -57,15 +72,30 @@ func GetArticles() ([]dto.ArticleResponse, error) {
|
|||
UpdatedAt: article.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
articlesJSON, _ := json.Marshal(response)
|
||||
config.RedisClient.Set(ctx, "articles", articlesJSON, 10*time.Minute)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func GetArticleByID(id string) (dto.ArticleResponse, error) {
|
||||
cachedArticle, err := config.RedisClient.Get(ctx, "article:"+id).Result()
|
||||
if err == nil {
|
||||
var article dto.ArticleResponse
|
||||
err := json.Unmarshal([]byte(cachedArticle), &article)
|
||||
if err != nil {
|
||||
return article, err
|
||||
}
|
||||
return article, nil
|
||||
}
|
||||
|
||||
article, err := repositories.GetArticleByID(id)
|
||||
if err != nil {
|
||||
return dto.ArticleResponse{}, err
|
||||
}
|
||||
return dto.ArticleResponse{
|
||||
|
||||
articleResponse := dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
CoverImage: article.CoverImage,
|
||||
|
@ -74,7 +104,12 @@ func GetArticleByID(id string) (dto.ArticleResponse, error) {
|
|||
Content: article.Content,
|
||||
PublishedAt: article.PublishedAt,
|
||||
UpdatedAt: article.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
articleJSON, _ := json.Marshal(articleResponse)
|
||||
config.RedisClient.Set(ctx, "article:"+id, articleJSON, 10*time.Minute)
|
||||
|
||||
return articleResponse, nil
|
||||
}
|
||||
|
||||
func UpdateArticle(id string, articleUpdateRequest *dto.ArticleUpdateRequest) (*dto.ArticleResponse, error) {
|
||||
|
@ -96,7 +131,10 @@ func UpdateArticle(id string, articleUpdateRequest *dto.ArticleUpdateRequest) (*
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &dto.ArticleResponse{
|
||||
config.RedisClient.Del(ctx, "article:"+id)
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
|
||||
updatedArticleResponse := dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
CoverImage: article.CoverImage,
|
||||
|
@ -105,7 +143,9 @@ func UpdateArticle(id string, articleUpdateRequest *dto.ArticleUpdateRequest) (*
|
|||
Content: article.Content,
|
||||
PublishedAt: article.PublishedAt,
|
||||
UpdatedAt: article.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &updatedArticleResponse, nil
|
||||
}
|
||||
|
||||
func DeleteArticle(id string) error {
|
||||
|
@ -114,5 +154,9 @@ func DeleteArticle(id string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.RedisClient.Del(ctx, "article:"+id)
|
||||
config.RedisClient.Del(ctx, "articles")
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue