Skip to content

Commit 60e006b

Browse files
authored
remove builders (#15)
* remove builders --------- Signed-off-by: Gabriele Santomaggio <[email protected]>
1 parent 5fc29f4 commit 60e006b

19 files changed

+680
-498
lines changed

examples/getting_started/main.go

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,87 @@
11
package main
22

33
import (
4-
"bufio"
54
"context"
65
"fmt"
7-
mq "github.com/rabbitmq/rabbitmq-amqp-go-client/rabbitmq_amqp"
8-
"os"
6+
"github.com/rabbitmq/rabbitmq-amqp-go-client/rabbitmq_amqp"
97
"time"
108
)
119

1210
func main() {
1311
fmt.Printf("Getting started with AMQP Go AMQP 1.0 Client\n")
14-
chStatusChanged := make(chan *mq.StatusChanged, 1)
12+
chStatusChanged := make(chan *rabbitmq_amqp.StatusChanged, 1)
1513

16-
go func(ch chan *mq.StatusChanged) {
14+
go func(ch chan *rabbitmq_amqp.StatusChanged) {
1715
for statusChanged := range ch {
18-
fmt.Printf("Status changed from %d to %d\n", statusChanged.From, statusChanged.To)
16+
fmt.Printf("%s\n", statusChanged)
1917
}
2018
}(chStatusChanged)
2119

22-
amqpConnection := mq.NewAmqpConnection()
23-
amqpConnection.NotifyStatusChange(chStatusChanged)
24-
err := amqpConnection.Open(context.Background(), mq.NewConnectionSettings())
20+
amqpConnection := rabbitmq_amqp.NewAmqpConnectionNotifyStatusChanged(chStatusChanged)
21+
err := amqpConnection.Open(context.Background(), rabbitmq_amqp.NewConnectionSettings())
2522
if err != nil {
23+
fmt.Printf("Error opening connection: %v\n", err)
2624
return
2725
}
28-
2926
fmt.Printf("AMQP Connection opened.\n")
3027
management := amqpConnection.Management()
31-
queueSpec := management.Queue("getting_started_queue").
32-
QueueType(mq.QueueType{Type: mq.Quorum}).
33-
MaxLengthBytes(mq.CapacityGB(1))
34-
exchangeSpec := management.Exchange("getting_started_exchange").
35-
ExchangeType(mq.ExchangeType{Type: mq.Topic})
36-
37-
queueInfo, err := queueSpec.Declare(context.Background())
28+
exchangeInfo, err := management.DeclareExchange(context.TODO(), &rabbitmq_amqp.ExchangeSpecification{
29+
Name: "getting-started-exchange",
30+
})
3831
if err != nil {
39-
fmt.Printf("Error declaring queue %s\n", err)
32+
fmt.Printf("Error declaring exchange: %v\n", err)
4033
return
4134
}
42-
fmt.Printf("Queue %s created.\n", queueInfo.GetName())
4335

44-
exchangeInfo, err := exchangeSpec.Declare(context.Background())
36+
queueInfo, err := management.DeclareQueue(context.TODO(), &rabbitmq_amqp.QueueSpecification{
37+
Name: "getting-started-queue",
38+
QueueType: rabbitmq_amqp.QueueType{Type: rabbitmq_amqp.Quorum},
39+
})
40+
4541
if err != nil {
46-
fmt.Printf("Error declaring exchange %s\n", err)
42+
fmt.Printf("Error declaring queue: %v\n", err)
4743
return
4844
}
49-
fmt.Printf("Exchange %s created.\n", exchangeInfo.GetName())
5045

51-
bindingSpec := management.Binding().SourceExchange(exchangeSpec).DestinationQueue(queueSpec).Key("routing-key")
46+
bindingPath, err := management.Bind(context.TODO(), &rabbitmq_amqp.BindingSpecification{
47+
SourceExchange: exchangeInfo.Name(),
48+
DestinationQueue: queueInfo.Name(),
49+
BindingKey: "routing-key",
50+
})
5251

53-
err = bindingSpec.Bind(context.Background())
5452
if err != nil {
55-
fmt.Printf("Error binding %s\n", err)
53+
fmt.Printf("Error binding: %v\n", err)
5654
return
5755
}
5856

59-
fmt.Printf("Binding between %s and %s created.\n", exchangeInfo.GetName(), queueInfo.GetName())
60-
61-
fmt.Println("Press any key to cleanup and exit")
62-
reader := bufio.NewReader(os.Stdin)
63-
_, _ = reader.ReadString('\n')
57+
err = management.Unbind(context.TODO(), bindingPath)
6458

65-
err = bindingSpec.Unbind(context.Background())
6659
if err != nil {
67-
fmt.Printf("Error unbinding %s\n", err)
60+
fmt.Printf("Error unbinding: %v\n", err)
6861
return
6962
}
7063

71-
fmt.Printf("Binding between %s and %s deleted.\n", exchangeInfo.GetName(), queueInfo.GetName())
72-
73-
err = exchangeSpec.Delete(context.Background())
64+
err = management.DeleteExchange(context.TODO(), exchangeInfo.Name())
7465
if err != nil {
75-
fmt.Printf("Error deleting exchange %s\n", err)
66+
fmt.Printf("Error deleting exchange: %v\n", err)
7667
return
7768
}
7869

79-
err = queueSpec.Delete(context.Background())
70+
err = management.DeleteQueue(context.TODO(), queueInfo.Name())
8071
if err != nil {
72+
fmt.Printf("Error deleting queue: %v\n", err)
8173
return
8274
}
83-
fmt.Printf("Queue %s deleted.\n", queueInfo.GetName())
8475

8576
err = amqpConnection.Close(context.Background())
8677
if err != nil {
78+
fmt.Printf("Error closing connection: %v\n", err)
8779
return
8880
}
81+
8982
fmt.Printf("AMQP Connection closed.\n")
9083
// Wait for the status change to be printed
9184
time.Sleep(500 * time.Millisecond)
85+
9286
close(chStatusChanged)
9387
}

rabbitmq_amqp/address_builder.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package rabbitmq_amqp
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"net/url"
7+
"strings"
8+
)
9+
10+
type AddressBuilder struct {
11+
queue *string
12+
exchange *string
13+
key *string
14+
append *string
15+
}
16+
17+
func NewAddressBuilder() *AddressBuilder {
18+
return &AddressBuilder{}
19+
}
20+
21+
func (a *AddressBuilder) Queue(queue string) *AddressBuilder {
22+
a.queue = &queue
23+
return a
24+
}
25+
26+
func (a *AddressBuilder) Exchange(exchange string) *AddressBuilder {
27+
a.exchange = &exchange
28+
return a
29+
}
30+
31+
func (a *AddressBuilder) Key(key string) *AddressBuilder {
32+
a.key = &key
33+
return a
34+
}
35+
36+
func (a *AddressBuilder) Append(append string) *AddressBuilder {
37+
a.append = &append
38+
return a
39+
}
40+
41+
func (a *AddressBuilder) Address() (string, error) {
42+
if a.exchange == nil && a.queue == nil {
43+
return "", errors.New("exchange or queue must be set")
44+
}
45+
46+
urlAppend := ""
47+
if !isStringNilOrEmpty(a.append) {
48+
urlAppend = *a.append
49+
}
50+
if !isStringNilOrEmpty(a.exchange) && !isStringNilOrEmpty(a.queue) {
51+
return "", errors.New("exchange and queue cannot be set together")
52+
}
53+
54+
if !isStringNilOrEmpty(a.exchange) {
55+
if !isStringNilOrEmpty(a.key) {
56+
return "/" + exchanges + "/" + encodePathSegments(*a.exchange) + "/" + encodePathSegments(*a.key) + urlAppend, nil
57+
}
58+
return "/" + exchanges + "/" + encodePathSegments(*a.exchange) + urlAppend, nil
59+
}
60+
61+
if a.queue == nil {
62+
return "", nil
63+
}
64+
65+
if isStringNilOrEmpty(a.queue) {
66+
return "", errors.New("queue must be set")
67+
}
68+
69+
return "/" + queues + "/" + encodePathSegments(*a.queue) + urlAppend, nil
70+
}
71+
72+
// encodePathSegments takes a string and returns its percent-encoded representation.
73+
func encodePathSegments(input string) string {
74+
var encoded strings.Builder
75+
76+
// Iterate over each character in the input string
77+
for _, char := range input {
78+
// Check if the character is an unreserved character (i.e., it doesn't need encoding)
79+
if isUnreserved(char) {
80+
encoded.WriteRune(char) // Append as is
81+
} else {
82+
// Encode character To %HH format
83+
encoded.WriteString(fmt.Sprintf("%%%02X", char))
84+
}
85+
}
86+
87+
return encoded.String()
88+
}
89+
90+
// Decode takes a percent-encoded string and returns its decoded representation.
91+
func decode(input string) (string, error) {
92+
// Use url.QueryUnescape which properly decodes percent-encoded strings
93+
decoded, err := url.QueryUnescape(input)
94+
if err != nil {
95+
return "", err
96+
}
97+
98+
return decoded, nil
99+
}
100+
101+
// isUnreserved checks if a character is an unreserved character in percent encoding
102+
// Unreserved characters are: A-Z, a-z, 0-9, -, ., _, ~
103+
func isUnreserved(char rune) bool {
104+
return (char >= 'A' && char <= 'Z') ||
105+
(char >= 'a' && char <= 'z') ||
106+
(char >= '0' && char <= '9') ||
107+
char == '-' || char == '.' || char == '_' || char == '~'
108+
}
109+
110+
func bindingPath() string {
111+
return "/" + bindings
112+
}
113+
114+
func bindingPathWithExchangeQueueKey(toQueue bool, sourceName, destinationName, key string) string {
115+
sourceNameEncoded := encodePathSegments(sourceName)
116+
destinationNameEncoded := encodePathSegments(destinationName)
117+
keyEncoded := encodePathSegments(key)
118+
destinationType := "dste"
119+
if toQueue {
120+
destinationType = "dstq"
121+
}
122+
format := "/%s/src=%s;%s=%s;key=%s;args="
123+
return fmt.Sprintf(format, bindings, sourceNameEncoded, destinationType, destinationNameEncoded, keyEncoded)
124+
125+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package rabbitmq_amqp
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
)
7+
8+
var _ = Describe("Address builder test ", func() {
9+
It("With exchange, queue and key should raise and error", func() {
10+
addressBuilder := NewAddressBuilder()
11+
Expect(addressBuilder).NotTo(BeNil())
12+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
13+
addressBuilder.Queue("queue").Exchange("exchange").Key("key")
14+
_, err := addressBuilder.Address()
15+
Expect(err).NotTo(BeNil())
16+
Expect(err.Error()).To(Equal("exchange and queue cannot be set together"))
17+
})
18+
19+
It("Without exchange and queue should raise and error", func() {
20+
addressBuilder := NewAddressBuilder()
21+
Expect(addressBuilder).NotTo(BeNil())
22+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
23+
_, err := addressBuilder.Address()
24+
Expect(err).NotTo(BeNil())
25+
Expect(err.Error()).To(Equal("exchange or queue must be set"))
26+
})
27+
28+
It("With exchange and key should return address", func() {
29+
addressBuilder := NewAddressBuilder()
30+
Expect(addressBuilder).NotTo(BeNil())
31+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
32+
addressBuilder.Exchange("my_exchange").Key("my_key")
33+
address, err := addressBuilder.Address()
34+
Expect(err).To(BeNil())
35+
Expect(address).To(Equal("/exchanges/my_exchange/my_key"))
36+
})
37+
38+
It("With exchange should return address", func() {
39+
addressBuilder := NewAddressBuilder()
40+
Expect(addressBuilder).NotTo(BeNil())
41+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
42+
addressBuilder.Exchange("my_exchange")
43+
address, err := addressBuilder.Address()
44+
Expect(err).To(BeNil())
45+
Expect(address).To(Equal("/exchanges/my_exchange"))
46+
})
47+
48+
It("With exchange and key with names to encode should return the encoded address", func() {
49+
addressBuilder := NewAddressBuilder()
50+
Expect(addressBuilder).NotTo(BeNil())
51+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
52+
addressBuilder.Exchange("my_ exchange/()").Key("my_key ")
53+
address, err := addressBuilder.Address()
54+
Expect(err).To(BeNil())
55+
Expect(address).To(Equal("/exchanges/my_%20exchange%2F%28%29/my_key%20"))
56+
})
57+
58+
It("With queue should return address", func() {
59+
addressBuilder := NewAddressBuilder()
60+
Expect(addressBuilder).NotTo(BeNil())
61+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
62+
addressBuilder.Queue("my_queue>")
63+
address, err := addressBuilder.Address()
64+
Expect(err).To(BeNil())
65+
Expect(address).To(Equal("/queues/my_queue%3E"))
66+
})
67+
68+
It("With queue and append should return address", func() {
69+
addressBuilder := NewAddressBuilder()
70+
Expect(addressBuilder).NotTo(BeNil())
71+
Expect(addressBuilder).To(BeAssignableToTypeOf(&AddressBuilder{}))
72+
addressBuilder.Queue("my_queue").Append("/messages")
73+
address, err := addressBuilder.Address()
74+
Expect(err).To(BeNil())
75+
Expect(address).To(Equal("/queues/my_queue/messages"))
76+
})
77+
78+
})

0 commit comments

Comments
 (0)