DP- Singleton / Multitone and Get your .NET Web App into the cloud

 

Presentation 1:  Design Patterns – Singleton / Multiton

Speaker : Andrei Ignat

Description: You will learn about Singleton / Multitone pattern . Also it will be presented a practical example about where it is used in practice in .NET framework

Presentations 2: Get your .NET Web App into the cloud and sleep better at night

Speaker: Sorin Peste, Technical Evangelist @ Microsoft

Description: We’re often told that one big reason to consider the cloud is because a lot of the headaches of management and operations can be taken care of for us. Things like Auto scaling, Continuous Deployment, Staging slots, Monitoring, Failover may not come as a completely free lunch, but you CAN get them at a significant discount – of your time, effort, and money. Come to this session to see how Azure App Service can help you meet those requirements for your app – so you can sleep better at night. *expect hands on experience! :)

Telefonul meu este 0728200034.

Adresa este Bulevardul Expoziției nr.2 . Ne gasiti in Sala de Relaxare – intrarea in cladire se face prin lateralul cladirii, acolo unde este parcarea Ubisoft.

Worldbank–retry task if failure

Data trecuta am facut un benchmark pentru obtinerea datelor. Cind citeam de pe hard ( fisiere ) , era ok. Insa cind frameworkul de benchmark incepea sa solicite WorldBank API, acesta intorcea 500 ( internal server error)

Asa incit m-am hotarit ca ar trebui sa iau un framework de retry – daca da eroare serviciul , sa mai incerc de citeva ori.

Si am ajuns la Polly, https://github.com/App-vNext/Polly#asynchronous-support  . Codul este destul de simplu . Trebuie sa faca retry de 3 ori si sa logheze daca a fost vreo eroare si a cita eroare a fost.

Acesta este codul ( functia de downloadat se numeste DownloadData )

 

 

        public async Task<string> JsonData(int page = 1)
        {
            string req = "indicators?format=json" + ((page != 1) ? $"&page={page}" : "");
            Context c = new Context(req);
            
            var task = Policy
                .Handle<HttpRequestException>()
                .Or<WebException>()
                .WaitAndRetryAsync(3,
                    (t) => TimeSpan.FromSeconds(10),
                    (ex, ts, nr, context) =>
                    {
                        Console.WriteLine($"!!!{context["req"]} {DateTime.Now.ToString("HHmmss")}  retrying {nr} for error ");
                    }
                    )
                    .ExecuteAsync(async (ct) => 
                        {
                            ct["req"] = req;
                            return await DownloadData(req);
                        }
                        ,c);


            return await task;
                
        }

 

Am executat cu acelasi BenchMarkDotNet  – cu

[SimpleJob(launchCount: 1, warmupCount: 1,invocationCount:3,targetCount: 2, id: “QuickJob”)]

Acestea sunt rezultatele:

 

Pentru secvential:

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetIndicators 167.4 s NA 0.1202 s 77666.6667 17333.3333 1333.3333 11.82 KB

 

Pentru task

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetIndicators 4.025 s NA 0.5998 s 49333.3333 11833.3333 2333.3333 11.82 KB

 

Concluzii:

1. Se vede clar ca paralel e MULTmai bun decit secvential  ( 4 vs 167 secunde)

2. Paralel totusi poate da eroare la API ,daca e chemat prea rapid ( de aceea am facut retry)

3. Facind retry am rezolvat partial problema . Ar trebui sa fie si o BD de cache in care sa se tina raspunsurile ( ca acele fisiere de pe disk pe care le-am salvat dupa call ca sa fac unit test independente de http)

Imbunatatirea performantei la citire

 

Ce am remarcat este ca obtinerea resurselor se poate face pe cite un thread separat ( dupa prima care iti da numarul de pagini)

Asta e bine – si am transformat codul secvential intr-un unul pe thread / task ( Vedeti si o problema pe care am rezolvat-o cu diferenta intre List<T> si ConcurrentBag<T> aici: http://msprogrammer.serviciipeweb.ro/2017/05/22/task-and-generic-list/)

Am instalat https://github.com/dotnet/BenchmarkDotNet si am inceput sa fac teste de performanta. Nu a fost greu, dat fiind ca aveam deja teste automate – am modificat un pic clasa:

 

Pentru citirea de pe hard secvential:

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetAndInterpretData 532.5 ms 68.21 ms 3.854 ms 25604.1667 7375.0000 2791.6667 8.12 KB

 

Pentru citirea de pe hard cu task

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetAndInterpretData 435.1 ms 56.27 ms 3.179 ms 31000.0000 8229.1667 2729.1667 8.12 KB

Puteti observa chestii de baza:

1. E mai bine cu Task ca timp ( desi , daca fac Mean+Error la task , da mai mare decit Mean-Error la secvential – totusi,  cu 27 ms )

2. Alocarea de obiecte e mai mare la Task

 

Am facut si pentru citirea de la WorldBank API pe http, insa aici mi-au dat tot felul de erori de http ( de la 500 la 404 ) . Asa ca nu  am putut face benchmark . Si mi-a dat o noua idee – retry on task ( asta , data viitoare)

Maintaining history of data modifications & Inversion of Control

Presentation 1
Maintaining history of data modifications ( Microsoft SQL Server 2016)
Presenter:
Andrei Ignat, http://msprogrammer.serviciipeweb.ro/
Details:
1. Coding / Event Sourcing
2. Table Triggers
3. Change Data Capture
4. Temporal Tables
5. Conclusions

Presentation 2

Inversion of Control 

Presenter:
Costin Manda , https://siderite.blogspot.com/
Details:  For starters please see https://siderite.blogspot.com/2016/12/dependency-injection-inversion-of.html

 

Data: 23 mai 2017, ora 19

Inscrieri https://www.meetup.com/Bucharest-A-D-C-E-S-Meetup/events/238598555/

WorldBank–adaugare de indicatori si o idee de refactoring la teste

Dupa ce am adus tarile ( countries)  si am facut testarea , am zis sa aduc si indicatorii(http://api.worldbank.org/indicators?format=json ).  La indicatia lui Alexandru Savu de data trecuta, am copiat JSON si am dat File => Paste Special =>Paste JSON as Classes si a fost ok.

La indicatori  am inceput sa vad limitarile la ce am facut pina aici:

  • Indicatorii au 324 de pagini – dureaza prea mult sa ii incarci . Ar trebui adusi pe thread-uri separate
  • Pentru testare am creat 324 de fisiere  – mai bine le pun intr-un zip si apoi dezipuiesc- solutia e cam mare cu atitea fisiere. La fel , citirea s-ar putea face in paralel de pe hard( desi cred ca ar dura mai mult)
  • API-ul este aproape acelasi pentru JsonIndicators si JsonCountries . Se vede nevoia de refactoring.(generics?)
  • La fel la testare  – citirea de pe hard a fisierelor e la fel pentru cele doua(countries si indicators) . Aici am facut deja o clasa comuna de citit de pe hard fisierele json
    class JsonFromHard : IJsonData
    {
        public string NameFile { get; private set; }
        public JsonFromHard(string nameFile)
        {
            NameFile = nameFile;
        }
        /// <summary>
        /// generating data with 
        ///System.IO.File.WriteAllText("countries" + page + ".txt", str);
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public Task<string> JsonData(int page = 1) {
            return Task.FromResult( File.ReadAllText($@"{NameFile}\{NameFile}{page}.txt"));
        }

    }

si se apeleaza simplu in cele doua moduri

var c = new CountriesRepository(new JsonFromHard("Countries"));
var c = new IndicatorRepository(new JsonFromHard("indicators"));

World bank – testare

Am ajuns la testare. Cum faci testarea pentru WebAPI ? Simplu – in trei pasi

 

1. Creezi o clasa Data si o interfata IData  care iti da datele.  Clasa care foloseste API primeste o interfata IData. Clasa Data ia datele de pe WebAPI

2.. Testezi manual cu date reale si scrii datele pe hard

3. Faci o noua clasa , DataHard, ce implementeaza IData care iti citeste datele de pe hard.

4. Adaugi in proiectul de Test fisierele de date reale si DataHard

5. Clasa care foloseste API primeste ca interfata IData instanta de DataHard.

Cod:

Interfata de obtinere de date:

public interface IJsonData
    {
        Task<string> JsonData(int page = 1);
    }

Implementare cu WebAPI real si scriere pe hard a fisierelor

class JsonCountries : IJsonData
    {
        public async Task<string> JsonData(int page=1)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://api.worldbank.org/");
                string req = "countries?format=json" +((page != 1) ? $"&page={page}" : "");
                var response = await client.GetAsync(req);
                response.EnsureSuccessStatusCode();
                var str= await response.Content.ReadAsStringAsync();
                //System.IO.File.WriteAllText("countries" + page + ".txt", str); 
                return str;
            }
        }

        
    }

Clasa care citeste de pe hard

    class JsonCountriesFromHard : IJsonData
    {

        /// <summary>
        /// generating data with 
        ///System.IO.File.WriteAllText("countries" + page + ".txt", str);
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public Task<string> JsonData(int page = 1) {
            return Task.FromResult( File.ReadAllText($@"Countries\countries{page}.txt"));
        }

    }

Clasa care va fi testata – primeste in constructor interfata

[assembly: InternalsVisibleTo("WorldBank.Test")]
namespace WorldBank.Repository
{
    public class CountriesRepository
    {
        private IJsonData data;
        public CountriesRepository():this(new JsonCountries())
        {

        }
        internal CountriesRepository(IJsonData data)
        {
            this.data = data;
        }
     }
}

Testarea manuala

var c = new CountriesRepository();
var data = c.GetCountries().Result;
Console.WriteLine(data.Length);

Testarea automata

var c = new CountriesRepository(new JsonCountriesFromHard());
            var data = c.GetCountries().Result;
            Assert.Equal(218, data.Length);

Gasiti tot codul la https://github.com/ignatandrei/WorldBankAPi
Intrebare – ca sa vad daca sunteti atenti: la ce foloseste InternalsVisibleTo ?

World Bank API–partea 1

M-am hotarit sa fac citesc API de la WorldBank. 

La ce bun?

1. Nu exista inca pachet de NuGet pentru asta

2. Vreau sa integrez Typescript cu roslyn

3. Vreau sa vad ce folosesc la un proiect de API

4. Vreau sa il trec prin diferite faze( optimizare , testare, etc)

5. Vreau sa am un proiect bun ( vezi 1)

Am citit documentatia de la https://datahelpdesk.worldbank.org/knowledgebase/articles/889386-developer-information-overview  si am zis sa aduc tarile lumii. Documentatia pentru tari o gasiti aici: https://datahelpdesk.worldbank.org/knowledgebase/articles/898590-api-country-queries si un exemplu de API http://api.worldbank.org/countries?format=json&page=2 

Am utilizat http://json2csharp.com/ ca sa scot modelele in C# din JSON ( au si XML – insa JSON e la ordinea zilei)

 

Asa ca m-am pomenit cu aceste clase:

Ce am mai observat; API-ul de Country de la WorldBank  nu contine doar tarile  – contine si date agregate (ca de exemplu

d":"DLA","iso2Code":"D2","name":"Latin America & the Caribbean (IDA-eligible countries)"

. Asa incit am doua functii:

public async Task<Country[]> GetCountriesWithAggregates()

si

public async Task<Country[]> GetCountries()

Asa ca , iata lista tarilor din lume obtinuta din codul urmator:


var c = new CountriesRepository();
var data = c.GetCountries().Result;
Console.WriteLine(data.Length);
foreach(var item in data)
      {                
          Console.WriteLine(item.id + "--" + item.name + " - " + "-" + item.incomeLevel.value);
      }

 

ABW–Aruba – -High income
AFG–Afghanistan – -Low income
AGO–Angola – -Upper middle income
ALB–Albania – -Upper middle income
AND–Andorra – -High income
ARE–United Arab Emirates – -High income
ARG–Argentina – -Upper middle income
ARM–Armenia – -Lower middle income
ASM–American Samoa – -Upper middle income
ATG–Antigua and Barbuda – -High income
AUS–Australia – -High income
AUT–Austria – -High income
AZE–Azerbaijan – -Upper middle income
BDI–Burundi – -Low income
BEL–Belgium – -High income
BEN–Benin – -Low income
BFA–Burkina Faso – -Low income
BGD–Bangladesh – -Lower middle income
BGR–Bulgaria – -Upper middle income
BHR–Bahrain – -High income
BHS–Bahamas, The – -High income
BIH–Bosnia and Herzegovina – -Upper middle income
BLR–Belarus – -Upper middle income
BLZ–Belize – -Upper middle income
BMU–Bermuda – -High income
BOL–Bolivia – -Lower middle income
BRA–Brazil – -Upper middle income
BRB–Barbados – -High income
BRN–Brunei Darussalam – -High income
BTN–Bhutan – -Lower middle income
BWA–Botswana – -Upper middle income
CAF–Central African Republic – -Low income
CAN–Canada – -High income
CHE–Switzerland – -High income
CHI–Channel Islands – -High income
CHL–Chile – -High income
CHN–China – -Upper middle income
CIV–Cote d’Ivoire – -Lower middle income
CMR–Cameroon – -Lower middle income
COD–Congo, Dem. Rep. – -Low income
COG–Congo, Rep. – -Lower middle income
COL–Colombia – -Upper middle income
COM–Comoros – -Low income
CPV–Cabo Verde – -Lower middle income
CRI–Costa Rica – -Upper middle income
CUB–Cuba – -Upper middle income
CUW–Curacao – -High income
CYM–Cayman Islands – -High income
CYP–Cyprus – -High income
CZE–Czech Republic – -High income
DEU–Germany – -High income
DJI–Djibouti – -Lower middle income
DMA–Dominica – -Upper middle income
DNK–Denmark – -High income
DOM–Dominican Republic – -Upper middle income
DZA–Algeria – -Upper middle income
ECU–Ecuador – -Upper middle income
EGY–Egypt, Arab Rep. – -Lower middle income
ERI–Eritrea – -Low income
ESP–Spain – -High income
EST–Estonia – -High income
ETH–Ethiopia – -Low income
FIN–Finland – -High income
FJI–Fiji – -Upper middle income
FRA–France – -High income
FRO–Faroe Islands – -High income
FSM–Micronesia, Fed. Sts. – -Lower middle income
GAB–Gabon – -Upper middle income
GBR–United Kingdom – -High income
GEO–Georgia – -Upper middle income
GHA–Ghana – -Lower middle income
GIB–Gibraltar – -High income
GIN–Guinea – -Low income
GMB–Gambia, The – -Low income
GNB–Guinea-Bissau – -Low income
GNQ–Equatorial Guinea – -Upper middle income
GRC–Greece – -High income
GRD–Grenada – -Upper middle income
GRL–Greenland – -High income
GTM–Guatemala – -Lower middle income
GUM–Guam – -High income
GUY–Guyana – -Upper middle income
HKG–Hong Kong SAR, China – -High income
HND–Honduras – -Lower middle income
HRV–Croatia – -High income
HTI–Haiti – -Low income
HUN–Hungary – -High income
IDN–Indonesia – -Lower middle income
IMN–Isle of Man – -High income
IND–India – -Lower middle income
IRL–Ireland – -High income
IRN–Iran, Islamic Rep. – -Upper middle income
IRQ–Iraq – -Upper middle income
ISL–Iceland – -High income
ISR–Israel – -High income
ITA–Italy – -High income
JAM–Jamaica – -Upper middle income
JOR–Jordan – -Upper middle income
JPN–Japan – -High income
KAZ–Kazakhstan – -Upper middle income
KEN–Kenya – -Lower middle income
KGZ–Kyrgyz Republic – -Lower middle income
KHM–Cambodia – -Lower middle income
KIR–Kiribati – -Lower middle income
KNA–St. Kitts and Nevis – -High income
KOR–Korea, Rep. – -High income
KWT–Kuwait – -High income
LAO–Lao PDR – -Lower middle income
LBN–Lebanon – -Upper middle income
LBR–Liberia – -Low income
LBY–Libya – -Upper middle income
LCA–St. Lucia – -Upper middle income
LIE–Liechtenstein – -High income
LKA–Sri Lanka – -Lower middle income
LSO–Lesotho – -Lower middle income
LTU–Lithuania – -High income
LUX–Luxembourg – -High income
LVA–Latvia – -High income
MAC–Macao SAR, China – -High income
MAF–St. Martin (French part) – -High income
MAR–Morocco – -Lower middle income
MCO–Monaco – -High income
MDA–Moldova – -Lower middle income
MDG–Madagascar – -Low income
MDV–Maldives – -Upper middle income
MEX–Mexico – -Upper middle income
MHL–Marshall Islands – -Upper middle income
MKD–Macedonia, FYR – -Upper middle income
MLI–Mali – -Low income
MLT–Malta – -High income
MMR–Myanmar – -Lower middle income
MNE–Montenegro – -Upper middle income
MNG–Mongolia – -Lower middle income
MNP–Northern Mariana Islands – -High income
MOZ–Mozambique – -Low income
MRT–Mauritania – -Lower middle income
MUS–Mauritius – -Upper middle income
MWI–Malawi – -Low income
MYS–Malaysia – -Upper middle income
NAM–Namibia – -Upper middle income
NCL–New Caledonia – -High income
NER–Niger – -Low income
NGA–Nigeria – -Lower middle income
NIC–Nicaragua – -Lower middle income
NLD–Netherlands – -High income
NOR–Norway – -High income
NPL–Nepal – -Low income
NRU–Nauru – -High income
NZL–New Zealand – -High income
OMN–Oman – -High income
PAK–Pakistan – -Lower middle income
PAN–Panama – -Upper middle income
PER–Peru – -Upper middle income
PHL–Philippines – -Lower middle income
PLW–Palau – -Upper middle income
PNG–Papua New Guinea – -Lower middle income
POL–Poland – -High income
PRI–Puerto Rico – -High income
PRK–Korea, Dem. PeopleΓÇÖs Rep. – -Low income
PRT–Portugal – -High income
PRY–Paraguay – -Upper middle income
PSE–West Bank and Gaza – -Lower middle income
PYF–French Polynesia – -High income
QAT–Qatar – -High income
ROU–Romania – -Upper middle income
RUS–Russian Federation – -Upper middle income
RWA–Rwanda – -Low income
SAU–Saudi Arabia – -High income
SDN–Sudan – -Lower middle income
SEN–Senegal – -Low income
SGP–Singapore – -High income
SLB–Solomon Islands – -Lower middle income
SLE–Sierra Leone – -Low income
SLV–El Salvador – -Lower middle income
SMR–San Marino – -High income
SOM–Somalia – -Low income
SRB–Serbia – -Upper middle income
SSD–South Sudan – -Low income
STP–Sao Tome and Principe – -Lower middle income
SUR–Suriname – -Upper middle income
SVK–Slovak Republic – -High income
SVN–Slovenia – -High income
SWE–Sweden – -High income
SWZ–Swaziland – -Lower middle income
SXM–Sint Maarten (Dutch part) – -High income
SYC–Seychelles – -High income
SYR–Syrian Arab Republic – -Lower middle income
TCA–Turks and Caicos Islands – -High income
TCD–Chad – -Low income
TGO–Togo – -Low income
THA–Thailand – -Upper middle income
TJK–Tajikistan – -Lower middle income
TKM–Turkmenistan – -Upper middle income
TLS–Timor-Leste – -Lower middle income
TON–Tonga – -Lower middle income
TTO–Trinidad and Tobago – -High income
TUN–Tunisia – -Lower middle income
TUR–Turkey – -Upper middle income
TUV–Tuvalu – -Upper middle income
TWN–Taiwan, China – -High income
TZA–Tanzania – -Low income
UGA–Uganda – -Low income
UKR–Ukraine – -Lower middle income
URY–Uruguay – -High income
USA–United States – -High income
UZB–Uzbekistan – -Lower middle income
VCT–St. Vincent and the Grenadines – -Upper middle income
VEN–Venezuela, RB – -Upper middle income
VGB–British Virgin Islands – -High income
VIR–Virgin Islands (U.S.) – -High income
VNM–Vietnam – -Lower middle income
VUT–Vanuatu – -Lower middle income
WSM–Samoa – -Lower middle income
XKX–Kosovo – -Lower middle income
YEM–Yemen, Rep. – -Lower middle income
ZAF–South Africa – -Upper middle income
ZMB–Zambia – -Lower middle income
ZWE–Zimbabwe – -Low income

 

Daca vreti sa participati, va rog sa va duceti pe GitHub la https://github.com/ignatandrei/WorldBankAPi

Freelancing / Remote Work and SqlServer 2016 Temporal Tables

 

Pe 11 aprilie avem un nou ADCES – cu doua prezentari

Prezentarea 1:
Asia Lindsay, https://www.linkedin.com/in/asialindsay

Title: How Freelancing and Remote Work is Changing the World
Description:
– How to break into freelancing
– How freelancing and remote work can improve your life
– What it’s like being a digital nomad (hint- it’s fun!)

Prezentarea 2: 

Andrei Ignat, http://msprogrammer.serviciipeweb.ro/
SqlServer 2016 History tables
1. History with StoredProcedures
2. History with EF
3. History with Change Data Capture
4. History with Temporal tables

 

Inscrierea la https://www.meetup.com/Bucharest-A-D-C-E-S-Meetup/events/237069124/

Bula de evenimente IT

Saptamina care a trecut au fost urmatoarele evenimene IT in Bucuresti DevAfterWork la Ubisoft, ROSql meeting, Docker , 3 Cool things about D, Open Source Catalyst  si probabil altele de care nu am aflat

Saptamina aceasta sunt Code4Beer, Powershell fun facts, Code and Beer, Digital Ocean microservices, Azure as a service.Mobile Growth, Building sparrow wireless sensor nodes, EARO Hard/Code …

Daca esti student poate fi OK  sa te duci la toate si sa vezi care iti place. Ce te faci daca esti deja in IT , muncesti 8 ore / zi  si totusi vrei sa afli de ele ?Si mai vrei si viata ta proprie….

Si, daca te duci, nu o sa ai asta: https://en.wikipedia.org/wiki/Information_overload ?

PS1 Saptamina aceasta am fost la 2 …

PS2 Contribui si eu la inflatia aceasta 1 data pe luna cu https://www.meetup.com/Bucharest-A-D-C-E-S-Meetup/

Image Tag Helper base 64

 

In ASP.NET Core exista un image tag helper – care e bun – adauga si versiunea daca vrei.

Am creat un Image Tag Helper base 64 . Ce face –e simplu : pune imaginile inline in HTML conform cu specificatia https://en.wikipedia.org/wiki/Data_URI_scheme .

Cum se foloseste ?

<img src=’~/ relative path to the image ‘ asp-render-base64=’true’ />

Unde se foloseste?
De exemplu, daca vreti sa trimiteti un html ca atasament care sa aiba imaginile direct in el.

Unde gasiti sursele?

https://github.com/ignatandrei/AspNetCoreImageTagHelper

NuGet ?

NuGet Package at https://www.nuget.org/packages/AspNetCore.Mvc.ImageBase64/

De ce nu e in ASP.NET MVC ?

Am facut un pull request. Nu l-au aprobat ( au spus ca nu e in scope)

Totusi, l-au listat pe https://github.com/aspnet/mvc in readme.md