This commit is contained in:
67
.drone.yml
67
.drone.yml
@@ -1,67 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: static_check
|
|
||||||
image: golang:latest
|
|
||||||
commands:
|
|
||||||
- go install honnef.co/go/tools/cmd/staticcheck@latest
|
|
||||||
- cd src && staticcheck ./...
|
|
||||||
volumes:
|
|
||||||
- name: gopath
|
|
||||||
path: /go
|
|
||||||
|
|
||||||
- name: lint
|
|
||||||
image: golang:latest
|
|
||||||
commands:
|
|
||||||
- go install golang.org/x/lint/golint@latest
|
|
||||||
- golint ./src/...
|
|
||||||
volumes:
|
|
||||||
- name: gopath
|
|
||||||
path: /go
|
|
||||||
|
|
||||||
- name: analyze
|
|
||||||
image: golang:latest
|
|
||||||
commands:
|
|
||||||
- cd src && go vet ./...
|
|
||||||
volumes:
|
|
||||||
- name: gopath
|
|
||||||
path: /go
|
|
||||||
|
|
||||||
- name: publish_image
|
|
||||||
image: plugins/docker
|
|
||||||
environment:
|
|
||||||
DOCKER_USERNAME:
|
|
||||||
from_secret: registry_username
|
|
||||||
DOCKER_PASSWORD:
|
|
||||||
from_secret: registry_password
|
|
||||||
commands:
|
|
||||||
- sleep 5
|
|
||||||
- ./deploy/image-build.sh
|
|
||||||
- ./deploy/image-push.sh
|
|
||||||
volumes:
|
|
||||||
- name: docker-sock
|
|
||||||
path: /var/run
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- main
|
|
||||||
|
|
||||||
services:
|
|
||||||
- name: docker
|
|
||||||
image: docker:dind
|
|
||||||
privileged: true
|
|
||||||
volumes:
|
|
||||||
- name: docker-sock
|
|
||||||
path: /var/run
|
|
||||||
- name: etc_hosts
|
|
||||||
path: /etc/hosts
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- name: gopath
|
|
||||||
temp: {}
|
|
||||||
- name: docker-sock
|
|
||||||
temp: {}
|
|
||||||
- name: etc_hosts
|
|
||||||
host:
|
|
||||||
path: /etc/hosts
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
deploy/.env
|
deploy/.env
|
||||||
!deploy/.env.dist
|
!deploy/.env.dist
|
||||||
deploy/.env.*
|
!deploy/.env.docker
|
||||||
|
deploy/.env.local
|
||||||
|
|
||||||
deploy/server
|
deploy/server
|
||||||
deploy/worker
|
deploy/worker
|
||||||
|
|||||||
131
.woodpecker/workflow.yaml
Normal file
131
.woodpecker/workflow.yaml
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
variables:
|
||||||
|
- &golang_image 'docker.io/golang:1.24'
|
||||||
|
- &buildx_plugin 'docker.io/woodpeckerci/plugin-docker-buildx:6.0.3'
|
||||||
|
- &platforms_release 'linux/amd64'
|
||||||
|
- &build_args 'CI_COMMIT_SHA=${CI_COMMIT_SHA},CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH},CI_COMMIT_TAG=${CI_COMMIT_TAG}'
|
||||||
|
- publish_logins: &publish_logins
|
||||||
|
- registry: git.ego.freeddns.org
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: [pull_request, tag]
|
||||||
|
- event: push
|
||||||
|
# branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||||
|
branch: develop
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: vendor
|
||||||
|
image: *golang_image
|
||||||
|
pull: true
|
||||||
|
commands:
|
||||||
|
- cd src/ && go mod vendor
|
||||||
|
- name: analyze
|
||||||
|
image: *golang_image
|
||||||
|
commands:
|
||||||
|
- cd src && go vet ./...
|
||||||
|
- name: static-check
|
||||||
|
image: *golang_image
|
||||||
|
commands:
|
||||||
|
- echo "Static Check"
|
||||||
|
- go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
- cd src && staticcheck ./...
|
||||||
|
- name: lint
|
||||||
|
image: *golang_image
|
||||||
|
commands:
|
||||||
|
- echo "Lint"
|
||||||
|
- go install golang.org/x/lint/golint@latest
|
||||||
|
- golint ./src/...
|
||||||
|
- name: build-image
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
depends_on:
|
||||||
|
- vendor
|
||||||
|
# commands:
|
||||||
|
# - docker build --rm -t egommerce-builder:catalog -f deploy/docker/Dockerfile.builder .
|
||||||
|
settings:
|
||||||
|
repo: git.ego.freeddns.org/egommerce/catalog-svc
|
||||||
|
tag: builder
|
||||||
|
dockerfile: deploy/docker/Dockerfile.builder
|
||||||
|
logins: *publish_logins
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- name: push-image
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
depends_on:
|
||||||
|
- build-image
|
||||||
|
settings:
|
||||||
|
repo: git.ego.freeddns.org/egommerce/catalog-svc
|
||||||
|
tag: dev
|
||||||
|
build_args:
|
||||||
|
BUILDER_IMAGE: git.ego.freeddns.org/egommerce/catalog-svc:builder
|
||||||
|
SVC_NAME: "catalog-svc"
|
||||||
|
SVC_VER: "1.0"
|
||||||
|
dockerfile: deploy/docker/Dockerfile.target
|
||||||
|
logins: *publish_logins
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
# steps:
|
||||||
|
# - name: static_check
|
||||||
|
# image: golang:latest
|
||||||
|
# commands:
|
||||||
|
# - go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
# - cd src && staticcheck ./...
|
||||||
|
# volumes:
|
||||||
|
# - name: gopath
|
||||||
|
# path: /go
|
||||||
|
|
||||||
|
# - name: lint
|
||||||
|
# image: golang:latest
|
||||||
|
# commands:
|
||||||
|
# - go install golang.org/x/lint/golint@latest
|
||||||
|
# - golint ./src/...
|
||||||
|
# volumes:
|
||||||
|
# - name: gopath
|
||||||
|
# path: /go
|
||||||
|
|
||||||
|
# - name: analyze
|
||||||
|
# image: golang:latest
|
||||||
|
# commands:
|
||||||
|
# - cd src && go vet ./...
|
||||||
|
# volumes:
|
||||||
|
# - name: gopath
|
||||||
|
# path: /go
|
||||||
|
|
||||||
|
# - name: publish_image
|
||||||
|
# image: plugins/docker
|
||||||
|
# environment:
|
||||||
|
# DOCKER_USERNAME:
|
||||||
|
# from_secret: registry_username
|
||||||
|
# DOCKER_PASSWORD:
|
||||||
|
# from_secret: registry_password
|
||||||
|
# commands:
|
||||||
|
# - sleep 5
|
||||||
|
# - ./deploy/image-build.sh
|
||||||
|
# - ./deploy/image-push.sh
|
||||||
|
# volumes:
|
||||||
|
# - name: docker-sock
|
||||||
|
# path: /var/run
|
||||||
|
# when:
|
||||||
|
# branch:
|
||||||
|
# - main
|
||||||
|
|
||||||
|
# services:
|
||||||
|
# - name: docker
|
||||||
|
# image: docker:dind
|
||||||
|
# privileged: true
|
||||||
|
# volumes:
|
||||||
|
# - name: docker-sock
|
||||||
|
# path: /var/run
|
||||||
|
# - name: etc_hosts
|
||||||
|
# path: /etc/hosts
|
||||||
|
|
||||||
|
# volumes:
|
||||||
|
# - name: gopath
|
||||||
|
# temp: {}
|
||||||
|
# - name: docker-sock
|
||||||
|
# temp: {}
|
||||||
|
# - name: etc_hosts
|
||||||
|
# host:
|
||||||
|
# path: /etc/hosts
|
||||||
8
Makefile
8
Makefile
@@ -2,16 +2,16 @@ DEPLOY_DIR := ./deploy
|
|||||||
SRC_DIR := ./src
|
SRC_DIR := ./src
|
||||||
|
|
||||||
build-image-dev:
|
build-image-dev:
|
||||||
- sh ${DEPLOY_DIR}/image-build.sh dev
|
- sh ${DEPLOY_DIR}/scripts/image-build.sh dev
|
||||||
|
|
||||||
build-image-prod:
|
build-image-prod:
|
||||||
- sh ${DEPLOY_DIR}/image-build.sh
|
- sh ${DEPLOY_DIR}/scripts/image-build.sh
|
||||||
|
|
||||||
push-image-dev:
|
push-image-dev:
|
||||||
- sh ${DEPLOY_DIR}/image-push.sh dev
|
- sh ${DEPLOY_DIR}/scripts/image-push.sh dev
|
||||||
|
|
||||||
push-image-prod:
|
push-image-prod:
|
||||||
- sh ${DEPLOY_DIR}/image-push.sh
|
- sh ${DEPLOY_DIR}/scripts/image-push.sh
|
||||||
|
|
||||||
build-local-scheduler:
|
build-local-scheduler:
|
||||||
- go build -C ${SRC_DIR} -o ../deploy/scheduler cmd/scheduler/main.go
|
- go build -C ${SRC_DIR} -o ../deploy/scheduler cmd/scheduler/main.go
|
||||||
|
|||||||
12
deploy/.env.dist
Normal file
12
deploy/.env.dist
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
SERVER_ADDR=:443
|
||||||
|
|
||||||
|
APP_NAME=catalog-svc
|
||||||
|
APP_DOMAIN=catalog.service.ego.io
|
||||||
|
|
||||||
|
API_DATABASE_URL=postgres://postgres:12345678@db-postgres:5432/egommerce
|
||||||
|
API_CACHE_ADDR=api-cache:6379
|
||||||
|
API_CACHE_USERNAME=default
|
||||||
|
API_CACHE_PASSWORD=12345678
|
||||||
|
API_MONGODB_URL=mongodb://mongodb:12345678@mongo-db:27017
|
||||||
|
API_EVENTBUS_URL=amqp://guest:guest@api-eventbus:5672
|
||||||
|
|
||||||
13
deploy/.env.docker
Normal file
13
deploy/.env.docker
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
SERVER_ADDR=:443
|
||||||
|
|
||||||
|
APP_NAME=catalog-svc
|
||||||
|
APP_DOMAIN=catalog.service.ego.io
|
||||||
|
|
||||||
|
API_LOGGER_ADDR=api-logger:24224
|
||||||
|
API_DATABASE_URL=postgres://postgres:12345678@db-postgres:5432/egommerce
|
||||||
|
API_CACHE_ADDR=api-cache:6379
|
||||||
|
API_CACHE_USERNAME=default
|
||||||
|
API_CACHE_PASSWORD=12345678
|
||||||
|
API_MONGODB_URL=mongodb://mongodb:12345678@mongo-db:27017
|
||||||
|
API_EVENTBUS_URL=amqp://guest:guest@api-eventbus:5672
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ TARGET=${1:-latest}
|
|||||||
[ ! -d "src/vendor" ] && sh -c "cd src; go mod vendor"
|
[ ! -d "src/vendor" ] && sh -c "cd src; go mod vendor"
|
||||||
|
|
||||||
echo "Building target $IMAGE_PREFIX images..."
|
echo "Building target $IMAGE_PREFIX images..."
|
||||||
docker build --rm -t "$BUILDER_IMAGE" -f Dockerfile.builder .
|
docker build --rm -t "$BUILDER_IMAGE" -f deploy/docker/Dockerfile.builder .
|
||||||
|
|
||||||
if [ $TARGET = "latest" ]
|
if [ $TARGET = "latest" ]
|
||||||
then
|
then
|
||||||
@@ -24,7 +24,7 @@ then
|
|||||||
--build-arg BUILD_TIME \
|
--build-arg BUILD_TIME \
|
||||||
--rm --cache-from $SERVER_IMAGE:$TARGET \
|
--rm --cache-from $SERVER_IMAGE:$TARGET \
|
||||||
-t $SERVER_IMAGE:$TARGET \
|
-t $SERVER_IMAGE:$TARGET \
|
||||||
-f Dockerfile.target . > /dev/null 2>&1 && echo "Successfully tagged $SERVER_IMAGE:$TARGET"
|
-f deploy/docker/Dockerfile.target . > /dev/null 2>&1 && echo "Successfully tagged $SERVER_IMAGE:$TARGET"
|
||||||
|
|
||||||
# WORKER - TODO REMOVE IN FUTURE - cause we copy worker binary to the server image
|
# WORKER - TODO REMOVE IN FUTURE - cause we copy worker binary to the server image
|
||||||
# docker build \
|
# docker build \
|
||||||
@@ -35,7 +35,7 @@ then
|
|||||||
# --build-arg BUILD_TIME \
|
# --build-arg BUILD_TIME \
|
||||||
# --rm --cache-from $WORKER_IMAGE:$TARGET \
|
# --rm --cache-from $WORKER_IMAGE:$TARGET \
|
||||||
# -t $WORKER_IMAGE:$TARGET \
|
# -t $WORKER_IMAGE:$TARGET \
|
||||||
# -f Dockerfile.target . >/dev/null 2>&1 && echo "Successfully tagged $WORKER_IMAGE:$TARGET"
|
# -f deploy/docker/Dockerfile.target . >/dev/null 2>&1 && echo "Successfully tagged $WORKER_IMAGE:$TARGET"
|
||||||
else
|
else
|
||||||
# DEV
|
# DEV
|
||||||
docker build \
|
docker build \
|
||||||
@@ -44,7 +44,7 @@ else
|
|||||||
--build-arg BUILDER_IMAGE=$BUILDER_IMAGE \
|
--build-arg BUILDER_IMAGE=$BUILDER_IMAGE \
|
||||||
--build-arg BUILD_TIME \
|
--build-arg BUILD_TIME \
|
||||||
--rm --no-cache -t $SERVER_IMAGE:$TARGET \
|
--rm --no-cache -t $SERVER_IMAGE:$TARGET \
|
||||||
-f Dockerfile.target . > /dev/null 2>&1 && echo "Successfully tagged $SERVER_IMAGE:$TARGET"
|
-f deploy/docker/Dockerfile.target . > /dev/null 2>&1 && echo "Successfully tagged $SERVER_IMAGE:$TARGET"
|
||||||
|
|
||||||
# WORKER
|
# WORKER
|
||||||
# docker build \
|
# docker build \
|
||||||
@@ -55,7 +55,7 @@ else
|
|||||||
# --build-arg BUILD_TIME \
|
# --build-arg BUILD_TIME \
|
||||||
# --rm --no-cache \
|
# --rm --no-cache \
|
||||||
# -t $WORKER_IMAGE:$TARGET \
|
# -t $WORKER_IMAGE:$TARGET \
|
||||||
# -f Dockerfile.target . >/dev/null 2>&1 && echo "Successfully tagged $WORKER_IMAGE:$TARGET"
|
# -f deploy/docker/Dockerfile.target . >/dev/null 2>&1 && echo "Successfully tagged $WORKER_IMAGE:$TARGET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Done."
|
echo "Done."
|
||||||
@@ -36,5 +36,5 @@ func (app *App) Shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) RegisterPlugin(plugin Plugin) {
|
func (app *App) RegisterPlugin(plugin Plugin) {
|
||||||
app.worker.addPlugin(plugin.name, plugin.fn)
|
app.worker.addPlugin(plugin.name, plugin.connect)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,6 @@ type (
|
|||||||
Start() error
|
Start() error
|
||||||
OnShutdown()
|
OnShutdown()
|
||||||
|
|
||||||
addPlugin(name string, fn PluginFn)
|
addPlugin(name string, fn PluginConnectFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin struct {
|
|
||||||
name string
|
|
||||||
fn PluginFn
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginFn func() any
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,15 +3,22 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
redis "github.com/go-redis/redis/v8"
|
redis "github.com/go-redis/redis/v8"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
db "github.com/jackc/pgx/v5/pgxpool"
|
|
||||||
amqp "github.com/rabbitmq/amqp091-go"
|
amqp "github.com/rabbitmq/amqp091-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Plugin struct {
|
||||||
|
name string
|
||||||
|
connect PluginConnectFn
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginConnectFn func() any // returns connection handle
|
||||||
|
)
|
||||||
|
|
||||||
type PluginManager struct {
|
type PluginManager struct {
|
||||||
plugins map[string]any
|
plugins map[string]any
|
||||||
}
|
}
|
||||||
@@ -22,68 +29,144 @@ func NewPluginManager() *PluginManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PluginManager) addPlugin(name string, fn PluginFn) {
|
func (pm *PluginManager) addPlugin(name string, fn PluginConnectFn) {
|
||||||
pm.plugins[name] = fn()
|
pm.plugins[name] = fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PluginManager) getCache() *redis.Client {
|
func (pm *PluginManager) GetCache() *redis.Client {
|
||||||
return (pm.plugins["cache"]).(*redis.Client)
|
return (pm.plugins["cache"]).(*redis.Client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PluginManager) getDatabase() *pgxpool.Pool {
|
func (pm *PluginManager) GetDatabase() *pgxpool.Pool {
|
||||||
return (pm.plugins["database"]).(*pgxpool.Pool)
|
return (pm.plugins["database"]).(*pgxpool.Pool)
|
||||||
}
|
}
|
||||||
func (pm *PluginManager) getEventbus() *amqp.Channel {
|
|
||||||
|
func (pm *PluginManager) GetEventbus() *amqp.Channel {
|
||||||
return (pm.plugins["eventbus"]).(*amqp.Channel)
|
return (pm.plugins["eventbus"]).(*amqp.Channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CachePlugin(cnf *Config) Plugin {
|
func CachePlugin(cnf *Config) Plugin {
|
||||||
|
// plugin := &Plugin{
|
||||||
|
// name: "cache",
|
||||||
|
// connectFn: func() any {},
|
||||||
|
// afterConnFn: func() any {},
|
||||||
|
// }
|
||||||
|
|
||||||
|
connectFn := func() *redis.Client {
|
||||||
|
log.Println("establishing api-cache connection...")
|
||||||
|
|
||||||
|
return redis.NewClient(&redis.Options{
|
||||||
|
Addr: cnf.CacheAddr,
|
||||||
|
Username: cnf.CacheUsername,
|
||||||
|
Password: cnf.CachePassword,
|
||||||
|
DB: 0, // TODO
|
||||||
|
DialTimeout: 100 * time.Millisecond, // TODO
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// checking if the connection is still alive and try to reconnect when it is not
|
||||||
|
go func(conn *redis.Client) {
|
||||||
|
tick := time.NewTicker(5 * time.Second) // is 5 seconds is not too much?
|
||||||
|
defer tick.Stop()
|
||||||
|
|
||||||
|
// for {
|
||||||
|
// select {
|
||||||
|
// case <-tick.C:
|
||||||
|
// if err := conn.Ping(context.Background()).Err(); err != nil {
|
||||||
|
// log.Println("lost connection with api-cache. Reconnecting...")
|
||||||
|
// conn = connectFn()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for range tick.C {
|
||||||
|
if err := conn.Ping(context.Background()).Err(); err != nil {
|
||||||
|
log.Println("lost connection with api-cache. Reconnecting...")
|
||||||
|
conn = connectFn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(connectFn())
|
||||||
|
|
||||||
return Plugin{
|
return Plugin{
|
||||||
name: "cache",
|
name: "cache",
|
||||||
fn: func() any {
|
connect: func() any {
|
||||||
return redis.NewClient(&redis.Options{
|
return connectFn()
|
||||||
Addr: cnf.CacheAddr,
|
|
||||||
Username: cnf.CacheUsername,
|
|
||||||
Password: cnf.CachePassword,
|
|
||||||
DB: 0, // TODO
|
|
||||||
DialTimeout: 100 * time.Millisecond, // TODO
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DatabasePlugin(cnf *Config) Plugin {
|
func DatabasePlugin(cnf *Config) Plugin {
|
||||||
|
connectFn := func() *pgxpool.Pool {
|
||||||
|
log.Println("establishing db-postgres connection...")
|
||||||
|
|
||||||
|
conn, err := pgxpool.New(context.Background(), cnf.DbURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to connect to the database: %s. Err: %s\n", cnf.DbURL, err.Error())
|
||||||
|
return nil
|
||||||
|
// os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
// checking if the connection is still alive and try to reconnect when it is not
|
||||||
|
go func(conn *pgxpool.Pool) {
|
||||||
|
tick := time.NewTicker(5 * time.Second) // is 5 seconds is not too much?
|
||||||
|
defer tick.Stop()
|
||||||
|
|
||||||
|
for range tick.C {
|
||||||
|
if err := conn.Ping(context.Background()); err != nil {
|
||||||
|
log.Println("lost connection with db-postgres. Reconnecting...")
|
||||||
|
conn = connectFn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(connectFn())
|
||||||
|
|
||||||
return Plugin{
|
return Plugin{
|
||||||
name: "database",
|
name: "database",
|
||||||
fn: func() any {
|
connect: func() any {
|
||||||
dbConn, err := db.New(context.Background(), cnf.DbURL)
|
return connectFn()
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Database: %s. Err: %v\n", cnf.DbURL, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbConn
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func EventbusPlugin(cnf *Config) Plugin {
|
func EventbusPlugin(cnf *Config) Plugin {
|
||||||
|
connectFn := func() *amqp.Channel {
|
||||||
|
log.Println("establishing api-eventbus connection...")
|
||||||
|
|
||||||
|
conn, err := amqp.Dial(cnf.EventbusURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to connect to the eventbus: %s. Err: %v\n", cnf.EventbusURL, err.Error())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
chn, err := conn.Channel()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to open new eventbus channel. Err: %v\n", err.Error())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return chn
|
||||||
|
}
|
||||||
|
|
||||||
|
// checking if the connection is still alive and try to reconnect when it is not
|
||||||
|
go func(chn *amqp.Channel) {
|
||||||
|
tick := time.NewTicker(5 * time.Second) // is 5 seconds is not too much?
|
||||||
|
defer tick.Stop()
|
||||||
|
|
||||||
|
for range tick.C {
|
||||||
|
if closed := chn.IsClosed(); closed {
|
||||||
|
log.Println("lost connection with api-eventbus. Reconnecting...")
|
||||||
|
chn = connectFn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(connectFn())
|
||||||
|
|
||||||
return Plugin{
|
return Plugin{
|
||||||
name: "eventbus",
|
name: "eventbus",
|
||||||
fn: func() any {
|
connect: func() any {
|
||||||
conn, err := amqp.Dial(cnf.EventbusURL)
|
return connectFn()
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Eventbus: %s. Err: %v\n", cnf.EventbusURL, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
chn, err := conn.Channel()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to open new Eventbus channel. Err: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return chn
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ func (c *Scheduler) Start() error {
|
|||||||
func (c *Scheduler) OnShutdown() {
|
func (c *Scheduler) OnShutdown() {
|
||||||
log.Println("Scheduler is going down...")
|
log.Println("Scheduler is going down...")
|
||||||
|
|
||||||
c.getDatabase().Close()
|
c.GetDatabase().Close()
|
||||||
c.getCache().Close()
|
c.GetCache().Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (s *Server) addPlugin(name string, fn PluginFn) {
|
// func (s *Server) addPlugin(name string, fn PluginFn) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func (s *Server) Start() error {
|
|||||||
|
|
||||||
crt, err := tls.LoadX509KeyPair("certs/catalog-svc.crt", "certs/catalog-svc.key")
|
crt, err := tls.LoadX509KeyPair("certs/catalog-svc.crt", "certs/catalog-svc.key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal("failed to load certificates:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsCnf := &tls.Config{Certificates: []tls.Certificate{crt}}
|
tlsCnf := &tls.Config{Certificates: []tls.Certificate{crt}}
|
||||||
@@ -76,29 +76,13 @@ func (s *Server) Start() error {
|
|||||||
func (s *Server) OnShutdown() {
|
func (s *Server) OnShutdown() {
|
||||||
log.Printf("Server %s is going down...", s.ID)
|
log.Printf("Server %s is going down...", s.ID)
|
||||||
|
|
||||||
s.getDatabase().Close()
|
s.GetDatabase().Close()
|
||||||
s.getEventbus().Close()
|
s.GetEventbus().Close()
|
||||||
s.getCache().Close()
|
s.GetCache().Close()
|
||||||
|
|
||||||
s.Shutdown()
|
s.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (s *Server) addPlugin(name string, fn PluginFn) {
|
|
||||||
// s.plugins[name] = fn()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (s *Server) getCache() *redis.Client {
|
|
||||||
// return (s.plugins["cache"]).(*redis.Client)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (s *Server) getDatabase() *pgxpool.Pool {
|
|
||||||
// return (s.plugins["database"]).(*pgxpool.Pool)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (s *Server) getEventbus() *amqp.Channel {
|
|
||||||
// return (s.plugins["eventbus"]).(*amqp.Channel)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func GetRequestID(c *fiber.Ctx) (string, error) {
|
// func GetRequestID(c *fiber.Ctx) (string, error) {
|
||||||
// var hdr = new(HeaderRequestID)
|
// var hdr = new(HeaderRequestID)
|
||||||
// if err := c.ReqHeaderParser(hdr); err != nil {
|
// if err := c.ReqHeaderParser(hdr); err != nil {
|
||||||
@@ -112,11 +96,11 @@ func (s *Server) setupRouter() {
|
|||||||
s.Options("*", defaultCORS)
|
s.Options("*", defaultCORS)
|
||||||
s.Use(defaultCORS)
|
s.Use(defaultCORS)
|
||||||
|
|
||||||
s.Get("/health", http.HealthHandlerFn(s.getDatabase(), s.getEventbus(), s.getCache()))
|
s.Get("/health", http.HealthHandlerFn(s.GetDatabase(), s.GetEventbus(), s.GetCache()))
|
||||||
|
|
||||||
s.Group("/v1").
|
s.Group("/v1").
|
||||||
Get("/product", http.ListProductsHandlerFn(s.getDatabase())).
|
Get("/product", http.ListProductsHandlerFn(s.GetDatabase())).
|
||||||
Get("/product/:id", http.ShowProductHandlerFn(s.getDatabase()))
|
Get("/product/:id", http.ShowProductHandlerFn(s.GetDatabase()))
|
||||||
// Post("/product", http.AddProductHandlerFn(s.getDatabase(), s.getCache()))
|
// Post("/product", http.AddProductHandlerFn(s.getDatabase(), s.getCache()))
|
||||||
// Delete("/product", http.RemoveProductFromBasketHandlerFn(s.getDatabase(), s.getCache()))
|
// Delete("/product", http.RemoveProductFromBasketHandlerFn(s.getDatabase(), s.getCache()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,19 +28,28 @@ func NewWorker(c *Config) *Worker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bus *Worker) Start() error {
|
func (w *Worker) Start() error {
|
||||||
bus.consumeCommands(bus.getEventbus())
|
// fmt.Printf("eventbus: %#v", w.GetEventbus())
|
||||||
|
chn := w.GetEventbus()
|
||||||
|
// chn, err := conn.Channel()
|
||||||
|
// if err != nil {
|
||||||
|
// log.Println("failed to open eventbus channel: ", err.Error())
|
||||||
|
// }
|
||||||
|
|
||||||
|
if !chn.IsClosed() {
|
||||||
|
w.consumeCommands(chn)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bus *Worker) OnShutdown() {
|
func (w *Worker) OnShutdown() {
|
||||||
bus.getEventbus().Close()
|
w.GetEventbus().Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bus *Worker) consumeCommands(ch *amqp.Channel) error {
|
func (w *Worker) consumeCommands(ch *amqp.Channel) error {
|
||||||
msgs, err := ch.Consume(
|
msgs, err := ch.Consume(
|
||||||
bus.queueName,
|
w.queueName,
|
||||||
"",
|
"",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func main() {
|
|||||||
<-while
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to run scheduler. Reason: %v\n", err)
|
log.Fatalf("failed to run scheduler. Reason: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ func main() {
|
|||||||
<-while
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to start server. Reason: %v\n", err)
|
log.Fatalf("failed to start server. reason: %v\n", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|||||||
@@ -11,12 +11,11 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if cnf.ErrLoadingEnvs != nil {
|
if cnf.ErrLoadingEnvs != nil {
|
||||||
log.Fatalln("Error loading .env file.")
|
log.Fatalln("error loading .env file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
cnf := app.NewConfig("catalog-worker")
|
cnf := app.NewConfig("catalog-worker")
|
||||||
bus := app.NewWorker(cnf)
|
a := app.NewApp(app.NewWorker(cnf))
|
||||||
a := app.NewApp(bus)
|
|
||||||
a.RegisterPlugin(app.CachePlugin(cnf))
|
a.RegisterPlugin(app.CachePlugin(cnf))
|
||||||
a.RegisterPlugin(app.DatabasePlugin(cnf))
|
a.RegisterPlugin(app.DatabasePlugin(cnf))
|
||||||
a.RegisterPlugin(app.EventbusPlugin(cnf))
|
a.RegisterPlugin(app.EventbusPlugin(cnf))
|
||||||
@@ -26,7 +25,7 @@ func main() {
|
|||||||
<-while
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to start worker. Reason: %v\n", err)
|
log.Fatalf("failed to start worker. Reason: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
redis "github.com/go-redis/redis/v8"
|
redis "github.com/go-redis/redis/v8"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -18,15 +17,15 @@ func HealthHandlerFn(db *pgxpool.Pool, bus *amqp.Channel, cache *redis.Client) f
|
|||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
// Only 404 indicate service as not-healthy
|
// Only 404 indicate service as not-healthy
|
||||||
if err := db.Ping(context.Background()); err != nil {
|
if err := db.Ping(context.Background()); err != nil {
|
||||||
return c.SendStatus(http.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if closed := bus.IsClosed(); closed {
|
if closed := bus.IsClosed(); closed {
|
||||||
return c.SendStatus(http.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Ping(context.Background()).Err(); err != nil {
|
if err := cache.Ping(context.Background()).Err(); err != nil {
|
||||||
return c.SendStatus(http.StatusNotFound)
|
return c.SendStatus(fiber.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(&HealthResponse{
|
return c.JSON(&HealthResponse{
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func ListProductsHandlerFn(db *pgxpool.Pool) fiber.Handler {
|
|||||||
// if res.ProductID == 0 {
|
// if res.ProductID == 0 {
|
||||||
// return s.Error(c, fiber.StatusNotFound, fmt.Sprintf("Product #%d not exists", req.ProductID))
|
// return s.Error(c, fiber.StatusNotFound, fmt.Sprintf("Product #%d not exists", req.ProductID))
|
||||||
// }
|
// }
|
||||||
// return s.Error(c, fiber.StatusBadRequest, "Failed to add product to the basket")
|
// return s.Error(c, fiber.StatusBadRequest, "failed to add product to the basket")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// return c.JSON(res)
|
// return c.JSON(res)
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
// type AddProductActionUI struct {
|
||||||
"git.ego.freeddns.org/egommerce/catalog-service/internal/service"
|
// catalogSrv *service.CatalogService
|
||||||
)
|
// }
|
||||||
|
|
||||||
type AddProductActionUI struct {
|
|
||||||
catalogSrv *service.CatalogService
|
|
||||||
}
|
|
||||||
|
|
||||||
// func NewAddToBasketActionUI(catalogSrv *service.CatalogService) *AddProductActionUI {
|
// func NewAddToBasketActionUI(catalogSrv *service.CatalogService) *AddProductActionUI {
|
||||||
// return &AddProductActionUI{catalogSrv: catalogSrv}
|
// return &AddProductActionUI{catalogSrv: catalogSrv}
|
||||||
|
|||||||
Reference in New Issue
Block a user