Skip to main content

Create a consumer

One of the primary use cases for gosoline is to create a message queue consumer. In this tutorial, you'll do just that!

To build a consumer of async message queues you'll' implement the ConsumerCallback interface of the stream package.

Before you begin​

Before you begin, make sure you have Golang installed on your machine.

Set up your file structure​

First, you need to set up the following file structure:

consumer/
├── consumer.go
├── main.go
├── events.json
└── config.dist.yml

For example, in Unix, run:

mkdir consumer; cd consumer
touch consumer.go
touch main.go
touch events.json
touch config.dist.yml

Those are all the files you need to build your first consumer with gosoline! Next, you'll implement each of these files, starting with consumer.go.

Implement consumer.go​

In consumer.go, add the following code:

consumer.go
package main

import (
"context"

"github.com/justtrackio/gosoline/pkg/cfg"
"github.com/justtrackio/gosoline/pkg/log"
"github.com/justtrackio/gosoline/pkg/stream"
)

type Input struct {
Id string `json:"id"`
Body string `json:"body"`
}

type Consumer struct {
logger log.Logger
}

func NewConsumer(ctx context.Context, config cfg.Config, logger log.Logger) (stream.ConsumerCallback[Input], error) {
return &Consumer{
logger: logger,
}, nil
}

func (c Consumer) Consume(ctx context.Context, input Input, attributes map[string]string) (bool, error) {
c.logger.Info(ctx, "got input with id %q and body %q", input.Id, input.Body)

return true, nil
}

Now, you'll walkthrough this file in detail to learn how it works.

Import dependencies​

At the top of consumer.go, you declared the package and imported some dependencies:

package main

import (
"context"

"github.com/justtrackio/gosoline/pkg/cfg"
"github.com/justtrackio/gosoline/pkg/log"
"github.com/justtrackio/gosoline/pkg/stream"
)

Here, you declared the package as main. Then, you imported the context module along with three gosoline dependencies:

Implement your data structs​

Then, you created an Input struct and a Consumer struct:

// 1
type Input struct {
Id string `json:"id"`
Body string `json:"body"`
}

// 2
type Consumer struct {
logger log.Logger
}

You'll use these to:

  1. Bind data from the message queue. Note that you read an id and body from Json keys.
  2. Store logger information about your consumer.

Implement Consumer methods​

Next, you implemented some methods for the Consumer:

// 1
func NewConsumer(ctx context.Context, config cfg.Config, logger log.Logger) (stream.ConsumerCallback[Input], error) {
return &Consumer{
logger: logger,
}, nil
}

// 2
func (c Consumer) Consume(ctx context.Context, input Input, attributes map[string]string) (bool, error) {
c.logger.Info(ctx, "got input with id %q and body %q", input.Id, input.Body)

return true, nil
}

Here, you implemented:

  1. A constructor for creating new Consumer objects. It matches stream.ConsumerCallbackFactory[Input] and is used to add the callback to your application.
  2. Consume(), which receives the decoded Input, logs the data, and returns true because it successfully handled the message. This is called for every incoming message. Typed callbacks do not need GetModel; Gosoline derives the model from Input.

The Consume method implements stream.ConsumerCallback[Input].

Implement main.go​

In main.go, add the following code:

main.go
package main

import "github.com/justtrackio/gosoline/pkg/application"

func main() {
application.RunConsumer(NewConsumer,
application.WithConfigFile("config.dist.yml", "yml"),
)
}

Here, you execute your consumer. RunConsumer() accepts a stream.ConsumerCallbackFactory[Input] to create and run the consumer. The model type is inferred from NewConsumer.

Configure your consumer​

In config.dist.yml, configure your server:

config.dist.yml
app:
env: dev
name: consumer
namespace: "{app.tags.project}.{app.env}.{app.tags.family}.{app.tags.group}"
tags:
project: gosoline
family: how-to
group: grp

stream:
input:
consumer:
type: file
filename: events.json

Here, you set some minimal configurations for your web server. By default, the gosoline expects that there is an input configured with the config key stream.input.consumer. This defines the input source. In this tutorial, you'll use a file as source with the configured filename, "events.json".

Add your data​

In events.json, add some mock events stream data:

{"body": "{\"id\": \"1a0a960f-f04f-4c41-9b9a-a5ca0e2637b2\", \"body\": \"Lorem ipsum dolor sit amet.\"}"}

Now, the final step is to test it to confirm that it works as expected.

Test your consumer​

In the consumer directory, run:

go mod init consumer/m
go mod tidy
go run .

In the output, you'll see a log that indicates your consumer handled the event data:

10:23:57.648 consumerCallback info got input with id "1a0a960f-f04f-4c41-9b9a-a5ca0e2637b2" and body "Lorem ipsum dolor sit amet." application: consumer

Conclusion​

That's it! You created your first gosoline message queue consumer.