|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This document provides guidance for AI coding assistants working with the RabbitMQ AMQP 1.0 Go Client library. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a Go client library for RabbitMQ 4.x that provides a wrapper around the Azure `go-amqp` client. The library simplifies working with AMQP 1.0 protocol in RabbitMQ, providing high-level abstractions for common operations like publishing, consuming, RPC patterns, and queue management. |
| 8 | + |
| 9 | +## Key Dependencies |
| 10 | + |
| 11 | +- `github.com/Azure/go-amqp v1.5.1` - Core AMQP 1.0 implementation |
| 12 | +- `github.com/google/uuid` - UUID generation |
| 13 | +- `github.com/golang-jwt/jwt/v5` - JWT token handling (for OAuth2) |
| 14 | +- Testing: `github.com/onsi/ginkgo/v2` and `github.com/onsi/gomega` |
| 15 | + |
| 16 | +## Project Structure |
| 17 | + |
| 18 | +``` |
| 19 | +pkg/rabbitmqamqp/ # Main package with all client functionality |
| 20 | + - amqp_connection.go # Connection management |
| 21 | + - amqp_consumer.go # Consumer implementation |
| 22 | + - amqp_publisher.go # Publisher implementation |
| 23 | + - amqp_queue.go # Queue operations |
| 24 | + - amqp_exchange.go # Exchange operations |
| 25 | + - amqp_management.go # Management API operations |
| 26 | + - requester.go # RPC requester (client side) |
| 27 | + - responder.go # RPC responder (server side) |
| 28 | + - entities.go # Queue specifications and types |
| 29 | + - amqp_types.go # Type aliases and interfaces |
| 30 | + - common.go # Shared utilities and constants |
| 31 | + - converters.go # Message conversion utilities |
| 32 | + - address.go # Address parsing |
| 33 | + - uri.go # URI handling |
| 34 | + - websocket_dialer.go # WebSocket support |
| 35 | + - log.go # Logging utilities |
| 36 | + - life_cycle.go # Lifecycle management |
| 37 | + - *_test.go # Test files |
| 38 | +
|
| 39 | +docs/examples/ # Example code demonstrating usage |
| 40 | +``` |
| 41 | + |
| 42 | +## Core Interfaces and Types |
| 43 | + |
| 44 | +### Main Client Interfaces |
| 45 | + |
| 46 | +- **`AmqpEnvironment`** - Main entry point for creating connections, publishers, consumers |
| 47 | +- **`AmqpConnection`** - Represents an AMQP connection |
| 48 | +- **`AmqpPublisher`** - Interface for publishing messages |
| 49 | +- **`AmqpConsumer`** - Interface for consuming messages |
| 50 | +- **`Requester`** - Interface for RPC client operations (formerly RpcClient) |
| 51 | +- **`Responder`** - Interface for RPC server operations (formerly RpcServer) |
| 52 | +- **`AmqpQueue`** - Interface for queue management operations |
| 53 | +- **`AmqpExchange`** - Interface for exchange operations |
| 54 | +- **`AmqpManagement`** - Interface for management API operations |
| 55 | + |
| 56 | +### Queue Types |
| 57 | + |
| 58 | +- `Quorum` - Quorum queue type |
| 59 | +- `Classic` - Classic queue type |
| 60 | +- `Stream` - Stream queue type |
| 61 | + |
| 62 | +### Consumer Options |
| 63 | + |
| 64 | +- **`IConsumerOptions`** - Interface for configuring consumers |
| 65 | + - `linkName()` - Link name (defaults to random UUID) |
| 66 | + - `initialCredits()` - Initial credits (defaults to 256) |
| 67 | + - `linkFilters()` - Link filters for stream consumers |
| 68 | + - `id()` - Consumer ID |
| 69 | + - `isDirectReplyToEnable()` - Enable direct reply-to for RPC |
| 70 | + |
| 71 | +### Queue Specifications |
| 72 | + |
| 73 | +- **`IQueueSpecification`** - Interface for queue specifications |
| 74 | +- **`QuorumQueueSpecification`** - Specification for quorum queues |
| 75 | +- **`ClassicQueueSpecification`** - Specification for classic queues |
| 76 | +- **`StreamQueueSpecification`** - Specification for stream queues |
| 77 | + |
| 78 | +## Code Conventions |
| 79 | + |
| 80 | +### Naming |
| 81 | + |
| 82 | +- Interfaces typically start with `I` (e.g., `IConsumerOptions`, `IQueueSpecification`) |
| 83 | +- Private methods use lowercase (e.g., `linkName()`, `initialCredits()`) |
| 84 | +- Public methods use PascalCase (e.g., `Close()`, `Publish()`) |
| 85 | +- Constants use camelCase (e.g., `linkPairName`, `managementNodeAddress`) |
| 86 | + |
| 87 | +### Error Handling |
| 88 | + |
| 89 | +- Functions return `error` as the last return value |
| 90 | +- Use descriptive error messages with context |
| 91 | +- Check for nil before dereferencing pointers |
| 92 | + |
| 93 | +### Context Usage |
| 94 | + |
| 95 | +- Most operations accept `context.Context` as the first parameter |
| 96 | +- Use context for cancellation and timeouts |
| 97 | +- Always pass context through the call chain |
| 98 | + |
| 99 | +### Logging |
| 100 | + |
| 101 | +- Use the logging functions from `log.go`: |
| 102 | + - `Info()`, `Error()`, `Debug()`, `Warn()` |
| 103 | +- Logging follows structured logging patterns with key-value pairs |
| 104 | + |
| 105 | +## Common Patterns |
| 106 | + |
| 107 | +### Creating a Connection |
| 108 | + |
| 109 | +```go |
| 110 | +env, err := rabbitmqamqp.NewAmqpEnvironment(ctx, rabbitmqamqp.NewAmqpEnvironmentOptions(). |
| 111 | + SetHost("localhost"). |
| 112 | + SetUser("guest"). |
| 113 | + SetPassword("guest")) |
| 114 | +``` |
| 115 | + |
| 116 | +### Publishing Messages |
| 117 | + |
| 118 | +```go |
| 119 | +publisher, err := connection.NewAmqpPublisher(ctx, rabbitmqamqp.NewAmqpPublisherOptions(). |
| 120 | + SetTarget("my-queue")) |
| 121 | + |
| 122 | +msg := &amqp.Message{ |
| 123 | + Body: []byte("Hello, RabbitMQ!"), |
| 124 | +} |
| 125 | +err = publisher.Publish(ctx, msg) |
| 126 | +``` |
| 127 | + |
| 128 | +### Consuming Messages |
| 129 | + |
| 130 | +```go |
| 131 | +consumer, err := connection.NewAmqpConsumer(ctx, rabbitmqamqp.NewAmqpConsumerOptions(). |
| 132 | + SetSource("my-queue"). |
| 133 | + SetInitialCredits(100)) |
| 134 | + |
| 135 | +msgChan := consumer.Receive(ctx) |
| 136 | +for msg := range msgChan { |
| 137 | + // Process message |
| 138 | + msg.Accept(ctx) |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +### RPC Pattern |
| 143 | + |
| 144 | +**Requester (Client):** |
| 145 | +```go |
| 146 | +requester, err := connection.NewRequester(ctx, rabbitmqamqp.NewRequesterOptions(). |
| 147 | + SetRequestQueue("rpc-queue")) |
| 148 | + |
| 149 | +msg := requester.Message([]byte("request")) |
| 150 | +replyChan, err := requester.Publish(ctx, msg) |
| 151 | +reply := <-replyChan |
| 152 | +``` |
| 153 | + |
| 154 | +**Responder (Server):** |
| 155 | +```go |
| 156 | +responder, err := connection.NewResponder(ctx, rabbitmqamqp.NewResponderOptions(). |
| 157 | + SetRequestQueue("rpc-queue")) |
| 158 | + |
| 159 | +msgChan := responder.Receive(ctx) |
| 160 | +for msg := range msgChan { |
| 161 | + // Process request and send reply |
| 162 | + responder.Send(ctx, msg, replyMsg) |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +## Testing |
| 167 | + |
| 168 | +- Tests use Ginkgo/Gomega framework |
| 169 | +- Test files follow the pattern `*_test.go` |
| 170 | +- Test utilities are in `test_utils.go` |
| 171 | +- Integration tests may require a running RabbitMQ instance |
| 172 | +- Use `make test` to run all tests |
| 173 | + |
| 174 | +## Important Constants |
| 175 | + |
| 176 | +- `AMQPS` - Protocol constant for AMQPS |
| 177 | +- `StreamFilterValue` - Header key for stream filtering |
| 178 | +- `commandReplyTo` - Direct reply-to address (`"$me"`) |
| 179 | +- `managementNodeAddress` - Management API address (`"/management"`) |
| 180 | +- `linkPairName` - Default management link name |
| 181 | + |
| 182 | +## Breaking Changes |
| 183 | + |
| 184 | +- In v0.4.0, `RpcClient` was renamed to `Requester` and `RpcServer` was renamed to `Responder` |
| 185 | +- Always check the CHANGELOG.md for breaking changes between versions |
| 186 | + |
| 187 | +## Common Tasks |
| 188 | + |
| 189 | +### Adding a New Feature |
| 190 | + |
| 191 | +1. Define interfaces if needed (following the `I` prefix convention) |
| 192 | +2. Implement the feature in the appropriate file |
| 193 | +3. Add tests in corresponding `*_test.go` file |
| 194 | +4. Update documentation if needed |
| 195 | +5. Add examples in `docs/examples/` if applicable |
| 196 | + |
| 197 | +### Modifying Existing Code |
| 198 | + |
| 199 | +1. Check for related tests and update them |
| 200 | +2. Ensure backward compatibility or document breaking changes |
| 201 | +3. Update CHANGELOG.md for user-facing changes |
| 202 | +4. Follow existing code patterns and conventions |
| 203 | + |
| 204 | +### Working with Azure go-amqp |
| 205 | + |
| 206 | +- This library wraps Azure's go-amqp client |
| 207 | +- Type aliases are defined in `amqp_types.go` (e.g., `DeliveryState`, `StateAccepted`) |
| 208 | +- When updating Azure dependency, check for breaking changes in their changelog |
| 209 | + |
| 210 | +## Resources |
| 211 | + |
| 212 | +- [RabbitMQ Client Libraries Documentation](https://www.rabbitmq.com/client-libraries/amqp-client-libraries) |
| 213 | +- [Examples Directory](docs/examples/) |
| 214 | +- [Azure go-amqp Repository](https://github.com/Azure/go-amqp) |
0 commit comments