Skip to content

Commit

Permalink
Merge pull request #74 from synapse-organization/locations/init-api
Browse files Browse the repository at this point in the history
feaat(loactions): Init api
  • Loading branch information
irania9O authored May 23, 2024
2 parents 4ef81ba + 8b394ec commit d47bf92
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 8 deletions.
53 changes: 53 additions & 0 deletions api/http/cafe_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,3 +653,56 @@ func (h Cafe) ReserveCafe(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
return
}

type RequestNearestCafes struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Radius float64 `json:"radius"`
}

func (h Cafe) GetNearestCafes(c *gin.Context) {
ctx, cancel := context.WithTimeout(c, TimeOut)
defer cancel()

var req RequestNearestCafes

err := c.ShouldBindJSON(&req)
if err != nil {
log.GetLog().WithError(err).Error("Unable to bind JSON")
c.JSON(http.StatusBadRequest, gin.H{"error": errors.ErrBadRequest.Error().Error()})
return
}

cafes, err := h.Handler.GetNearestCafes(ctx, req.Latitude, req.Longitude, req.Radius)
if err != nil {
log.GetLog().Errorf("Unable to get nearest cafes. error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"cafes": cafes})

}

func (h Cafe) SetCafeLocation(c *gin.Context) {
ctx, cancel := context.WithTimeout(c, TimeOut)
defer cancel()

var req models.Location

err := c.ShouldBindJSON(&req)
if err != nil {
log.GetLog().WithError(err).Error("Unable to bind JSON")
c.JSON(http.StatusBadRequest, gin.H{"error": errors.ErrBadRequest.Error().Error()})
return
}

err = h.Handler.SetCafeLocation(ctx, &req)
if err != nil {
log.GetLog().Errorf("Unable to set cafe location. error: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"status": "ok"})
}
14 changes: 14 additions & 0 deletions deploy/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ services:
resources:
limits:
memory: 200M
redis:
image: redis
environment:
- ALLOW_EMPTY_PASSWORD=yes
ports:
- 6379:6379
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
resources:
limits:
memory: 400M
postgres_backend:
image: postgres:alpine3.19
volumes:
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
github.com/jackc/pgx/v5 v5.5.5
github.com/redis/go-redis/v9 v9.5.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cast v1.6.0
github.com/stretchr/testify v1.9.0
Expand All @@ -17,9 +18,11 @@ require (

require (
github.com/bytedance/sonic v1.11.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
Expand All @@ -29,7 +32,6 @@ require (
github.com/golang/snappy v0.0.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgx v3.6.2+incompatible // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.13.6 // indirect
Expand All @@ -40,7 +42,6 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
Expand Down
14 changes: 10 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA=
github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
Expand All @@ -12,6 +18,8 @@ github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
Expand Down Expand Up @@ -43,8 +51,6 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
Expand Down Expand Up @@ -74,10 +80,10 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6f
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
Expand Down
21 changes: 21 additions & 0 deletions internal/modules/cafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"barista/pkg/utils"
"context"
"fmt"
"github.com/redis/go-redis/v9"
"math/rand"
"strconv"
"time"
Expand All @@ -27,6 +28,8 @@ type CafeHandler struct {
ReservationRepo repo.ReservationRepo
MenuItemRepo repo.MenuItemsRepo
PaymentRepo repo.Transaction
LocationsRepo repo.LocationsRepo
Redis *redis.Client
}

func (c CafeHandler) Create(ctx context.Context, cafe *models.Cafe) error {
Expand Down Expand Up @@ -945,3 +948,21 @@ func (c CafeHandler) ReserveCafe(ctx context.Context, reservation *models.Reserv

return nil
}

func (c CafeHandler) GetNearestCafes(ctx context.Context, lat float64, long float64, radius float64) ([]redis.GeoLocation, error) {

return c.Redis.GeoRadius(ctx, "locations", lat, long, &redis.GeoRadiusQuery{
Radius: radius,
Unit: "km",
WithCoord: true,
WithDist: true,
WithGeoHash: true,
Count: 5,
Sort: "ASC",
}).Result()

}

func (c CafeHandler) SetCafeLocation(ctx context.Context, m *models.Location) error {
return c.LocationsRepo.SetLocation(ctx, m)
}
69 changes: 67 additions & 2 deletions internal/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ package internal
import (
"barista/api/http"
"barista/internal/modules"
"barista/pkg/log"
"barista/pkg/middlewares"
"barista/pkg/models"
"barista/pkg/repo"
"barista/pkg/utils"
"context"
"github.com/redis/go-redis/v9"
"github.com/spf13/cast"
"go.mongodb.org/mongo-driver/mongo/options"
"os"
"time"
)

func getPostgres() (string, int) {
Expand Down Expand Up @@ -40,6 +44,20 @@ func getMongo() (string, int) {
return address, cast.ToInt(port)
}

func getRedis() (string, int) {
address, ok := os.LookupEnv("redis_address")
if !ok {
return "localhost", 6379
}

port, ok := os.LookupEnv("redis_port")
if !ok {
return "localhost", 6379
}

return address, cast.ToInt(port)
}

func Run() {
address, port := getPostgres()
postgres := utils.NewPostgres(
Expand All @@ -63,6 +81,13 @@ func Run() {
)
mongoDbOpt := options.GridFSBucket().SetName("image-server")

address, port = getRedis()
rdb := redis.NewClient(&redis.Options{
Addr: address + ":" + cast.ToString(port),
Password: "", // no password set
DB: 0, // use default DB
})

authMiddleware := middlewares.AuthMiddleware{Postgres: postgres}

service := StartService()
Expand Down Expand Up @@ -93,10 +118,48 @@ func Run() {
eventRepo := repo.NewEventRepoImp(postgres)
reservationRepo := repo.NewReservationRepoImp(postgres)
menuItemRepo := repo.NewMenuItemRepoImp(postgres)

cafeHandler := modules.CafeHandler{CafeRepo: cafeRepo, Rating: ratingRepo, CommentRepo: commentRepo, ImageRepo: imageRepo, EventRepo: eventRepo, UserRepo: userRepo, ReservationRepo: reservationRepo, MenuItemRepo: menuItemRepo, PaymentRepo: paymentRepo}
locationRepo := repo.NewLocationsRepoImp(postgres)

cafeHandler := modules.CafeHandler{
CafeRepo: cafeRepo,
Rating: ratingRepo,
CommentRepo: commentRepo,
ImageRepo: imageRepo,
EventRepo: eventRepo,
UserRepo: userRepo,
ReservationRepo: reservationRepo,
MenuItemRepo: menuItemRepo,
PaymentRepo: paymentRepo,
Redis: rdb,
}
cafeHttpHandler := http.Cafe{Handler: &cafeHandler}

newTicker := time.NewTicker(1 * time.Minute)
go func() {
for {
select {
case <-newTicker.C:
if err := rdb.FlushDB(context.Background()).Err(); err != nil {
log.GetLog().Errorf("Unable to flush redis db. error: %v", err)
}
locations, err := locationRepo.FindAll(context.Background())
if err != nil {
log.GetLog().Errorf("Unable to get locations. error: %v", err)
}

for _, location := range locations {
if err := rdb.GeoAdd(context.Background(), "locations", &redis.GeoLocation{
Name: cast.ToString(location.CafeID),
Longitude: location.Lng,
Latitude: location.Lat,
}).Err(); err != nil {
log.GetLog().Errorf("Unable to add location to redis. error: %v", err)
}
}
}
}
}()

cafe := apiV1.Group("/cafe")
cafe.Handle(string(models.POST), "create", authMiddleware.IsAuthorized, cafeHttpHandler.Create)
cafe.Handle(string(models.POST), "search-cafe", cafeHttpHandler.SearchCafe)
Expand All @@ -117,6 +180,8 @@ func Run() {
cafe.Handle(string(models.GET), "fully-booked-days", cafeHttpHandler.GetFullyBookedDays)
cafe.Handle(string(models.GET), "time-slots", cafeHttpHandler.GetTimeSlots)
cafe.Handle(string(models.POST), "reserve-cafe", authMiddleware.IsAuthorized, cafeHttpHandler.ReserveCafe)
cafe.Handle(string(models.GET), "get-nearest-cafes", cafeHttpHandler.GetNearestCafes)
cafe.Handle(string(models.GET), "set-location", cafeHttpHandler.SetCafeLocation)

imageHandler := http.ImageHandler{MongoDb: mongoDb, MongoOpt: mongoDbOpt, ImageRepo: imageRepo}
image := apiV1.Group("/image")
Expand Down
7 changes: 7 additions & 0 deletions pkg/models/locations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package models

type Location struct {
CafeID int32 `json:"cafe_id"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
56 changes: 56 additions & 0 deletions pkg/repo/lcoations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package repo

import (
"barista/pkg/log"
"barista/pkg/models"
"context"
"github.com/jackc/pgx/v5/pgxpool"
)

type LocationsRepo interface {
SetLocation(ctx context.Context, location *models.Location) error
FindAll(ctx context.Context) ([]*models.Location, error)
}

type LocationsRepoImp struct {
postgres *pgxpool.Pool
}

func NewLocationsRepoImp(postgres *pgxpool.Pool) *LocationsRepoImp {
_, err := postgres.Exec(context.Background(),
`CREATE TABLE IF NOT EXISTS locations (
id BIGINT PRIMARY KEY,
latitude FLOAT,
longitude FLOAT
);`)
if err != nil {
log.GetLog().WithError(err).WithField("table", "locations").Fatal("Unable to create table")
}
return &LocationsRepoImp{postgres: postgres}
}

func (r *LocationsRepoImp) SetLocation(ctx context.Context, location *models.Location) error {
_, err := r.postgres.Exec(ctx, "INSERT INTO locations (id, latitude, longitude) VALUES ($1, $2, $3) ON CONFLICT (id) DO UPDATE SET latitude = $2, longitude = $3", location.CafeID, location.Lat, location.Lng)
if err != nil {
log.GetLog().Errorf("Unable to insert location. error: %v", err)
}
return err
}

func (r *LocationsRepoImp) FindAll(ctx context.Context) ([]*models.Location, error) {
var locations []*models.Location
rows, err := r.postgres.Query(ctx, "SELECT id, latitude, longitude FROM locations")
if err != nil {
log.GetLog().Errorf("Unable to get locations. error: %v", err)
}
for rows.Next() {
var location models.Location
err := rows.Scan(&location.CafeID, &location.Lat, &location.Lng)
if err != nil {
log.GetLog().Errorf("Unable to scan location. error: %v", err)
continue
}
locations = append(locations, &location)
}
return locations, err
}

0 comments on commit d47bf92

Please sign in to comment.