Skip to content

Commit 8d128db

Browse files
authored
feat(bindings): add amqp bindings (LEGO#153)
1 parent 9291da6 commit 8d128db

File tree

13 files changed

+596
-12
lines changed

13 files changed

+596
-12
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using System;
6+
using LEGO.AsyncAPI.Models;
7+
using LEGO.AsyncAPI.Readers.ParseNodes;
8+
using LEGO.AsyncAPI.Writers;
9+
10+
/// <summary>
11+
/// Binding class for AMQP channel settings.
12+
/// </summary>
13+
public class AMQPChannelBinding : ChannelBinding<AMQPChannelBinding>
14+
{
15+
/// <summary>
16+
/// Defines what type of channel is it. Can be either queue or routingKey.
17+
/// </summary>
18+
public ChannelType Is { get; set; }
19+
20+
/// <summary>
21+
/// When is=routingKey, this object defines the exchange properties.
22+
/// </summary>
23+
public Exchange Exchange { get; set; }
24+
25+
/// <summary>
26+
/// When is=queue, this object defines the queue properties.
27+
/// </summary>
28+
public Queue Queue { get; set; }
29+
30+
public override string BindingKey => "amqp";
31+
32+
protected override FixedFieldMap<AMQPChannelBinding> FixedFieldMap => new ()
33+
{
34+
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
35+
{ "is", (a, n) => { a.Is = n.GetScalarValue().GetEnumFromDisplayName<ChannelType>(); } },
36+
{ "exchange", (a, n) => { a.Exchange = n.ParseMap(ExchangeFixedFields); } },
37+
{ "queue", (a, n) => { a.Queue = n.ParseMap(QueueFixedFields); } },
38+
};
39+
40+
private static FixedFieldMap<Exchange> ExchangeFixedFields = new ()
41+
{
42+
{ "name", (a, n) => { a.Name = n.GetScalarValue(); } },
43+
{ "durable", (a, n) => { a.Durable = n.GetBooleanValue(); } },
44+
{ "type", (a, n) => { a.Type = n.GetScalarValue().GetEnumFromDisplayName<ExchangeType>(); } },
45+
{ "autoDelete", (a, n) => { a.AutoDelete = n.GetBooleanValue(); } },
46+
{ "vhost", (a, n) => { a.Vhost = n.GetScalarValue(); } },
47+
};
48+
49+
private static FixedFieldMap<Queue> QueueFixedFields = new()
50+
{
51+
{ "name", (a, n) => { a.Name = n.GetScalarValue(); } },
52+
{ "durable", (a, n) => { a.Durable = n.GetBooleanValue(); } },
53+
{ "exclusive", (a, n) => { a.Exclusive = n.GetBooleanValue(); } },
54+
{ "autoDelete", (a, n) => { a.AutoDelete = n.GetBooleanValue(); } },
55+
{ "vhost", (a, n) => { a.Vhost = n.GetScalarValue(); } },
56+
};
57+
58+
/// <summary>
59+
/// Serialize to AsyncAPI V2 document without using reference.
60+
/// </summary>
61+
public override void SerializeProperties(IAsyncApiWriter writer)
62+
{
63+
if (writer is null)
64+
{
65+
throw new ArgumentNullException(nameof(writer));
66+
}
67+
68+
writer.WriteStartObject();
69+
writer.WriteRequiredProperty("is", this.Is.GetDisplayName());
70+
switch (this.Is)
71+
{
72+
case ChannelType.RoutingKey:
73+
writer.WriteOptionalObject("exchange", this.Exchange, (w, t) => t.Serialize(w));
74+
break;
75+
case ChannelType.Queue:
76+
writer.WriteOptionalObject("queue", this.Queue, (w, t) => t.Serialize(w));
77+
break;
78+
}
79+
80+
writer.WriteOptionalProperty(AsyncApiConstants.BindingVersion, this.BindingVersion);
81+
writer.WriteExtensions(this.Extensions);
82+
83+
writer.WriteEndObject();
84+
}
85+
}
86+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using System;
6+
using LEGO.AsyncAPI.Models;
7+
using LEGO.AsyncAPI.Readers.ParseNodes;
8+
using LEGO.AsyncAPI.Writers;
9+
10+
/// <summary>
11+
/// Binding class for AMQP messages.
12+
/// </summary>
13+
public class AMQPMessageBinding : MessageBinding<AMQPMessageBinding>
14+
{
15+
/// <summary>
16+
/// A MIME encoding for the message content.
17+
/// </summary>
18+
public string ContentEncoding { get; set; }
19+
20+
/// <summary>
21+
/// Application-specific message type.
22+
/// </summary>
23+
public string MessageType { get; set; }
24+
25+
public override void SerializeProperties(IAsyncApiWriter writer)
26+
{
27+
if (writer is null)
28+
{
29+
throw new ArgumentNullException(nameof(writer));
30+
}
31+
32+
writer.WriteStartObject();
33+
34+
writer.WriteOptionalProperty("contentEncoding", this.ContentEncoding);
35+
writer.WriteOptionalProperty("messageType", this.MessageType);
36+
writer.WriteOptionalProperty(AsyncApiConstants.BindingVersion, this.BindingVersion);
37+
writer.WriteExtensions(this.Extensions);
38+
39+
writer.WriteEndObject();
40+
}
41+
42+
public override string BindingKey => "amqp";
43+
44+
protected override FixedFieldMap<AMQPMessageBinding> FixedFieldMap => new ()
45+
{
46+
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
47+
{ "contentEncoding", (a, n) => { a.ContentEncoding = n.GetScalarValue(); } },
48+
{ "messageType", (a, n) => { a.MessageType = n.GetScalarValue(); } },
49+
};
50+
}
51+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using System;
6+
using System.Collections.Generic;
7+
using LEGO.AsyncAPI.Models;
8+
using LEGO.AsyncAPI.Readers;
9+
using LEGO.AsyncAPI.Readers.ParseNodes;
10+
using LEGO.AsyncAPI.Writers;
11+
12+
/// <summary>
13+
/// Binding class for AMQP operations.
14+
/// </summary>
15+
public class AMQPOperationBinding : OperationBinding<AMQPOperationBinding>
16+
{
17+
/// <summary>
18+
/// TTL (Time-To-Live) for the message. It MUST be greater than or equal to zero.
19+
/// </summary>
20+
public uint? Expiration { get; set; }
21+
22+
/// <summary>
23+
/// Identifies the user who has sent the message.
24+
/// </summary>
25+
public string UserId { get; set; }
26+
27+
/// <summary>
28+
/// The routing keys the message should be routed to at the time of publishing.
29+
/// </summary>
30+
public List<string> Cc { get; set; } = new List<string>();
31+
32+
/// <summary>
33+
/// A priority for the message.
34+
/// </summary>
35+
public int? Priority { get; set; }
36+
37+
/// <summary>
38+
/// Delivery mode of the message. Its value MUST be either 1 (transient) or 2 (persistent).
39+
/// </summary>
40+
public DeliveryMode? DeliveryMode { get; set; }
41+
42+
/// <summary>
43+
/// Whether the message is mandatory or not.
44+
/// </summary>
45+
public bool? Mandatory { get; set; }
46+
47+
/// <summary>
48+
/// Like cc but consumers will not receive this information.
49+
/// </summary>
50+
public List<string> Bcc { get; set; } = new List<string>();
51+
52+
/// <summary>
53+
/// Whether the message should include a timestamp or not.
54+
/// </summary>
55+
public bool? Timestamp { get; set; }
56+
57+
/// <summary>
58+
/// Whether the consumer should ack the message or not.
59+
/// </summary>
60+
public bool? Ack { get; set; }
61+
62+
public override string BindingKey => "amqp";
63+
64+
protected override FixedFieldMap<AMQPOperationBinding> FixedFieldMap => new()
65+
{
66+
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
67+
{ "expiration", (a, n) => { a.Expiration = (uint?)n.GetIntegerValueOrDefault(); } },
68+
{ "userId", (a, n) => { a.UserId = n.GetScalarValueOrDefault(); } },
69+
{ "cc", (a, n) => { a.Cc = n.CreateSimpleList(s => s.GetScalarValue()); } },
70+
{ "priority", (a, n) => { a.Priority = n.GetIntegerValueOrDefault(); } },
71+
{ "deliveryMode", (a, n) => { a.DeliveryMode = (DeliveryMode?)n.GetIntegerValueOrDefault(); } },
72+
{ "mandatory", (a, n) => { a.Mandatory = n.GetBooleanValueOrDefault(); } },
73+
{ "bcc", (a, n) => { a.Bcc = n.CreateSimpleList(s => s.GetScalarValue()); } },
74+
{ "timestamp", (a, n) => { a.Timestamp = n.GetBooleanValueOrDefault(); } },
75+
{ "ack", (a, n) => { a.Ack = n.GetBooleanValueOrDefault(); } },
76+
};
77+
78+
/// <summary>
79+
/// Serialize to AsyncAPI V2 document without using reference.
80+
/// </summary>
81+
public override void SerializeProperties(IAsyncApiWriter writer)
82+
{
83+
if (writer is null)
84+
{
85+
throw new ArgumentNullException(nameof(writer));
86+
}
87+
88+
writer.WriteStartObject();
89+
writer.WriteOptionalProperty<int>("expiration", (int)this.Expiration);
90+
writer.WriteOptionalProperty("userId", this.UserId);
91+
writer.WriteOptionalCollection("cc", this.Cc, (w, s) => w.WriteValue(s));
92+
writer.WriteOptionalProperty("priority", this.Priority);
93+
writer.WriteOptionalProperty("deliveryMode", (int?)this.DeliveryMode);
94+
writer.WriteOptionalProperty("mandatory", this.Mandatory);
95+
writer.WriteOptionalCollection("bcc", this.Bcc, (w, s) => w.WriteValue(s));
96+
writer.WriteOptionalProperty("timestamp", this.Timestamp);
97+
writer.WriteOptionalProperty("ack", this.Ack);
98+
writer.WriteOptionalProperty(AsyncApiConstants.BindingVersion, this.BindingVersion);
99+
writer.WriteExtensions(this.Extensions);
100+
writer.WriteEndObject();
101+
}
102+
}
103+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using LEGO.AsyncAPI.Attributes;
6+
7+
public enum ChannelType
8+
{
9+
[Display("routingKey")]
10+
RoutingKey = 0,
11+
12+
[Display("queue")]
13+
Queue,
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using LEGO.AsyncAPI.Attributes;
6+
7+
public enum DeliveryMode
8+
{
9+
[Display("transient")]
10+
Transient = 1,
11+
12+
[Display("persistent")]
13+
Persistent = 2,
14+
}
15+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using LEGO.AsyncAPI.Models;
6+
using LEGO.AsyncAPI.Models.Interfaces;
7+
using LEGO.AsyncAPI.Writers;
8+
9+
/// <summary>
10+
/// Represents an exchange configuration.
11+
/// </summary>
12+
public class Exchange : IAsyncApiElement
13+
{
14+
/// <summary>
15+
/// The name of the exchange. It MUST NOT exceed 255 characters long.
16+
/// </summary>
17+
public string Name { get; set; }
18+
19+
/// <summary>
20+
/// The type of the exchange. Can be either topic, direct, fanout, default, or headers.
21+
/// </summary>
22+
public ExchangeType Type { get; set; }
23+
24+
/// <summary>
25+
/// Whether the exchange should survive broker restarts or not.
26+
/// </summary>
27+
public bool Durable { get; set; }
28+
29+
/// <summary>
30+
/// Whether the exchange should be deleted when the last queue is unbound from it.
31+
/// </summary>
32+
public bool AutoDelete { get; set; }
33+
34+
/// <summary>
35+
/// The virtual host of the exchange. Defaults to /.
36+
/// </summary>
37+
public string Vhost { get; set; } = "/";
38+
39+
public void Serialize(IAsyncApiWriter writer)
40+
{
41+
writer.WriteStartObject();
42+
writer.WriteRequiredProperty(AsyncApiConstants.Name, this.Name);
43+
writer.WriteRequiredProperty(AsyncApiConstants.Type, this.Type.GetDisplayName());
44+
writer.WriteRequiredProperty("durable", this.Durable);
45+
writer.WriteRequiredProperty("autoDelete", this.AutoDelete);
46+
writer.WriteRequiredProperty("vhost", this.Vhost);
47+
writer.WriteEndObject();
48+
}
49+
}
50+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Bindings.AMQP
4+
{
5+
using LEGO.AsyncAPI.Attributes;
6+
7+
public enum ExchangeType
8+
{
9+
[Display("default")]
10+
Default = 0,
11+
12+
[Display("topic")]
13+
Topic,
14+
15+
[Display("direct")]
16+
Direct,
17+
18+
[Display("fanout")]
19+
Fanout,
20+
21+
[Display("headers")]
22+
Headers,
23+
}
24+
}

0 commit comments

Comments
 (0)