Skip to content

Commit

Permalink
Add announcements feature supporting SSE flash news
Browse files Browse the repository at this point in the history
Implemented a new announcements feature to support server-sent events for delivering flash news. Created handler, service, and route logic along with JSON data structure for announcements. Updated the main API initialization to include the new announcements service.
  • Loading branch information
mukulmantosh committed Sep 19, 2024
1 parent 0de69ee commit ff53447
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 1 deletion.
5 changes: 5 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import (
"Go_Food_Delivery/cmd/api/middleware"
"Go_Food_Delivery/pkg/database"
"Go_Food_Delivery/pkg/handler"
"Go_Food_Delivery/pkg/handler/annoucements"
crt "Go_Food_Delivery/pkg/handler/cart"
delv "Go_Food_Delivery/pkg/handler/delivery"
notify "Go_Food_Delivery/pkg/handler/notification"
"Go_Food_Delivery/pkg/handler/restaurant"
revw "Go_Food_Delivery/pkg/handler/review"
"Go_Food_Delivery/pkg/handler/user"
"Go_Food_Delivery/pkg/nats"
"Go_Food_Delivery/pkg/service/announcements"
"Go_Food_Delivery/pkg/service/cart_order"
"Go_Food_Delivery/pkg/service/delivery"
"Go_Food_Delivery/pkg/service/notification"
Expand Down Expand Up @@ -81,6 +83,9 @@ func main() {
}
notify.NewNotifyHandler(s, "/notify", notifyService, middlewares, validate, wsClients)

// Events/Announcements
announceService := announcements.NewAnnouncementService(db, env)
annoucements.NewAnnouncementHandler(s, "/announcements", announceService, middlewares, validate)
log.Fatal(s.Run())

}
10 changes: 10 additions & 0 deletions pkg/abstract/announcements/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package announcements

type FlashEvents struct {
Headline string `json:"headline"`
Message string `json:"message"`
}

type Announcement interface {
FlashEvents() (*[]FlashEvents, error)
}
44 changes: 44 additions & 0 deletions pkg/handler/annoucements/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package annoucements

import (
"context"
"github.com/gin-gonic/gin"
"time"
)

func (s *AnnouncementHandler) flashNews(c *gin.Context) {
_, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
defer cancel()

events, err := s.service.FlashEvents()
if err != nil {
c.AbortWithStatusJSON(500, gin.H{"error": err.Error()})
return
}

// Set headers for SSE
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")

ticker := time.NewTicker(2 * time.Second) // Set up a ticker to tick every 2 seconds
defer ticker.Stop()

eventIndex := 0

for {
select {
case <-ticker.C:
// Send the current event
event := (*events)[eventIndex]
c.SSEvent("message", event.Message)
c.Writer.Flush()

// Move to the next event
eventIndex = (eventIndex + 1) % len(*events)
case <-c.Request.Context().Done():
return // Exit if the client disconnects
}
}

}
24 changes: 24 additions & 0 deletions pkg/handler/annoucements/routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package annoucements

import (
"github.com/gin-gonic/gin"
"net/http"
)

func (s *AnnouncementHandler) registerMiddlewareGroup(middleware ...gin.HandlerFunc) gin.IRoutes {
return s.serve.Gin.Group(s.group).Use(middleware...)
}

func (s *AnnouncementHandler) registerGroup() gin.IRoutes {
return s.serve.Gin.Group(s.group)
}

func (s *AnnouncementHandler) regularRoutes() http.Handler {
s.router.GET("/events", s.flashNews)

return s.serve.Gin
}

func (s *AnnouncementHandler) middlewareRoutes() http.Handler {
return s.serve.Gin
}
42 changes: 42 additions & 0 deletions pkg/handler/annoucements/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package annoucements

import (
"Go_Food_Delivery/pkg/handler"
"Go_Food_Delivery/pkg/service/announcements"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)

type AnnouncementHandler struct {
serve *handler.Server
group string
middlewareGuarded gin.IRoutes
router gin.IRoutes
service *announcements.AnnouncementService
middleware []gin.HandlerFunc
validate *validator.Validate
}

func NewAnnouncementHandler(s *handler.Server, group string,
service *announcements.AnnouncementService, middleware []gin.HandlerFunc,
validate *validator.Validate) {

cartHandler := &AnnouncementHandler{
s,
group,
nil,
nil,
service,
middleware,
validate,
}
cartHandler.middlewareGuarded = cartHandler.registerMiddlewareGroup(middleware...)
cartHandler.router = cartHandler.registerGroup()
cartHandler.regularRoutes()
cartHandler.middlewareRoutes()
cartHandler.registerValidator()
}

func (s *AnnouncementHandler) registerValidator() {

}
48 changes: 48 additions & 0 deletions pkg/service/announcements/announcement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package announcements

import (
"Go_Food_Delivery/pkg/abstract/announcements"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
)

func (eventSrv *AnnouncementService) FlashEvents() (*[]announcements.FlashEvents, error) {
currentDir, err := getCurrentDirectory()
if err != nil {
return nil, errors.New("unable to get current directory")
}
fileName := filepath.Join(currentDir, "events.json")

file, err := os.Open(fileName)
if err != nil {
log.Println("Error opening file:", err)
return nil, errors.New("unable to open file")
}
defer file.Close()

var newsEvents []announcements.FlashEvents
err = json.NewDecoder(file).Decode(&newsEvents)
if err != nil {
return nil, errors.New("unable to decode JSON")
}

return &newsEvents, nil
}

func getCurrentDirectory() (string, error) {
// Get the caller's information
_, currentFile, _, ok := runtime.Caller(1)
if !ok {
return "", fmt.Errorf("unable to get current file path")
}

// Get the directory from the current file path
currentDir := filepath.Dir(currentFile)

return currentDir, nil
}
126 changes: 126 additions & 0 deletions pkg/service/announcements/events.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
[
{
"headline": "New Local Flavors",
"message": "🚀 Introducing exclusive menu items from your favorite local restaurants! Discover new tastes every week!"
},
{
"headline": "Limited-Time Offers",
"message": "🎉 Get 20% off your next order! Use code TASTY20 at checkout. Offer valid until Sunday!"
},
{
"headline": "Sustainability Initiative",
"message": "🌍 We’re going green! Starting this month, all deliveries will feature eco-friendly packaging. Join us in making a difference!"
},
{
"headline": "New Partnerships",
"message": "🍔 We’ve partnered with [Local Restaurant Name]! Enjoy their delicious dishes delivered straight to your door!"
},
{
"headline": "Loyalty Program Launch",
"message": "🏆 Introducing our new loyalty program! Earn points for every order and redeem them for exclusive rewards!"
},
{
"headline": "Delivery Speed Upgrade",
"message": "⚡ We’ve optimized our delivery network! Expect your meals faster than ever—hot and fresh at your doorstep!"
},
{
"headline": "Customer Feedback Drive",
"message": "📝 We value your input! Participate in our survey for a chance to win a $50 gift card!"
},
{
"headline": "Meal Kits Now Available",
"message": "🍽️ Craving a cooking adventure? Try our new meal kits! Fresh ingredients delivered with easy-to-follow recipes!"
},
{
"headline": "New Cuisine Alert",
"message": "🥢 Explore the flavors of [Cuisine Name]! Now available for delivery—order today!"
},
{
"headline": "Weekend Specials",
"message": "🍕 Enjoy our weekend special! Buy one pizza, get one half off! Limited time only!"
},
{
"headline": "App Update",
"message": "📱 Check out our new app features! Easier navigation and faster checkout for a smoother experience!"
},
{
"headline": "Chef's Recommendation",
"message": "👨‍🍳 Try our chef's special this week! A must-taste dish from [Restaurant Name]!"
},
{
"headline": "Free Delivery Day",
"message": "🚚 This Thursday, enjoy FREE delivery on all orders over $30! Don’t miss out!"
},
{
"headline": "Seasonal Menu Launch",
"message": "🍂 Our fall menu is here! Discover seasonal dishes that celebrate the flavors of autumn!"
},
{
"headline": "Happy Hour Deals",
"message": "🍹 Join us for happy hour! Enjoy 50% off select drinks from 4 PM to 6 PM!"
},
{
"headline": "Referral Bonus",
"message": "👥 Refer a friend and both of you get $10 off your next order! Share the love!"
},
{
"headline": "Exclusive Chef Collaboration",
"message": "✨ We’re teaming up with [Famous Chef] for a limited-time menu! Don’t miss these exclusive dishes!"
},
{
"headline": "Healthy Choices",
"message": "🥗 Looking for something light? Check out our new range of healthy meal options!"
},
{
"headline": "Breakfast All Day",
"message": "🌞 Breakfast lovers rejoice! Enjoy breakfast items all day long, any day of the week!"
},
{
"headline": "Limited Edition Desserts",
"message": "🍰 Indulge in our limited-edition desserts available for this month only!"
},
{
"headline": "Community Support",
"message": "🤝 We're donating a portion of every order this month to local charities. Help us give back!"
},
{
"headline": "Curbside Pickup Now Available",
"message": "🚗 Order online and enjoy convenient curbside pickup at select locations!"
},
{
"headline": "New Payment Options",
"message": "💳 We now accept [Payment Method]! Enjoy more flexibility with your orders!"
},
{
"headline": "Food Truck Festival",
"message": "🎪 Join us for the upcoming food truck festival! Sample dishes from various local food trucks!"
},
{
"headline": "Customer Appreciation Week",
"message": "🎊 It’s customer appreciation week! Enjoy surprise discounts and giveaways all week long!"
},
{
"headline": "Online Cooking Classes",
"message": "👩‍🍳 Join our online cooking classes with professional chefs and learn to create your favorite dishes!"
},
{
"headline": "Flash Sales",
"message": "⚡ Don’t miss our flash sales! Follow us for exclusive 1-hour deals throughout the week!"
},
{
"headline": "Family Meal Bundles",
"message": "👨‍👩‍👧‍👦 Enjoy our family meal bundles! Perfect for sharing with loved ones at great prices!"
},
{
"headline": "Late Night Delivery",
"message": "🌙 Craving a midnight snack? We now offer late-night delivery on select items!"
},
{
"headline": "Global Flavors Series",
"message": "🌎 Dive into our Global Flavors series—each week featuring a different country’s cuisine!"
},
{
"headline": "New Dessert Line",
"message": "🍦 Satisfy your sweet tooth with our new dessert line! Available for delivery now!"
}
]
12 changes: 12 additions & 0 deletions pkg/service/announcements/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package announcements

import "Go_Food_Delivery/pkg/database"

type AnnouncementService struct {
db database.Database
env string
}

func NewAnnouncementService(db database.Database, env string) *AnnouncementService {
return &AnnouncementService{db, env}
}
2 changes: 1 addition & 1 deletion pkg/service/delivery/order_placement.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (deliverSrv *DeliveryService) OrderPlacement(ctx context.Context,
return false, err
}

// Add info. into the delivery table.
// Add info. Into the delivery table.
deliver := new(delivery.Deliveries)
deliver.DeliveryPersonID = deliveryPersonID
deliver.OrderID = orderID
Expand Down

0 comments on commit ff53447

Please sign in to comment.