Azure Service Bus
Azure Service Bus is een online dienst waarmee berichten kunnen uitgewisseld worden tussen applicaties.
Voordelen van gebruik van deze dienst:
- asynchroon. Er kunnen berichten uitgewisseld worden, zelfs als een applicatie niet actief is.
- gebruik van de Azure Message Bus kan ook pieken in communicatie opvangen. Frequentie waarop berichten worden opgehaald is onder eigen controle.
Codeunit CFL Azure Service Bus Mgt.
Deze codeunit is een implementatie van de Azure Service Bus REST API.
Meer info vind je ook terug op de officiële documentatie
procedure CFLSetConnection
procedure CFLSetConnection(pServiceBus: Text; pQueue: Text; pAccessPolicyName: Text; pAccessKey: Text)
Het beheer van één of meerdere wachtrijen valt buiten de scope van deze codeunit en is vaak afhankelijk van het individuele project. Het is een best-practice om per type bericht een aparte wachtrij te gebruiken. Via deze functie wordt de connectie met de wachtrij opgezet. Je hoeft dit slechts éénmalig te doen per instantie van de codeunit.
procedure CFLSend
procedure CFLSend(Content: Text)
Functie voor het plaatsen van een bericht op de wachtrij met als parameter de inhoud van het bericht. Deze inhoud is typisch in de vorm van een JSON-bericht met een af te spreken formaat.
procedure CFLSend
procedure CFLSend(Content: Text; UserProperties: Dictionary of [Text, Text])
Functie voor het plaatsen van een bericht op de wachtrij waarbij naast de inhoud ook bijkomende eigenschappen als header bij het bericht worden toegevoegd. Deze bijkomende eigenschappen bevatten in paar een naam en waarde van de eigenschap.
procedure CFLSendBatch
procedure CFLSendBatch(Content: JsonArray)
Omwille van performantie kunnen we meerdere berichten ineens doorsturen. De berichten worden als JsonArray doorgestuurd. BrokerProperties bevatten eigenschappen van het platform, UserProperties bevatten bijkomende eigenschappen. Bv.
[
{
"Body":"This is the first message",
"BrokerProperties":{"Label":"M1","TimeToLiveTimeSpan":"0.00:00:40"}
},
{
"Body":"This is the second message",
"BrokerProperties":{"Label":"M2"},
"UserProperties":{"Priority":"Low"}
},
{
"Body":"This is the third message",
"BrokerProperties":{"Label":"M3"},
"UserProperties":{"Priority":"Medium","Customer":"ABC"}
}
]
procedure CFLReceiveDelete
procedure CFLReceiveDelete() HttpMessage : Record "CFL HttpMessage"
Functie om het eerstvolgende bericht van de wachtrij te lezen. Deze lees-instructie verwijdert ook onmiddelijk het bericht van de wachtrij. Eventuele andere partijen kunnen dit bericht ook niet meer lezen. De inhoud van het bericht wordt geplaatst in een HttpMessage voor verdere verwerking. Zie ook voorbeelden.
Specifieke eigenschappen (BrokerProperties) van het bericht worden ook opgehaald in de Response Headers van het bericht.
procedure CFLReceiveDeleteAll
procedure CFLReceiveDeleteAll()
Functie om alle berichten van de wachtrij te lezen (en te verwijderen). Deze functie wordt typisch in een taakwachtrijpost geplaatst en periodiek uitgevoerd.
procedure CFLPeekLock
procedure CFLPeekLock() HttpMessage : Record "CFL HttpMessage"
Functie om het eerstvolgende bericht van de wachtrij te lezen. Het bericht blijft wel staan op de wachtrij zodat eventuele andere partijen kunnen dit bericht ook kunnen lezen.
Bij het lezen wordt het bericht even geblokkeerd. Na een aantal pogingen wordt het bericht ook verplaatst naar dead-letter queue. Deze instellingen worden op de servicebus binnen Azure beheerd.
procedure CFLPeekLock
procedure CFLPeekLockAll()
Functie om alle berichten van de wachtrij te lezen (zonder te verwijderen).
procedure CFLUnLock
procedure CFLUnLock(MessageId: Text; LockToken: Text) HttpMessage : Record "CFL HttpMessage"
Functie om bericht na een Peek (met Lock) versneld te ontgrendelen.
procedure CFLRenewLock
procedure CFLRenewLock(MessageId: Text; LockToken: Text) HttpMessage : Record "CFL HttpMessage"
Functie om bericht na een Peek (met Lock) langer te vergrendelen.
procedure CFLDelete
procedure CFLDelete(MessageId: Text; LockToken: Text) HttpMessage : Record "CFL HttpMessage"
Functie om bericht na een Peek (met Lock) te verwijderen.
Voorbeelden
Bericht plaatsen op de wachtrij valkyrie van host bc18bus.servicebus.windows.net met als inhoud van het bericht 'Hello World!'. We gebruiken een Shared Access Policy Dynamics met zijn behorende Key om onszelf te authenticeren (user/password).
procedure SendMessage()
var
ASB: Codeunit "CFL Azure Service Bus Mgt.";
Props: Dictionary of [Text, Text];
begin
ASB.CFLSetConnection('bc18bus', 'valkyrie', 'Dynamics', '******E7ZQcbb3YL9d6WA+N8hIPU6Z72Bn6mSmx6Lp8=');
ASB.CFLSend(StrSubstNo('Hello %1!', UserId));
Er kunnen bijkomende Custom Properties worden toegevoegd aan de bericht-headers (name en value pair zijn hier bv. de bedrijfsnaam). Deze kunnen door de tegenpartij gebruikt/ontleed worden, naast de inhoud van het bericht zelf.
procedure SendMessageWithHeader()
var
ASB: Codeunit "CFL Azure Service Bus Mgt.";
Props: Dictionary of [Text, Text];
begin
ASB.CFLSetConnection('bc18bus', 'valkyrie', 'Dynamics', '******E7ZQcbb3YL9d6WA+N8hIPU6Z72Bn6mSmx6Lp8=');
Props.Add('CompanyName', CompanyName());
ASB.CFLSend(StrSubstNo('Hello %1!', UserId), Props);
end;
Omwille van performantie kunnen we meerdere berichten ineens doorsturen in. Onderstaand voorbeeld stuurt alle openstaande klanten door.
procedure SendOpenCustomers()
var
ASB: Codeunit "CFL Azure Service Bus Mgt.";
HttpMessage: record "CFL HttpMessage";
JsonArray: JsonArray;
JsonObject, JsonObjectProps : JsonObject;
Customer: Record Customer;
begin
Customer.SetFilter("Balance (LCY)", '>0');
if Customer.FindFirst() then
repeat
Customer.CalcFields("Balance (LCY)");
JsonObject.ReadFrom('{}');
JsonObjectProps.ReadFrom('{}');
JsonObjectProps.Add('CompanyName', CompanyName());
JsonObject.Add('UserProperties', JsonObjectProps);
JsonObject.Add('Body', StrSubstNo('Customer %1 has Balance Due (LCY) of %2.', Customer.Name, Customer."Balance (LCY)"));
JsonArray.Add(JsonObject);
until Customer.Next() = 0;
ASB.CFLSetConnection('bc18bus', 'valkyrie', 'Dynamics', '******E7ZQcbb3YL9d6WA+N8hIPU6Z72Bn6mSmx6Lp8=');
ASB.CFLSendBatch(JsonArray);
end;
Code die periodiek wordt uitgevoerd om de ganse wachtrij uit te lezen, bv. via taakwachtrijpost.
codeunit 50000 ReceiveDeleteAll
{
trigger OnRun()
var
ASB: Codeunit "CFL Azure Service Bus Mgt.";
HttpMessage : record "CFL HttpMessage";
JsonObject: JsonObject;
Bus, Queue : Text;
begin
Bus := 'bc18bus';
Queue := 'valkyrie';
ASB.CFLSetConnection(Bus, Queue, 'Dynamics', '******E7ZQcbb3YL9d6WA+N8hIPU6Z72Bn6mSmx6Lp8=');
repeat
HttpMessage := ASB.CFLReceiveDelete();
if (HttpMessage."CFL Method" = 'DELETE')
and (HttpMessage."CFL Uri" = StrSubstNo('https://%1.servicebus.windows.net/%2/messages/head', Bus, Queue))
and (HttpMessage."CFL Http Status Code" = 200) then begin
if JsonObject.ReadFrom(HttpMessage.CFLGetResponse()) then begin
//DO STUFF
end;
end;
until HttpMessage."CFL Http Status Code" <> 200
end;
}
Voorbeeld om bericht na een Peek te verwijderen.
trigger OnAction()
var
ASB: Codeunit "CFL Azure Service Bus Mgt.";
MessageId: Record "CFL HttpMessage Header";
LockToken: Record "CFL HttpMessage Header";
HttpHeaderType: Enum "CFL HttpHeaderType";
begin
ASB.CFLSetConnection('bc18bus', 'valkyrie', 'Dynamics', '******E7ZQcbb3YL9d6WA+N8hIPU6Z72Bn6mSmx6Lp8=');
MessageId.Get("CFL Entry No.", HttpHeaderType::"CFL Response", 'MessageId');
LockToken.Get("CFL Entry No.", HttpHeaderType::"CFL Response", 'LockToken');
ASB.CFLDelete(MessageId."CFL Value", LockToken."CFL Value");
end;