AVIS – pomocná funkce pro překonání výpadku dostupnosti Integračních služeb
Abychom ulehčili práci vývojářům třetích stran, kteří používají prostředí .Net, vytvořili jsme následující pomocnou metodu, která vám pomůže sjednotit a zjednodušit webové volání „Integračních služeb”. Metoda umožňuje opakovaně volat potřebnou část vašeho kódu a překonat tak bez většího úsilí krátkodobý výpadek dostupnosti Integračních služeb.
Kód je napsán v jazyku C#. Vývojáři, kteří používají jiné jazyky nebo jiné technologie, si mohou podobnou metodu napsat sami. Kód vzorové metody obsahuje komentáře, podle kterých je možné se zorientovat a funkci si přizpůsobit nebo napsat vlastní.
- Následující metodu zkopírujte a vložte ji na vhodné místo ve vašem projektu.
//Metoda pro automatické opakované volání Integračních služeb v případě jejich výpadku
//repeatSection - labda výraz nebo delegát, který je potřeba provést
//remainingAdditionalAttempts - počet opakování volání v případě, že služby nejsou dostupné
//sleepSeconds - délka intervalu v sekundách, po který se čeká mezi jednotlivými pokusy
public static void CallSafeAVIS(
Action repeatSection,
int remainingAdditionalAttempts = 3,
int sleepSeconds = 25)
{
try
{
//vyvoláme akci
repeatSection.Invoke();
}
catch (System.ServiceModel.CommunicationException err)
{
//při běhu, při pádu nebo v době restartu budeme sledovat výjimky
//typu System.ServiceModel.CommunicationException
//a jeho potomky
Type exceptionContractType = null;
bool isTerminalFault = true;
bool isApplicationException = true;
string exceptionDescription = null;
string exceptionSource = null;
int exceptionNumber = 0;
var errType = err.GetType();
if (!errType.IsGenericType) { }
else if (!(errType.BaseType == typeof(System.ServiceModel.FaultException))) { }
else if (errType.GenericTypeArguments.Length != 1) { }
else if (err.GetType().GenericTypeArguments[0].Name != "ExceptionContract") { }
else
{
//tady máme chybu, kterou vyhodily Integrační služby,
//takže zjistíme, jestli jde o chybu, která vynutila restart služby
//v případě, že je vlastnost IsTerminalFault = true, došlo právě k restartu služby
exceptionContractType = err.GetType().GenericTypeArguments[0];
isTerminalFault = exceptionContractType
.GetProperty("IsTerminalFault")
.GetValue(((dynamic)err).Detail);
isApplicationException = exceptionContractType
.GetProperty("IsApplicationException")
.GetValue(((dynamic)err).Detail);
exceptionDescription = exceptionContractType
.GetProperty("Description")
.GetValue(((dynamic)err).Detail);
exceptionSource = exceptionContractType
.GetProperty("Source")
.GetValue(((dynamic)err).Detail);
exceptionNumber = exceptionContractType
.GetProperty("Number")
.GetValue(((dynamic)err).Detail);
}
if (isTerminalFault && remainingAdditionalAttempts > 0)
{
//služby nejsou dočasně dostupné, zbývají ještě nějaké pokusy
//počkat a zkusit to znovu
System.Threading.Thread.Sleep(new TimeSpan(0, 0, sleepSeconds));
CallSafeAVIS(repeatSection, --remainingAdditionalAttempts, sleepSeconds);
return;
}
else if (isTerminalFault)
{
//služby nejsou dočasně dostupné
//došla trpělivost, oznámit chybu
throw;
}
else if (isApplicationException)
{
//očekávaná aplikační chyba, víme, co se děje, a uživatel ví, co s tím udělat
throw new ApplicationException(exceptionDescription);
}
else
{
//neočekávaná chyba
throw new ApplicationException(
string.Format("Chyba číslo {0} v {1}:\r\n{2}",
exceptionNumber,
exceptionSource,
exceptionDescription));
}
}
catch (Exception err)
{
//ostatní typy výjimek předáme volajícímu
throw err;
}
}
- Příklady použití pomocné metody CallSafeAVIS v praxi:
public DokladyAVIS.DokladContract NacistDoklad(string id)
{
DokladyAVIS.DokladContract result = null;
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
result = client.NacistDoklad(id);
}
});
return result;
}
public void AktualizovatDoklad(DokladyAVIS.DokladContract doklad)
{
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
client.AktualizovatDoklad(doklad);
}
});
}
public Guid VlozitNovyDoklad(DokladyAVIS.DokladContract doklad)
{
Guid rg = Guid.Empty;
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
rg = client.VlozitNovyDoklad(doklad);
}
});
return rg;
}
- Při volání různých metod v jedné funkci je potřeba, aby každé jedno volání bylo provedeno s pomocí metody CallSafeAVIS:
public Guid ZapsatNovyDoklad(DokladyAVIS.DokladContract doklad)
{
Guid rg = Guid.Empty;
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
rg = client.VlozitNovyDoklad(doklad);
}
});
…
//doklad načteme, získáme hodnoty vyplněné šablonou
…
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
doklad = client.NacistDokladRG(rg);
}
});
…
//provedeme nějaké úpravy a zaktualizujeme
…
CallSafeAVIS(() =>
{
using (var client = new DokladyAVIS.DokladyClient())
{
client.AktualizovatDoklad(doklad);
}
});