Skip to content

Commit

Permalink
Software Architecture in Go: Extensibility - Part 5
Browse files Browse the repository at this point in the history
Enable build tags and docker args to support Redis.

https://youtu.be/Wb24mcqNGD4
  • Loading branch information
MarioCarrion committed Feb 5, 2025
1 parent d84bd8f commit a3e35e0
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 10 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: 1.23.x
check-latest: true
cache: true
cache-dependency-path: |
**/go.sum
internal/tool/go.sum
internal/tools/go.sum
- name: Lint
run: make lint
- name: Make Docker images
Expand Down
2 changes: 0 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ linters-settings:
ignorePackageGlobs:
- github.com/MarioCarrion/todo-api/*
issues:
exclude:
- "NewMessageBrokerPublisher redeclared in this block" # build tags: `redis`, `rabbitmq` or `kafka`
exclude-rules:
# All tests
- path: _test\.go
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ test:
docker:
docker compose -f compose.yml -f compose.kafka.yml build
docker compose -f compose.yml -f compose.rabbitmq.yml build
docker compose -f compose.yml -f compose.redis.yml build
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ In no particular order:

## Running project locally using Docker Compose

Originally added as part of [Building Microservices In Go: Containerization with Docker](https://youtu.be/u_ayzie9pAQ), `docker compose` has evolved and with it the way to run everything locally. Make sure you are running a recent version of Docker Compose. The configuration in this repository and the instructions below are known to work:
Originally added as part of [Building Microservices In Go: Containerization with Docker](https://youtu.be/u_ayzie9pAQ), `docker compose` has evolved and with it the way to run everything locally. Make sure you are running a recent version of Docker Compose. The configuration in this repository and the instructions below are known to work for at least the following versions:

* Engine: **27.4.0**, and
* Compose: **v2.31.0-desktop.2**

This project takes advantage of [Go's build constrains](https://pkg.go.dev/go/build) and [Docker's arguments](https://docs.docker.com/reference/dockerfile/#arg) to build and run the [rest-server](cmd/rest-server) using any of the following types of message broker:
This project takes advantage of [Go's build constrains](https://pkg.go.dev/go/build) and [Docker's arguments](https://docs.docker.com/reference/dockerfile/#arg) to build the ElasticSearch indexers and to run the [rest-server](cmd/rest-server) using any of the following types of message broker:

* Redis (**default one**)
* RabbitMQ
* Kafka

Expand All @@ -138,22 +139,25 @@ docker compose -f compose.yml -f compose.<type>.yml <command>

Where:

* `<type>`: Indicates what message broker to use. Currently there are two supported values: `rabbitmq` and `kafka`; those effectively match the compose filename itself.
* `<type>`: Indicates what message broker to use, and effectively match the compose filename itself. The three supported values are:
1. `rabbitmq`,
1. `kafka`, and
1. `redis` (default value when building the `rest-server` binary).
* `<command>`: Indicates the docker compose command to use.

For example to build images using RabbitMQ as the message broker you would do:
For example to build images using RabbitMQ as the message broker you execute:

```
docker compose -f compose.yml -f compose.rabbitmq.yml build
```

Then to start the containers you would do:
Then to start the containers you execute:

```
docker compose -f compose.yml -f compose.rabbitmq.yml up
```

Once you `up` all the containers you can access the Swagger UI at http://127.0.0.1:9234/static/swagger-ui/ .
Once you all the containers are `up` you can access the Swagger UI at http://127.0.0.1:9234/static/swagger-ui/ .

## Diagrams

Expand Down
2 changes: 1 addition & 1 deletion cmd/rest-server/kafka.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !rabbitmq
//go:build kafka

package main

Expand Down
46 changes: 46 additions & 0 deletions cmd/rest-server/redis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build !kafka && !rabbitmq

package main

import (
"github.com/go-redis/redis/v8"

cmdinternal "github.com/MarioCarrion/todo-api/cmd/internal"
"github.com/MarioCarrion/todo-api/internal"
"github.com/MarioCarrion/todo-api/internal/envvar"
internalredis "github.com/MarioCarrion/todo-api/internal/redis"
"github.com/MarioCarrion/todo-api/internal/service"
)

// RedisMessageBroker represents Redis as a Message Broker.
type RedisMessageBroker struct {
client *redis.Client
publisher service.TaskMessageBrokerPublisher
}

// NewMessageBrokerPublisher initializes a new Redis Broker.
func NewMessageBrokerPublisher(conf *envvar.Configuration) (MessageBrokerPublisher, error) { //nolint: ireturn
producer, err := cmdinternal.NewRedis(conf)
if err != nil {
return nil, internal.WrapErrorf(err, internal.ErrorCodeUnknown, "internal.NewRedis")
}

return &RedisMessageBroker{
client: producer,
publisher: internalredis.NewTask(producer),
}, nil
}

// Publisher returns the Redis broker.
func (m *RedisMessageBroker) Publisher() service.TaskMessageBrokerPublisher { //nolint: ireturn
return m.publisher
}

// Close closes the broker.
func (m *RedisMessageBroker) Close() error {
if err := m.client.Close(); err != nil {
return internal.WrapErrorf(err, internal.ErrorCodeUnknown, "producer.Close")
}

return nil
}
33 changes: 33 additions & 0 deletions compose.redis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
services:
rest-server-redis:
extends:
file: compose.common.yml
service: rest-server-common
build:
args:
TAG: redis
environment:
REDIS_HOST: redis:6379
depends_on:
redis:
condition: service_healthy
elasticsearch-indexer-redis:
extends:
file: compose.common.yml
service: elasticsearch-indexer-common
build:
dockerfile: ./dockerfiles/elasticsearch-indexer-redis.Dockerfile
environment:
REDIS_HOST: redis:6379
depends_on:
redis:
condition: service_healthy
redis:
image: redis:7.0.9-alpine3.17
ports:
- 6379:6379
healthcheck:
test: ["CMD-SHELL", "redis-cli ping || exit 1"]
interval: 20s
timeout: 1s
retries: 5

0 comments on commit a3e35e0

Please sign in to comment.