<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>@MMK_L_A</key>
	<array>
		<string>A</string>
		<string>Aacute</string>
		<string>Abreve</string>
		<string>Acircumflex</string>
		<string>Adieresis</string>
		<string>Agrave</string>
		<string>Amacron</string>
		<string>Aogonek</string>
		<string>Aring</string>
		<string>Atilde</string>
	</array>
	<key>@MMK_L_A.salt</key>
	<array>
		<string>A.salt</string>
		<string>Aacute.salt</string>
		<string>Abreve.salt</string>
		<string>Acircumflex.salt</string>
		<string>Adieresis.salt</string>
		<string>Agrave.salt</string>
		<string>Amacron.salt</string>
		<string>Aogonek.salt</string>
		<string>Aring.salt</string>
		<string>Atilde.salt</string>
		<string>Eng</string>
		<string>M.salt</string>
		<string>N.salt</string>
		<string>Nacute.salt</string>
		<string>Ncaron.salt</string>
		<string>Ncommaaccent.salt</string>
		<string>Ntilde.salt</string>
	</array>
	<key>@MMK_L_B</key>
	<array>
		<string>B</string>
		<string>Germandbls</string>
	</array>
	<key>@MMK_L_C</key>
	<array>
		<string>C</string>
		<string>Cacute</string>
		<string>Ccaron</string>
		<string>Ccedilla</string>
		<string>Ccircumflex</string>
		<string>Cdotaccent</string>
	</array>
	<key>@MMK_L_E</key>
	<array>
		<string>AE</string>
		<string>AE.salt</string>
		<string>E</string>
		<string>E.salt</string>
		<string>Eacute</string>
		<string>Eacute.salt</string>
		<string>Ebreve</string>
		<string>Ebreve.salt</string>
		<string>Ecaron</string>
		<string>Ecaron.salt</string>
		<string>Ecircumflex</string>
		<string>Ecircumflex.salt</string>
		<string>Edieresis</string>
		<string>Edieresis.salt</string>
		<string>Edotaccent</string>
		<string>Edotaccent.salt</string>
		<string>Egrave</string>
		<string>Egrave.salt</string>
		<string>Emacron</string>
		<string>Emacron.salt</string>
		<string>Eogonek</string>
		<string>Eogonek.salt</string>
		<string>OE</string>
	</array>
	<key>@MMK_L_F</key>
	<array>
		<string>F</string>
	</array>
	<key>@MMK_L_G</key>
	<array>
		<string>G</string>
		<string>Gbreve</string>
		<string>Gcircumflex</string>
		<string>Gcommaaccent</string>
		<string>Gdotaccent</string>
	</array>
	<key>@MMK_L_H</key>
	<array>
		<string>H</string>
		<string>Hcircumflex</string>
		<string>I.salt</string>
		<string>Iacute.salt</string>
		<string>Ibreve.salt</string>
		<string>Icircumflex.salt</string>
		<string>Idieresis.salt</string>
		<string>Idotaccent.salt</string>
		<string>Igrave.salt</string>
		<string>Imacron.salt</string>
		<string>Iogonek.salt</string>
		<string>Itilde.salt</string>
		<string>M</string>
		<string>N</string>
		<string>Nacute</string>
		<string>Ncaron</string>
		<string>Ncommaaccent</string>
		<string>Ntilde</string>
	</array>
	<key>@MMK_L_I</key>
	<array>
		<string>I</string>
		<string>Iacute</string>
		<string>Ibreve</string>
		<string>Icircumflex</string>
		<string>Idieresis</string>
		<string>Idotaccent</string>
		<string>Igrave</string>
		<string>Imacron</string>
		<string>Iogonek</string>
		<string>Itilde</string>
	</array>
	<key>@MMK_L_K</key>
	<array>
		<string>K</string>
		<string>Kcommaaccent</string>
	</array>
	<key>@MMK_L_L</key>
	<array>
		<string>L</string>
		<string>Lacute</string>
		<string>Lcommaaccent</string>
		<string>Lslash</string>
	</array>
	<key>@MMK_L_L.salt</key>
	<array>
		<string>L.salt</string>
		<string>Lacute.salt</string>
		<string>Lcommaaccent.salt</string>
		<string>Lslash.salt</string>
	</array>
	<key>@MMK_L_O</key>
	<array>
		<string>D</string>
		<string>Dcaron</string>
		<string>Dcroat</string>
		<string>Eth</string>
		<string>O</string>
		<string>Oacute</string>
		<string>Obreve</string>
		<string>Ocircumflex</string>
		<string>Odieresis</string>
		<string>Ograve</string>
		<string>Ohungarumlaut</string>
		<string>Omacron</string>
		<string>Oslash</string>
		<string>Otilde</string>
		<string>Q</string>
	</array>
	<key>@MMK_L_P</key>
	<array>
		<string>P</string>
	</array>
	<key>@MMK_L_R</key>
	<array>
		<string>R</string>
		<string>Racute</string>
		<string>Rcaron</string>
		<string>Rcommaaccent</string>
	</array>
	<key>@MMK_L_S</key>
	<array>
		<string>S</string>
		<string>Sacute</string>
		<string>Scaron</string>
		<string>Scedilla</string>
		<string>Scircumflex</string>
		<string>Scommaaccent</string>
	</array>
	<key>@MMK_L_T</key>
	<array>
		<string>T</string>
		<string>Tcaron</string>
		<string>Tcommaaccent</string>
	</array>
	<key>@MMK_L_Thorn</key>
	<array>
		<string>Thorn</string>
	</array>
	<key>@MMK_L_U</key>
	<array>
		<string>IJ</string>
		<string>J</string>
		<string>Jcircumflex</string>
		<string>U</string>
		<string>Uacute</string>
		<string>Ubreve</string>
		<string>Ucircumflex</string>
		<string>Udieresis</string>
		<string>Ugrave</string>
		<string>Uhungarumlaut</string>
		<string>Umacron</string>
		<string>Uogonek</string>
		<string>Uring</string>
		<string>Utilde</string>
		<string>W.salt</string>
		<string>Wacute.salt</string>
		<string>Wcircumflex.salt</string>
		<string>Wdieresis.salt</string>
		<string>Wgrave.salt</string>
	</array>
	<key>@MMK_L_V</key>
	<array>
		<string>V</string>
	</array>
	<key>@MMK_L_W</key>
	<array>
		<string>W</string>
		<string>Wacute</string>
		<string>Wcircumflex</string>
		<string>Wdieresis</string>
		<string>Wgrave</string>
	</array>
	<key>@MMK_L_X</key>
	<array>
		<string>X</string>
		<string>X.salt</string>
	</array>
	<key>@MMK_L_Y</key>
	<array>
		<string>Y</string>
		<string>Yacute</string>
		<string>Ycircumflex</string>
		<string>Ydieresis</string>
		<string>Ygrave</string>
	</array>
	<key>@MMK_L_Y.salt</key>
	<array>
		<string>Y.salt</string>
		<string>Yacute.salt</string>
		<string>Ycircumflex.salt</string>
		<string>Ydieresis.salt</string>
		<string>Ygrave.salt</string>
	</array>
	<key>@MMK_L_Z</key>
	<array>
		<string>Z</string>
		<string>Zacute</string>
		<string>Zcaron</string>
		<string>Zdotaccent</string>
	</array>
	<key>@MMK_L_colon</key>
	<array>
		<string>colon</string>
		<string>semicolon</string>
	</array>
	<key>@MMK_L_comma</key>
	<array>
		<string>comma</string>
		<string>period</string>
	</array>
	<key>@MMK_L_dash</key>
	<array>
		<string>emdash</string>
		<string>endash</string>
		<string>hyphen</string>
	</array>
	<key>@MMK_L_guillemotleft</key>
	<array>
		<string>guillemotleft</string>
		<string>guilsinglleft</string>
	</array>
	<key>@MMK_L_guillemotright</key>
	<array>
		<string>guillemotright</string>
		<string>guilsinglright</string>
	</array>
	<key>@MMK_L_minute</key>
	<array>
		<string>minute</string>
		<string>second</string>
	</array>
	<key>@MMK_L_parenleft</key>
	<array>
		<string>braceleft</string>
		<string>bracketleft</string>
		<string>parenleft</string>
	</array>
	<key>@MMK_L_percent</key>
	<array>
		<string>percent</string>
		<string>perthousand</string>
	</array>
	<key>@MMK_L_plus</key>
	<array>
		<string>divide</string>
		<string>equal</string>
		<string>minus</string>
		<string>multiply</string>
		<string>plus</string>
	</array>
	<key>@MMK_L_quoteleft</key>
	<array>
		<string>quotedblleft</string>
		<string>quoteleft</string>
	</array>
	<key>@MMK_L_quoteright</key>
	<array>
		<string>quotedblright</string>
		<string>quoteright</string>
	</array>
	<key>@MMK_L_quotesinglbase</key>
	<array>
		<string>quotedblbase</string>
		<string>quotesinglbase</string>
	</array>
	<key>@MMK_L_quotesingle</key>
	<array>
		<string>quotedbl</string>
		<string>quotesingle</string>
	</array>
	<key>@MMK_R_A</key>
	<array>
		<string>A</string>
		<string>AE</string>
		<string>Aacute</string>
		<string>Abreve</string>
		<string>Acircumflex</string>
		<string>Adieresis</string>
		<string>Agrave</string>
		<string>Amacron</string>
		<string>Aogonek</string>
		<string>Aring</string>
		<string>Atilde</string>
	</array>
	<key>@MMK_R_A.salt</key>
	<array>
		<string>A.salt</string>
		<string>AE.salt</string>
		<string>Aacute.salt</string>
		<string>Abreve.salt</string>
		<string>Acircumflex.salt</string>
		<string>Adieresis.salt</string>
		<string>Agrave.salt</string>
		<string>Amacron.salt</string>
		<string>Aogonek.salt</string>
		<string>Aring.salt</string>
		<string>Atilde.salt</string>
		<string>Eng</string>
		<string>M.salt</string>
		<string>N.salt</string>
		<string>Nacute.salt</string>
		<string>Ncaron.salt</string>
		<string>Ncommaaccent.salt</string>
		<string>Ntilde.salt</string>
	</array>
	<key>@MMK_R_Eth</key>
	<array>
		<string>Dcroat</string>
		<string>Eth</string>
	</array>
	<key>@MMK_R_H</key>
	<array>
		<string>B</string>
		<string>D</string>
		<string>Dcaron</string>
		<string>E</string>
		<string>Eacute</string>
		<string>Ebreve</string>
		<string>Ecaron</string>
		<string>Ecircumflex</string>
		<string>Edieresis</string>
		<string>Edotaccent</string>
		<string>Egrave</string>
		<string>Emacron</string>
		<string>Eogonek</string>
		<string>F</string>
		<string>Germandbls</string>
		<string>H</string>
		<string>Hcircumflex</string>
		<string>I.salt</string>
		<string>Iacute.salt</string>
		<string>Ibreve.salt</string>
		<string>Icircumflex.salt</string>
		<string>Idieresis.salt</string>
		<string>Idotaccent.salt</string>
		<string>Igrave.salt</string>
		<string>Imacron.salt</string>
		<string>Iogonek.salt</string>
		<string>Itilde.salt</string>
		<string>K</string>
		<string>Kcommaaccent</string>
		<string>L</string>
		<string>L.salt</string>
		<string>Lacute</string>
		<string>Lacute.salt</string>
		<string>Lcaron</string>
		<string>Lcaron.salt</string>
		<string>Lcommaaccent</string>
		<string>Lcommaaccent.salt</string>
		<string>Ldot</string>
		<string>Ldot.salt</string>
		<string>M</string>
		<string>N</string>
		<string>Nacute</string>
		<string>Ncaron</string>
		<string>Ncommaaccent</string>
		<string>Ntilde</string>
		<string>P</string>
		<string>R</string>
		<string>Racute</string>
		<string>Rcaron</string>
		<string>Rcommaaccent</string>
		<string>Thorn</string>
	</array>
	<key>@MMK_R_I</key>
	<array>
		<string>I</string>
		<string>IJ</string>
		<string>Iacute</string>
		<string>Ibreve</string>
		<string>Icircumflex</string>
		<string>Idieresis</string>
		<string>Idotaccent</string>
		<string>Igrave</string>
		<string>Imacron</string>
		<string>Iogonek</string>
		<string>Itilde</string>
	</array>
	<key>@MMK_R_J</key>
	<array>
		<string>J</string>
		<string>Jcircumflex</string>
	</array>
	<key>@MMK_R_O</key>
	<array>
		<string>C</string>
		<string>Cacute</string>
		<string>Ccaron</string>
		<string>Ccedilla</string>
		<string>Ccircumflex</string>
		<string>Cdotaccent</string>
		<string>E.salt</string>
		<string>Eacute.salt</string>
		<string>Ebreve.salt</string>
		<string>Ecaron.salt</string>
		<string>Ecircumflex.salt</string>
		<string>Edieresis.salt</string>
		<string>Edotaccent.salt</string>
		<string>Egrave.salt</string>
		<string>Emacron.salt</string>
		<string>Eogonek.salt</string>
		<string>G</string>
		<string>Gbreve</string>
		<string>Gcircumflex</string>
		<string>Gcommaaccent</string>
		<string>Gdotaccent</string>
		<string>O</string>
		<string>OE</string>
		<string>Oacute</string>
		<string>Obreve</string>
		<string>Ocircumflex</string>
		<string>Odieresis</string>
		<string>Ograve</string>
		<string>Ohungarumlaut</string>
		<string>Omacron</string>
		<string>Oslash</string>
		<string>Otilde</string>
		<string>Q</string>
	</array>
	<key>@MMK_R_S</key>
	<array>
		<string>S</string>
		<string>Sacute</string>
		<string>Scaron</string>
		<string>Scedilla</string>
		<string>Scircumflex</string>
		<string>Scommaaccent</string>
	</array>
	<key>@MMK_R_T</key>
	<array>
		<string>T</string>
		<string>Tcaron</string>
		<string>Tcommaaccent</string>
	</array>
	<key>@MMK_R_U</key>
	<array>
		<string>U</string>
		<string>Uacute</string>
		<string>Ubreve</string>
		<string>Ucircumflex</string>
		<string>Udieresis</string>
		<string>Ugrave</string>
		<string>Uhungarumlaut</string>
		<string>Umacron</string>
		<string>Uogonek</string>
		<string>Uring</string>
		<string>Utilde</string>
		<string>W.salt</string>
		<string>Wacute.salt</string>
		<string>Wcircumflex.salt</string>
		<string>Wdieresis.salt</string>
		<string>Wgrave.salt</string>
	</array>
	<key>@MMK_R_V</key>
	<array>
		<string>V</string>
	</array>
	<key>@MMK_R_W</key>
	<array>
		<string>W</string>
		<string>Wacute</string>
		<string>Wcircumflex</string>
		<string>Wdieresis</string>
		<string>Wgrave</string>
	</array>
	<key>@MMK_R_X</key>
	<array>
		<string>X</string>
		<string>X.salt</string>
	</array>
	<key>@MMK_R_Y</key>
	<array>
		<string>Y</string>
		<string>Yacute</string>
		<string>Ycircumflex</string>
		<string>Ydieresis</string>
		<string>Ygrave</string>
	</array>
	<key>@MMK_R_Y.salt</key>
	<array>
		<string>Y.salt</string>
		<string>Yacute.salt</string>
		<string>Ycircumflex.salt</string>
		<string>Ydieresis.salt</string>
		<string>Ygrave.salt</string>
	</array>
	<key>@MMK_R_Z</key>
	<array>
		<string>Z</string>
		<string>Zacute</string>
		<string>Zcaron</string>
		<string>Zdotaccent</string>
	</array>
	<key>@MMK_R_colon</key>
	<array>
		<string>colon</string>
		<string>semicolon</string>
	</array>
	<key>@MMK_R_comma</key>
	<array>
		<string>comma</string>
		<string>period</string>
	</array>
	<key>@MMK_R_dash</key>
	<array>
		<string>emdash</string>
		<string>endash</string>
		<string>hyphen</string>
	</array>
	<key>@MMK_R_guillemotleft</key>
	<array>
		<string>guillemotleft</string>
		<string>guilsinglleft</string>
	</array>
	<key>@MMK_R_guillemotright</key>
	<array>
		<string>guillemotright</string>
		<string>guilsinglright</string>
	</array>
	<key>@MMK_R_minute</key>
	<array>
		<string>minute</string>
		<string>second</string>
	</array>
	<key>@MMK_R_parenleft</key>
	<array>
		<string>braceleft</string>
		<string>bracketleft</string>
		<string>parenleft</string>
	</array>
	<key>@MMK_R_percent</key>
	<array>
		<string>percent</string>
		<string>perthousand</string>
	</array>
	<key>@MMK_R_plus</key>
	<array>
		<string>divide</string>
		<string>equal</string>
		<string>minus</string>
		<string>multiply</string>
		<string>plus</string>
	</array>
	<key>@MMK_R_quoteleft</key>
	<array>
		<string>quotedblleft</string>
		<string>quoteleft</string>
	</array>
	<key>@MMK_R_quoteright</key>
	<array>
		<string>quotedblright</string>
		<string>quoteright</string>
	</array>
	<key>@MMK_R_quotesinglbase</key>
	<array>
		<string>quotedblbase</string>
		<string>quotesinglbase</string>
	</array>
	<key>@MMK_R_quotesingle</key>
	<array>
		<string>quotedbl</string>
		<string>quotesingle</string>
	</array>
	<key>vertical_off</key>
	<array>
		<string>A</string>
		<string>AE</string>
		<string>Aacute</string>
		<string>Abreve</string>
		<string>Acircumflex</string>
		<string>Adieresis</string>
		<string>Agrave</string>
		<string>Amacron</string>
		<string>Aogonek</string>
		<string>Aring</string>
		<string>Atilde</string>
		<string>B</string>
		<string>C</string>
		<string>Cacute</string>
		<string>Ccaron</string>
		<string>Ccedilla</string>
		<string>Ccircumflex</string>
		<string>Cdotaccent</string>
		<string>D</string>
		<string>Dcaron</string>
		<string>Dcroat</string>
		<string>E</string>
		<string>Eacute</string>
		<string>Ebreve</string>
		<string>Ecaron</string>
		<string>Ecircumflex</string>
		<string>Edieresis</string>
		<string>Edotaccent</string>
		<string>Egrave</string>
		<string>Emacron</string>
		<string>Eng</string>
		<string>Eogonek</string>
		<string>Eth</string>
		<string>F</string>
		<string>G</string>
		<string>Gbreve</string>
		<string>Gcircumflex</string>
		<string>Gcommaaccent</string>
		<string>Gdotaccent</string>
		<string>H</string>
		<string>Hbar</string>
		<string>Hcircumflex</string>
		<string>I</string>
		<string>IJ</string>
		<string>Iacute</string>
		<string>Ibreve</string>
		<string>Icircumflex</string>
		<string>Idieresis</string>
		<string>Idotaccent</string>
		<string>Igrave</string>
		<string>Imacron</string>
		<string>Iogonek</string>
		<string>Itilde</string>
		<string>J</string>
		<string>Jcircumflex</string>
		<string>K</string>
		<string>Kcommaaccent</string>
		<string>L</string>
		<string>Lacute</string>
		<string>Lcaron</string>
		<string>Lcommaaccent</string>
		<string>Ldot</string>
		<string>Lslash</string>
		<string>M</string>
		<string>N</string>
		<string>Nacute</string>
		<string>Ncaron</string>
		<string>Ncommaaccent</string>
		<string>Ntilde</string>
		<string>O</string>
		<string>OE</string>
		<string>Oacute</string>
		<string>Obreve</string>
		<string>Ocircumflex</string>
		<string>Odieresis</string>
		<string>Ograve</string>
		<string>Ohungarumlaut</string>
		<string>Omacron</string>
		<string>Oslash</string>
		<string>Otilde</string>
		<string>P</string>
		<string>Q</string>
		<string>R</string>
		<string>Racute</string>
		<string>Rcaron</string>
		<string>Rcommaaccent</string>
		<string>S</string>
		<string>Sacute</string>
		<string>Scaron</string>
		<string>Scedilla</string>
		<string>Scircumflex</string>
		<string>Scommaaccent</string>
		<string>T</string>
		<string>Tbar</string>
		<string>Tcaron</string>
		<string>Tcommaaccent</string>
		<string>Thorn</string>
		<string>U</string>
		<string>Uacute</string>
		<string>Ubreve</string>
		<string>Ucircumflex</string>
		<string>Udieresis</string>
		<string>Ugrave</string>
		<string>Uhungarumlaut</string>
		<string>Umacron</string>
		<string>Uogonek</string>
		<string>Uring</string>
		<string>Utilde</string>
		<string>V</string>
		<string>W</string>
		<string>Wacute</string>
		<string>Wcircumflex</string>
		<string>Wdieresis</string>
		<string>Wgrave</string>
		<string>X</string>
		<string>Y</string>
		<string>Yacute</string>
		<string>Ycircumflex</string>
		<string>Ydieresis</string>
		<string>Ygrave</string>
		<string>Z</string>
		<string>Zacute</string>
		<string>Zcaron</string>
		<string>Zdotaccent</string>
		<string>ampersand</string>
		<string>asterisk</string>
		<string>at</string>
		<string>colon</string>
		<string>comma</string>
		<string>commaaccent</string>
		<string>dagger</string>
		<string>daggerdbl</string>
		<string>eight</string>
		<string>ellipsis</string>
		<string>exclam</string>
		<string>exclamdown</string>
		<string>five</string>
		<string>four</string>
		<string>guillemotleft</string>
		<string>guillemotright</string>
		<string>guilsinglleft</string>
		<string>guilsinglright</string>
		<string>nine</string>
		<string>numbersign</string>
		<string>one</string>
		<string>percent</string>
		<string>period</string>
		<string>perthousand</string>
		<string>question</string>
		<string>questiondown</string>
		<string>quotedbl</string>
		<string>quotedblbase</string>
		<string>quotedblleft</string>
		<string>quotedblright</string>
		<string>quoteleft</string>
		<string>quoteright</string>
		<string>quotesinglbase</string>
		<string>quotesingle</string>
		<string>semicolon</string>
		<string>seven</string>
		<string>six</string>
		<string>space</string>
		<string>three</string>
		<string>two</string>
		<string>zero</string>
	</array>
	<key>vertical_sorts_off</key>
	<array>
		<string>braceleft</string>
		<string>braceright</string>
		<string>bracketleft</string>
		<string>bracketright</string>
		<string>emdash</string>
		<string>endash</string>
		<string>hyphen</string>
		<string>parenleft</string>
		<string>parenright</string>
	</array>
</dict>
</plist>

{'repo_name': 'djrrb/Bungee', 'stars': '237', 'repo_language': 'Python', 'file_name': 'WebFonts Report', 'mime_type': 'text/plain', 'hash': 4275934900148875476, 'source_dataset': 'data'}


/********************************************************************************
 * Copyright (C) 2018 Red Hat, Inc. and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/

import { interfaces } from 'inversify';
import { MAIN_RPC_CONTEXT, TreeViewsMain, TreeViewsExt, TreeViewRevealOptions } from '../../../common/plugin-api-rpc';
import { RPCProtocol } from '../../../common/rpc-protocol';
import { PluginViewRegistry, PLUGIN_VIEW_DATA_FACTORY_ID } from './plugin-view-registry';
import { SelectableTreeNode, ExpandableTreeNode, CompositeTreeNode, WidgetManager } from '@theia/core/lib/browser';
import { ViewContextKeyService } from './view-context-key-service';
import { Disposable, DisposableCollection } from '@theia/core';
import { TreeViewWidget, TreeViewNode } from './tree-view-widget';
import { PluginViewWidget } from './plugin-view-widget';

export class TreeViewsMainImpl implements TreeViewsMain, Disposable {

    private readonly proxy: TreeViewsExt;
    private readonly viewRegistry: PluginViewRegistry;
    private readonly contextKeys: ViewContextKeyService;
    private readonly widgetManager: WidgetManager;

    private readonly treeViewProviders = new Map<string, Disposable>();

    private readonly toDispose = new DisposableCollection(
        Disposable.create(() => { /* mark as not disposed */ })
    );

    constructor(rpc: RPCProtocol, private container: interfaces.Container) {
        this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.TREE_VIEWS_EXT);
        this.viewRegistry = container.get(PluginViewRegistry);

        this.contextKeys = this.container.get(ViewContextKeyService);
        this.widgetManager = this.container.get(WidgetManager);
    }

    dispose(): void {
        this.toDispose.dispose();
    }

    async $registerTreeDataProvider(treeViewId: string): Promise<void> {
        this.treeViewProviders.set(treeViewId, this.viewRegistry.registerViewDataProvider(treeViewId, async ({ state, viewInfo }) => {
            const widget = await this.widgetManager.getOrCreateWidget<TreeViewWidget>(PLUGIN_VIEW_DATA_FACTORY_ID, { id: treeViewId });
            widget.model.viewInfo = viewInfo;
            if (state) {
                widget.restoreState(state);
                // ensure that state is completely restored
                await widget.model.refresh();
            } else if (!widget.model.root) {
                const root: CompositeTreeNode & ExpandableTreeNode = {
                    id: '',
                    parent: undefined,
                    name: '',
                    visible: false,
                    expanded: true,
                    children: []
                };
                widget.model.root = root;
            }
            if (this.toDispose.disposed) {
                widget.model.proxy = undefined;
            } else {
                widget.model.proxy = this.proxy;
                this.toDispose.push(Disposable.create(() => widget.model.proxy = undefined));
                this.handleTreeEvents(widget.id, widget);
            }
            await widget.model.refresh();
            return widget;
        }));
        this.toDispose.push(Disposable.create(() => this.$unregisterTreeDataProvider(treeViewId)));
    }

    async $unregisterTreeDataProvider(treeViewId: string): Promise<void> {
        const treeDataProvider = this.treeViewProviders.get(treeViewId);
        if (treeDataProvider) {
            this.treeViewProviders.delete(treeViewId);
            treeDataProvider.dispose();
        }
    }

    async $refresh(treeViewId: string): Promise<void> {
        const viewPanel = await this.viewRegistry.getView(treeViewId);
        const widget = viewPanel && viewPanel.widgets[0];
        if (widget instanceof TreeViewWidget) {
            await widget.model.refresh();
        }
    }

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    async $reveal(treeViewId: string, treeItemId: string, options: TreeViewRevealOptions): Promise<any> {
        const viewPanel = await this.viewRegistry.openView(treeViewId, { activate: options.focus });
        const widget = viewPanel && viewPanel.widgets[0];
        if (widget instanceof TreeViewWidget) {
            const treeNode = widget.model.getNode(treeItemId);
            if (treeNode) {
                if (options.expand && ExpandableTreeNode.is(treeNode)) {
                    widget.model.expandNode(treeNode);
                }
                if (options.select && SelectableTreeNode.is(treeNode)) {
                    widget.model.selectNode(treeNode);
                }
            }
        }
    }

    async $setMessage(treeViewId: string, message: string): Promise<void> {
        const viewPanel = await this.viewRegistry.getView(treeViewId);
        if (viewPanel instanceof PluginViewWidget) {
            viewPanel.message = message;
        }
    }

    async $setTitle(treeViewId: string, title: string): Promise<void> {
        const viewPanel = await this.viewRegistry.getView(treeViewId);
        if (viewPanel) {
            viewPanel.title.label = title;
        }
    }

    protected handleTreeEvents(treeViewId: string, treeViewWidget: TreeViewWidget): void {
        this.toDispose.push(treeViewWidget.model.onExpansionChanged(event => {
            this.proxy.$setExpanded(treeViewId, event.id, event.expanded);
        }));

        this.toDispose.push(treeViewWidget.model.onSelectionChanged(event => {
            if (event.length === 1) {
                const { contextValue } = event[0] as TreeViewNode;
                this.contextKeys.viewItem.set(contextValue);
            } else {
                this.contextKeys.viewItem.set('');
            }
            this.contextKeys.view.set(treeViewId);

            this.proxy.$setSelection(treeViewId, event.map((node: TreeViewNode) => node.id));
        }));

        const updateVisible = () => this.proxy.$setVisible(treeViewId, treeViewWidget.isVisible);
        updateVisible();
        this.toDispose.push(treeViewWidget.onDidChangeVisibility(() => updateVisible()));
    }

}

{'repo_name': 'eclipse-theia/theia', 'stars': '11268', 'repo_language': 'TypeScript', 'file_name': 'pull-requests.md', 'mime_type': 'text/plain', 'hash': -4516497979271551758, 'source_dataset': 'data'}


# iOS8 Day-by-Day :: Day 9 :: Designated Initialisers

This post is part of a daily series of posts introducing the most exciting new
parts of iOS8 for developers - [#iOS8DayByDay](https://twitter.com/search?q=%23iOS8DayByDay).
To see the posts you've missed check out the [index page](http://shinobicontrols.com/iOS8DayByDay),
but have a read through the rest of this post first!

---

## Introduction

The concept of designated initialisers is not new to the Cocoa world - they have
exist in objective-C, but somewhat informally. Swift formalises class initialisation,
both in terms of what the different initialisation methods should do, and the
order in which things should be done.

In order to ease interoperability with objective-C, there is also a little more
formalisation there too.

In this post you'll learn a bit about how initialisation works in Swift, with
an explanation of what designated initialisers are, and how they related to
convenience initialisers.

The accompanying code for this project is part of an Xcode playground - and is
available in the repo on github at
[github.com/ShinobiControls/iOS8-day-by-day](https://github.com/ShinobiControls/iOS8-day-by-day).
You should be able to just open it up and see the live-run results.

## Creating objects

Initialisers are used to instantiate an instance of a class or a struct. There are
two types of initialiser:

- __Designated__ This is responsible for preparing all the properties, and calling
the superclass' initialiser, allowing it to do the same.
- __Convenience__ Don't have to directly prepare and instance state, but must
call a designated initialiser. Cannot call an initialiser of the superclass.

For example:

    class Person {
      var name: String
      var age: Int?
      var consideredDangerous = false

      init(name: String, age: Int?) {
        self.name = name
        self.age = age
      }
    }

This is a class which has 3 properties. `init(name:,age:)` is a designated
initialiser, and therefore it is responsible for ensuring that all properties have
been correctly initialised. In the example above that actually only means that it
must set a value for the `name` property. This is because optionals will be set
to `nil` by default, and `consideredDangerous` is set inline.

Since the age is optional, we might want to offer another initialiser which just
accepts a name. One option would be to make another designated initialiser:

    init(name: String) {
      self.name = name
    }

This is perfectly acceptable, but it is actually repeating the same code as in
the previous designated initialiser. Should you decide to store uppercase names,
then you'd have to change both initialisers. This is where the concept of initialiser
chaining comes in - which is the pattern established with convenience initialisers.

### Convenience Initialisers

Convenience initialisers are denoted by the use of the `convenience` keyword, and
they __must__ call a designated initialiser:

    convenience init(name: String) {
      self.init(name: name, age: nil)
    }

This method now has the desired behaviour - it only requires a name, and delegates
the actual initialisation to a designated initialiser. Convenience initialisers
__cannot__ call the super class, but __must__ call a designated initialiser in the
same class.

### Subclassing

When you create a subclass then in addition to the aforementioned rules associated
with designated initialisers, you are also required to call a designated
initialiser of the superclass.

Look at the following example - a ninja is clearly a person, but they have a
collection of weapons, defined by the accompanying enum:

    class Ninja: Person {
      var weapons: [Weapon]?
    }

    enum Weapon {
      case Katana, Tsuba, Shuriken, Kusarigama, Fukiya
    }

The `Ninja` class definition doesn't currently have an initialiser, and since
the only additional property is an optional (and thus defaults to nil) it isn't
a requirement to have one. However, it'd be nice to add one which allows setting
the weapons array at initialisation time:

    init(name: String, age: Int?, weapons: [Weapon]?) {
      self.weapons = weapons

      super.init(name: name, age: age)

      self.consideredDangerous = true
    }

This demonstrates the rules of how a designated initialiser must be formed in
Swift:

1. Any properties on the subclass must be initialised correctly. Here it's not
strictly necessary since `weapons` is an optional type.
2. Once the current object's properties are all initialised, there __must__ be
a call to a designated initialiser on the superclass.
3. You can then update any properties inherited from the superclass.

This order is very important, and changing it will result in compiler errors. Note
that the order is different to the ordering used in subclass initialisers in
objective-C, where the call to the superclass is the first instruction.

You can add convenience initialisers to subclasses as well, but they must call
a designated initialiser of the same class. They __cannnot__ call an initialiser
of a superclass:

    convenience init(name: String) {
      self.init(name: name, age: nil, weapons: nil)
    }

This results in you being able to create ninjas in 2 ways:

    let tina = Ninja(name: "tina", age: 23, weapons: [.Fukiya, .Tsuba])
    let trevor = Ninja(name: "trevor")

## Usage in objective-C

Objective-C has the notion of designated initialisers - but in an informal context.
In order to enable full interoperability between objective-C and Swift, there is
a macro with which you can annotate your objective-C initialisers:
`NS_DESIGNATED_INITIALIZER`:

    - (instancetype)init NS_DESIGNATED_INITIALIZER;

By using this, then all other initialisers in your class will be interpreted as
being convenience initialisers. The same rules apply with objective-C initialisers
as their Swift counterparts.

## Conclusion

The designated initialiser pattern has existed in the Cocoa world for a long time,
but Swift formalises it somewhat. You'll need to fully understand it and what
is required of you as a developer in order to create your own classes and subclasses
in Swift.

It's also definitely worth adopting the new macro in any new objective-C that you
write, particularly if you want it to be interoperable with Swift code.

The code which accompanies this post is in the form of an Xcode 6 playground -
and demonstrates how the different patterns work. It is part of the day-by-day
repo on the ShinobiControls github at
[github.com/ShinobiControls/iOS8-day-by-day](https://github.com/ShinobiControls/iOS8-day-by-day).
If you have any questions about this topic, then Apple's Swift book is very
thorough, or feel free to grab me on twitter - [@iwanymyrealname](https://twitter.com/iwanymyrealname)

sam

{'repo_name': 'ScottLogic/iOS8-day-by-day', 'stars': '2653', 'repo_language': 'Swift', 'file_name': 'contents.xcworkspacedata', 'mime_type': 'text/xml', 'hash': 6110555619053239933, 'source_dataset': 'data'}


# expected-to-throw
fragment NameRendererFragment on User {
  id
  nameRenderer {
    ...MarkdownUserNameRenderer_name
      @module(name: "MarkdownUserNameRenderer.react")
  }
}

fragment MarkdownUserNameRenderer_name on MarkdownUserNameRenderer @inline {
  markdown
  data {
    markup
  }
}

{'repo_name': 'facebook/relay', 'stars': '14749', 'repo_language': 'JavaScript', 'file_name': 'Component_node.graphql.js', 'mime_type': 'text/x-java', 'hash': -8373300638931378718, 'source_dataset': 'data'}


<root>
		something<else>  blerm <slurm

	attrib =
	"blorg"       ></else><!-- COMMENT!

--><![CDATA[processing...]]>  <selfclosing tag="blr>""/> a bit down here</root>

{'repo_name': 'BitMOE/PortableHexo', 'stars': '154', 'repo_language': 'Perl', 'file_name': 'core.js', 'mime_type': 'text/plain', 'hash': 2724109430015426714, 'source_dataset': 'data'}


import React from 'react';
import PropTypes from 'prop-types';
import StyledCardColumn from './card-column.style';
import OptionsHelper from '../../../utils/helpers/options-helper/options-helper';

const { alignFull } = OptionsHelper;

const CardColumn = ({
  align,
  children,
  ...props
}) => (
  <StyledCardColumn
    align={ align }
    data-element='card-column'
    { ...props }
  >
    { children }
  </StyledCardColumn>
);

CardColumn.propTypes = {
  /** text alignment of the card section text */
  align: PropTypes.oneOf(alignFull),
  children: PropTypes.node.isRequired
};

CardColumn.defaultProps = {
  align: 'center'
};

export default CardColumn;

{'repo_name': 'Sage/carbon', 'stars': '137', 'repo_language': 'JavaScript', 'file_name': 'ci.json', 'mime_type': 'text/plain', 'hash': 837753512088508714, 'source_dataset': 'data'}


#include "rt5350.dtsi"

#include <dt-bindings/gpio/gpio.h>

/ {
	compatible = "nixcore,x1", "ralink,rt5350-soc";

	chosen {
		bootargs = "console=ttyS1,57600";
	};

	gpio-export {
		compatible = "gpio-export";
		#size-cells = <0>;

		gpio0 {
			gpio-export,name = "gpio0";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
		};

		gpio1 {
			gpio-export,name = "gpio1";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
		};

		/* GPIOs 1-6 are I2C,SPI */
		/* GPIO 7-14 are uart1 */
		/* GPIOs 15 & 16 are uart2 */
		/* JTAG */

		gpio17 {
			/* JTAG_TDO */
			gpio-export,name = "gpio17";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
		};

		gpio18 {
			/* JTAG_TDI */
			gpio-export,name = "gpio18";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
		};

		gpio19 {
			/* JTAG_TMS */
			gpio-export,name = "gpio19";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
		};

		gpio20 {
			/* JTAG_TCLK */
			gpio-export,name = "gpio20";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
		};

		gpio21 {
			/* JTAG_TRST_N */
			gpio-export,name = "gpio21";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
		};

		/* ETH LEDs */
		/*
		gpio22 {
			gpio-export,name = "gpio22";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
		};

		gpio23 {
			gpio-export,name = "gpio23";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
		};

		gpio24 {
			gpio-export,name = "gpio24";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
		};

		gpio25 {
			gpio-export,name = "gpio25";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
		};

		*/
		gpio26 {
			/* ETH4_LED */
			gpio-export,name = "gpio26";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
		};

		gpio27 {
			/* spi_cs1 */
			gpio-export,name = "gpio27";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
		};
	};
};

&gpio0 {
	status = "okay";
};

&gpio1 {
	status = "okay";
};

&i2c {
	status = "okay";
};

&uart {
	status = "okay";
	reset-names = "gpio uartf";
};

&pinctrl {
	state_default: pinctrl0 {
		gpio {
			ralink,group = "jtag", "led", "spi_cs1";
			ralink,function = "gpio";
		};
	};
};

&ethernet {
	mtd-mac-address = <&factory 0x4>;
};

&esw {
	mediatek,portmap = <0x17>;
};

&wmac {
	ralink,mtd-eeprom = <&factory 0>;
};

&ehci {
	status = "okay";
};

&ohci {
	status = "okay";
};

{'repo_name': 'Lienol/openwrt', 'stars': '939', 'repo_language': 'C', 'file_name': 'cdefs.h', 'mime_type': 'text/x-c', 'hash': -3144494339914678183, 'source_dataset': 'data'}


/*
 * Copyright Debezium Authors.
 *
 * Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
 */
package io.debezium.connector.sqlserver;

import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.assertNull;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.kafka.connect.data.Schema;
import org.apache.kafka.connect.data.Struct;
import org.apache.kafka.connect.source.SourceRecord;
import org.awaitility.Awaitility;
import org.fest.assertions.Assertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import io.debezium.config.Configuration;
import io.debezium.connector.sqlserver.SqlServerConnectorConfig.SnapshotMode;
import io.debezium.connector.sqlserver.util.TestHelper;
import io.debezium.data.Envelope;
import io.debezium.data.SchemaAndValueField;
import io.debezium.embedded.AbstractConnectorTest;
import io.debezium.junit.EqualityCheck;
import io.debezium.junit.SkipTestRule;
import io.debezium.junit.SkipWhenKafkaVersion;
import io.debezium.junit.SkipWhenKafkaVersion.KafkaVersion;
import io.debezium.util.Collect;
import io.debezium.util.Testing;

/**
 * Integration test for the Debezium SQL Server connector.
 *
 * @author Jiri Pechanec
 */
@SkipWhenKafkaVersion(check = EqualityCheck.EQUAL, value = KafkaVersion.KAFKA_1XX, description = "Not compatible with Kafka 1.x")
public class TransactionMetadataIT extends AbstractConnectorTest {

    private SqlServerConnection connection;

    @Rule
    public SkipTestRule skipRule = new SkipTestRule();

    @Before
    public void before() throws SQLException {
        TestHelper.createTestDatabase();
        connection = TestHelper.testConnection();
        connection.execute(
                "CREATE TABLE tablea (id int primary key, cola varchar(30))",
                "CREATE TABLE tableb (id int primary key, colb varchar(30))",
                "INSERT INTO tablea VALUES(1, 'a')");
        TestHelper.enableTableCdc(connection, "tablea");
        TestHelper.enableTableCdc(connection, "tableb");

        initializeConnectorTestFramework();
        Testing.Files.delete(TestHelper.DB_HISTORY_PATH);
        // Testing.Print.enable();
    }

    @After
    public void after() throws SQLException {
        if (connection != null) {
            connection.close();
        }
    }

    @Test
    public void transactionMetadata() throws Exception {
        final int RECORDS_PER_TABLE = 5;
        final int ID_START = 10;
        final Configuration config = TestHelper.defaultConfig()
                .with(SqlServerConnectorConfig.SNAPSHOT_MODE, SnapshotMode.INITIAL)
                .with(SqlServerConnectorConfig.PROVIDE_TRANSACTION_METADATA, true)
                .build();

        start(SqlServerConnector.class, config);
        assertConnectorIsRunning();

        // Testing.Print.enable();
        // Wait for snapshot completion
        consumeRecordsByTopic(1);

        connection.setAutoCommit(false);
        final String[] inserts = new String[RECORDS_PER_TABLE * 2];
        for (int i = 0; i < RECORDS_PER_TABLE; i++) {
            final int id = ID_START + i;
            inserts[2 * i] = "INSERT INTO tablea VALUES(" + id + ", 'a')";
            inserts[2 * i + 1] = "INSERT INTO tableb VALUES(" + id + ", 'b')";
        }
        connection.execute(inserts);
        connection.setAutoCommit(true);

        connection.execute("INSERT INTO tableb VALUES(1000, 'b')");

        // BEGIN, data, END, BEGIN, data
        final SourceRecords records = consumeRecordsByTopic(1 + RECORDS_PER_TABLE * 2 + 1 + 1 + 1);
        final List<SourceRecord> tableA = records.recordsForTopic("server1.dbo.tablea");
        final List<SourceRecord> tableB = records.recordsForTopic("server1.dbo.tableb");
        final List<SourceRecord> tx = records.recordsForTopic("server1.transaction");
        Assertions.assertThat(tableA).hasSize(RECORDS_PER_TABLE);
        Assertions.assertThat(tableB).hasSize(RECORDS_PER_TABLE + 1);
        Assertions.assertThat(tx).hasSize(3);

        final List<SourceRecord> all = records.allRecordsInOrder();
        final String txId = assertBeginTransaction(all.get(0));

        long counter = 1;
        for (int i = 1; i <= 2 * RECORDS_PER_TABLE; i++) {
            assertRecordTransactionMetadata(all.get(i), txId, counter, (counter + 1) / 2);
            counter++;
        }

        assertEndTransaction(all.get(2 * RECORDS_PER_TABLE + 1), txId, 2 * RECORDS_PER_TABLE,
                Collect.hashMapOf("testDB.dbo.tablea", RECORDS_PER_TABLE, "testDB.dbo.tableb", RECORDS_PER_TABLE));
        stopConnector();
    }

    private void restartInTheMiddleOfTx(boolean restartJustAfterSnapshot, boolean afterStreaming) throws Exception {
        final int RECORDS_PER_TABLE = 30;
        final int TABLES = 2;
        final int ID_START = 10;
        final int ID_RESTART = 1000;
        final int HALF_ID = ID_START + RECORDS_PER_TABLE / 2;
        final Configuration config = TestHelper.defaultConfig()
                .with(SqlServerConnectorConfig.SNAPSHOT_MODE, SnapshotMode.INITIAL)
                .with(SqlServerConnectorConfig.PROVIDE_TRANSACTION_METADATA, true)
                .build();

        // Testing.Print.enable();

        if (restartJustAfterSnapshot) {
            start(SqlServerConnector.class, config);
            assertConnectorIsRunning();

            // Wait for snapshot to be completed
            consumeRecordsByTopic(1);
            stopConnector();
            connection.execute("INSERT INTO tablea VALUES(-1, '-a')");

            Awaitility.await().atMost(30, TimeUnit.SECONDS).until(() -> {
                if (!connection.getMaxLsn().isAvailable()) {
                    return false;
                }

                for (SqlServerChangeTable ct : connection.listOfChangeTables()) {
                    final String tableName = ct.getChangeTableId().table();
                    if (tableName.endsWith("dbo_" + connection.getNameOfChangeTable("tablea"))) {
                        try {
                            final Lsn minLsn = connection.getMinLsn(tableName);
                            final Lsn maxLsn = connection.getMaxLsn();
                            final AtomicReference<Boolean> found = new AtomicReference<>(false);
                            SqlServerChangeTable[] tables = Collections.singletonList(ct).toArray(new SqlServerChangeTable[]{});
                            connection.getChangesForTables(tables, minLsn, maxLsn, resultsets -> {
                                final ResultSet rs = resultsets[0];
                                while (rs.next()) {
                                    if (rs.getInt("id") == -1) {
                                        found.set(true);
                                        break;
                                    }
                                }
                            });
                            return found.get();
                        }
                        catch (Exception e) {
                            org.junit.Assert.fail("Failed to fetch changes for tablea: " + e.getMessage());
                        }
                    }
                }
                return false;
            });
        }

        start(SqlServerConnector.class, config, record -> {
            if (!"server1.dbo.tablea.Envelope".equals(record.valueSchema().name())) {
                return false;
            }
            final Struct envelope = (Struct) record.value();
            final Struct after = envelope.getStruct("after");
            final Integer id = after.getInt32("id");
            final String value = after.getString("cola");
            return id != null && id == HALF_ID && "a".equals(value);
        });
        assertConnectorIsRunning();

        String firstTxId = null;
        if (restartJustAfterSnapshot) {
            // Transaction begin
            SourceRecord begin = consumeRecordsByTopic(1).allRecordsInOrder().get(0);
            firstTxId = assertBeginTransaction(begin);
        }

        // Wait for snapshot to be completed or a first streaming message delivered
        consumeRecordsByTopic(1);

        if (afterStreaming) {
            connection.execute("INSERT INTO tablea VALUES(-2, '-a')");
            final SourceRecords records = consumeRecordsByTopic(2);
            final List<SchemaAndValueField> expectedRow = Arrays.asList(
                    new SchemaAndValueField("id", Schema.INT32_SCHEMA, -2),
                    new SchemaAndValueField("cola", Schema.OPTIONAL_STRING_SCHEMA, "-a"));
            assertRecord(((Struct) records.allRecordsInOrder().get(1).value()).getStruct(Envelope.FieldName.AFTER), expectedRow);
            SourceRecord begin = records.allRecordsInOrder().get(0);
            firstTxId = assertBeginTransaction(begin);
        }

        connection.setAutoCommit(false);
        for (int i = 0; i < RECORDS_PER_TABLE; i++) {
            final int id = ID_START + i;
            connection.executeWithoutCommitting(
                    "INSERT INTO tablea VALUES(" + id + ", 'a')");
            connection.executeWithoutCommitting(
                    "INSERT INTO tableb VALUES(" + id + ", 'b')");
        }
        connection.connection().commit();

        // End of previous TX, BEGIN of new TX, change records
        final int txBeginIndex = firstTxId != null ? 1 : 0;
        int expectedRecords = txBeginIndex + 1 + RECORDS_PER_TABLE;
        List<SourceRecord> records = consumeRecordsByTopic(expectedRecords).allRecordsInOrder();

        assertThat(records).hasSize(expectedRecords);

        if (firstTxId != null) {
            assertEndTransaction(records.get(0), firstTxId, 1, Collect.hashMapOf("testDB.dbo.tablea", 1));
        }
        final String batchTxId = assertBeginTransaction(records.get(txBeginIndex));

        SourceRecord lastRecordForOffset = records.get(RECORDS_PER_TABLE + txBeginIndex);
        Struct value = (Struct) lastRecordForOffset.value();
        final List<SchemaAndValueField> expectedLastRow = Arrays.asList(
                new SchemaAndValueField("id", Schema.INT32_SCHEMA, HALF_ID - 1),
                new SchemaAndValueField("colb", Schema.OPTIONAL_STRING_SCHEMA, "b"));
        assertRecord((Struct) value.get("after"), expectedLastRow);
        assertRecordTransactionMetadata(lastRecordForOffset, batchTxId, RECORDS_PER_TABLE, RECORDS_PER_TABLE / 2);

        stopConnector();
        start(SqlServerConnector.class, config);
        assertConnectorIsRunning();

        SourceRecords sourceRecords = consumeRecordsByTopic(RECORDS_PER_TABLE);
        records = sourceRecords.allRecordsInOrder();
        assertThat(records).hasSize(RECORDS_PER_TABLE);

        List<SourceRecord> tableA = sourceRecords.recordsForTopic("server1.dbo.tablea");
        List<SourceRecord> tableB = sourceRecords.recordsForTopic("server1.dbo.tableb");
        for (int i = 0; i < RECORDS_PER_TABLE / 2; i++) {
            final int id = HALF_ID + i;
            final SourceRecord recordA = tableA.get(i);
            final SourceRecord recordB = tableB.get(i);
            final List<SchemaAndValueField> expectedRowA = Arrays.asList(
                    new SchemaAndValueField("id", Schema.INT32_SCHEMA, id),
                    new SchemaAndValueField("cola", Schema.OPTIONAL_STRING_SCHEMA, "a"));
            final List<SchemaAndValueField> expectedRowB = Arrays.asList(
                    new SchemaAndValueField("id", Schema.INT32_SCHEMA, id),
                    new SchemaAndValueField("colb", Schema.OPTIONAL_STRING_SCHEMA, "b"));

            final Struct valueA = (Struct) recordA.value();
            assertRecord((Struct) valueA.get("after"), expectedRowA);
            assertNull(valueA.get("before"));

            final Struct valueB = (Struct) recordB.value();
            assertRecord((Struct) valueB.get("after"), expectedRowB);
            assertNull(valueB.get("before"));

            assertRecordTransactionMetadata(recordA, batchTxId, RECORDS_PER_TABLE + 2 * i + 1, RECORDS_PER_TABLE / 2 + i + 1);
            assertRecordTransactionMetadata(recordB, batchTxId, RECORDS_PER_TABLE + 2 * i + 2, RECORDS_PER_TABLE / 2 + i + 1);
        }

        for (int i = 0; i < RECORDS_PER_TABLE; i++) {
            final int id = ID_RESTART + i;
            connection.executeWithoutCommitting(
                    "INSERT INTO tablea VALUES(" + id + ", 'a')");
            connection.executeWithoutCommitting(
                    "INSERT INTO tableb VALUES(" + id + ", 'b')");
            connection.connection().commit();
        }

        // END of previous TX, data records, BEGIN of TX for every pair of record, END of TX for every pair of record but last
        sourceRecords = consumeRecordsByTopic(1 + RECORDS_PER_TABLE * TABLES + (2 * RECORDS_PER_TABLE - 1));
        tableA = sourceRecords.recordsForTopic("server1.dbo.tablea");
        tableB = sourceRecords.recordsForTopic("server1.dbo.tableb");
        List<SourceRecord> txMetadata = sourceRecords.recordsForTopic("server1.transaction");

        Assertions.assertThat(tableA).hasSize(RECORDS_PER_TABLE);
        Assertions.assertThat(tableB).hasSize(RECORDS_PER_TABLE);
        Assertions.assertThat(txMetadata).hasSize(1 + 2 * RECORDS_PER_TABLE - 1);
        assertEndTransaction(txMetadata.get(0), batchTxId, 2 * RECORDS_PER_TABLE,
                Collect.hashMapOf("testDB.dbo.tablea", RECORDS_PER_TABLE, "testDB.dbo.tableb", RECORDS_PER_TABLE));

        for (int i = 0; i < RECORDS_PER_TABLE; i++) {
            final int id = i + ID_RESTART;
            final SourceRecord recordA = tableA.get(i);
            final SourceRecord recordB = tableB.get(i);
            final List<SchemaAndValueField> expectedRowA = Arrays.asList(
                    new SchemaAndValueField("id", Schema.INT32_SCHEMA, id),
                    new SchemaAndValueField("cola", Schema.OPTIONAL_STRING_SCHEMA, "a"));
            final List<SchemaAndValueField> expectedRowB = Arrays.asList(
                    new SchemaAndValueField("id", Schema.INT32_SCHEMA, id),
                    new SchemaAndValueField("colb", Schema.OPTIONAL_STRING_SCHEMA, "b"));

            final Struct valueA = (Struct) recordA.value();
            assertRecord((Struct) valueA.get("after"), expectedRowA);
            assertNull(valueA.get("before"));

            final Struct valueB = (Struct) recordB.value();
            assertRecord((Struct) valueB.get("after"), expectedRowB);
            assertNull(valueB.get("before"));

            final String txId = assertBeginTransaction(txMetadata.get(2 * i + 1));
            assertRecordTransactionMetadata(recordA, txId, 1, 1);
            assertRecordTransactionMetadata(recordB, txId, 2, 1);
            if (i < RECORDS_PER_TABLE - 1) {
                assertEndTransaction(txMetadata.get(2 * i + 2), txId, 2, Collect.hashMapOf("testDB.dbo.tablea", 1, "testDB.dbo.tableb", 1));
            }
        }
    }

    @Test
    public void restartInTheMiddleOfTxAfterSnapshot() throws Exception {
        restartInTheMiddleOfTx(true, false);
    }

    @Test
    public void restartInTheMiddleOfTxAfterCompletedTx() throws Exception {
        restartInTheMiddleOfTx(false, true);
    }

    @Test
    public void restartInTheMiddleOfTx() throws Exception {
        restartInTheMiddleOfTx(false, false);
    }

    private void assertRecord(Struct record, List<SchemaAndValueField> expected) {
        expected.forEach(schemaAndValueField -> schemaAndValueField.assertFor(record));
    }
}

{'repo_name': 'debezium/debezium', 'stars': '3394', 'repo_language': 'Java', 'file_name': 'MySqlDdlParserPerf.java', 'mime_type': 'text/x-java', 'hash': 2472176953723017668, 'source_dataset': 'data'}


/*
 * Copyright (c) 2016 Mockito contributors
 * This program is made available under the terms of the MIT License.
 */
package org.mockito.internal.invocation;

import java.util.Comparator;

import org.mockito.invocation.Invocation;

/**
 * Compares invocations based on the sequence number
 */
public class InvocationComparator implements Comparator<Invocation> {
    public int compare(Invocation o1, Invocation o2) {
        return Integer.valueOf(o1.getSequenceNumber()).compareTo(o2.getSequenceNumber());
    }
}

{'repo_name': 'mockito/mockito', 'stars': '10792', 'repo_language': 'Java', 'file_name': 'config.yml', 'mime_type': 'text/plain', 'hash': 6982023770314501571, 'source_dataset': 'data'}


#
# Copyright World Wide Web Consortium, (Massachusetts Institute of
# Technology, Institut National de Recherche en Informatique et en
# Automatique, Keio University).
#
# All Rights Reserved.
#
# Please see the full Copyright clause at
# <http://www.w3.org/Consortium/Legal/copyright-software.html>
#
# $Id: test0012.nt,v 1.3 2001/10/04 16:01:45 barstow Exp $
#
#####################################################################
<http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0012.rdf#container> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> .
<http://www.w3.org/2000/10/rdf-tests/rdfcore/rdf-ns-prefix-confusion/test0012.rdf#container> <http://www.w3.org/1999/02/22-rdf-syntax-ns#_1> "bar" .

{'repo_name': 'RDFLib/rdflib', 'stars': '1256', 'repo_language': 'Python', 'file_name': 'rdf-test-13.n3', 'mime_type': 'text/plain', 'hash': -223014780061982696, 'source_dataset': 'data'}


import { Reducer }       from 'redux';
import { BlocksSection } from '../../state/blocks';
import { IBlocksNew }    from '../actions/actionTypes';

export const BlocksNewReducer: Reducer<BlocksSection, IBlocksNew> =
    (state: BlocksSection, action: IBlocksNew): BlocksSection => ({
        ...state,
        blocks: {
            ...state.blocks,
            [action.number]: action.block_infos
        }
    });

{'repo_name': 'ticket721/ethvtx', 'stars': '123', 'repo_language': 'TypeScript', 'file_name': 'index.tsx', 'mime_type': 'text/x-java', 'hash': -8002720808244996568, 'source_dataset': 'data'}


#!/usr/bin/env bash
set -e

current_dir="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

"$current_dir/../../gradlew" generateLogic

output=$(git status --porcelain);
if [ -n "$output" ]; then
  echo "You forgot to commit the changes of generateLogic - run \`./gradlew generateLogic\` again and commit them. Following files are affected:"
  printf "%s\n" "$output";
  git diff --color -R;
  exit 1;
fi

{'repo_name': 'robstoll/atrium', 'stars': '293', 'repo_language': 'Kotlin', 'file_name': 'DescriptionComparableAssertion.kt', 'mime_type': 'text/plain', 'hash': -5962313512382779870, 'source_dataset': 'data'}


/*
 * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "CallFrame.h"
#include "Error.h"

namespace JSC {

inline bool typeError(ExecState* exec, ThrowScope& scope, bool throwException, ASCIILiteral message)
{
    if (throwException)
        throwTypeError(exec, scope, message);
    return false;
}

} // namespace JSC

{'repo_name': 'ultralight-ux/WebCore', 'stars': '113', 'repo_language': 'C++', 'file_name': 'WebKitTargetConditionals.xcconfig', 'mime_type': 'text/plain', 'hash': 3768976780654461920, 'source_dataset': 'data'}


#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
#
# Copyright (c) 2010-2018 Oracle and/or its affiliates. All rights reserved.
#
# The contents of this file are subject to the terms of either the GNU
# General Public License Version 2 only ("GPL") or the Common Development
# and Distribution License("CDDL") (collectively, the "License").  You
# may not use this file except in compliance with the License.  You can
# obtain a copy of the License at
# https://oss.oracle.com/licenses/CDDL+GPL-1.1
# or LICENSE.txt.  See the License for the specific
# language governing permissions and limitations under the License.
#
# When distributing the software, include this License Header Notice in each
# file and include the License file at LICENSE.txt.
#
# GPL Classpath Exception:
# Oracle designates this particular file as subject to the "Classpath"
# exception as provided by Oracle in the GPL Version 2 section of the License
# file that accompanied this code.
#
# Modifications:
# If applicable, add the following below the License Header, with the fields
# enclosed by brackets [] replaced by your own identifying information:
# "Portions Copyright [year] [name of copyright owner]"
#
# Contributor(s):
# If you wish your version of this file to be governed by only the CDDL or
# only the GPL Version 2, indicate your decision by adding "[Contributor]
# elects to include this software in this distribution under the [CDDL or GPL
# Version 2] license."  If you don't indicate a single choice of license, a
# recipient has the option to distribute your version of this file under
# either the CDDL, the GPL Version 2 or to extend the choice of license to
# its licensees as provided above.  However, if you add GPL Version 2 code
# and therefore, elected the GPL Version 2 license, then the option applies
# only if the new code is made subject to such option by the copyright
# holder.
#

containers=jruby, web, php
jruby.application=app/controllers/application.rb
web.application=WEB-INF/web.xml
php.urlpattern=.*php$

{'repo_name': 'javaee/glassfish', 'stars': '707', 'repo_language': 'Java', 'file_name': 'build.properties', 'mime_type': 'text/plain', 'hash': -3789546377933317557, 'source_dataset': 'data'}


<!DOCTYPE html>

	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<link rel="stylesheet" href="../css/smartphoto.min.css">
	<link rel="stylesheet" href="./assets/style.css">
	<title>jquery-smartphoto.js</title>

jquery-smartphoto.js

{'repo_name': 'appleple/SmartPhoto', 'stars': '827', 'repo_language': 'JavaScript', 'file_name': 'jquery-smartphoto.js', 'mime_type': 'text/plain', 'hash': 874004839387005114, 'source_dataset': 'data'}


function Resolve-PScriboStyleColor
{
<#
    .SYNOPSIS
        Resolves a HTML color format or Word color constant to a RGB value
#>
    [CmdletBinding()]
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory, ValueFromPipeline, Position = 0)]
        [ValidateNotNull()]
        [System.String] $Color
    )
    begin
    {
        # http://www.jadecat.com/tuts/colorsplus.html
        $wordColorConstants = @{
            AliceBlue            = 'F0F8FF'
            AntiqueWhite         = 'FAEBD7'
            Aqua                 = '00FFFF'
            Aquamarine           = '7FFFD4'
            Azure                = 'F0FFFF'
            Beige                = 'F5F5DC'
            Bisque               = 'FFE4C4'
            Black                = '000000'
            BlanchedAlmond       = 'FFEBCD'
            Blue                 = '0000FF'
            BlueViolet           = '8A2BE2'
            Brown                = 'A52A2A'
            BurlyWood            = 'DEB887'
            CadetBlue            = '5F9EA0'
            Chartreuse           = '7FFF00'
            Chocolate            = 'D2691E'
            Coral                = 'FF7F50'
            CornflowerBlue       = '6495ED'
            Cornsilk             = 'FFF8DC'
            Crimson              = 'DC143C'
            Cyan                 = '00FFFF'
            DarkBlue             = '00008B'
            DarkCyan             = '008B8B'
            DarkGoldenrod        = 'B8860B'
            DarkGray             = 'A9A9A9'
            DarkGreen            = '006400'
            DarkKhaki            = 'BDB76B'
            DarkMagenta          = '8B008B'
            DarkOliveGreen       = '556B2F'
            DarkOrange           = 'FF8C00'
            DarkOrchid           = '9932CC'
            DarkRed              = '8B0000'
            DarkSalmon           = 'E9967A'
            DarkSeaGreen         = '8FBC8F'
            DarkSlateBlue        = '483D8B'
            DarkSlateGray        = '2F4F4F'
            DarkTurquoise        = '00CED1'
            DarkViolet           = '9400D3'
            DeepPink             = 'FF1493'
            DeepSkyBlue          = '00BFFF'
            DimGray              = '696969'
            DodgerBlue           = '1E90FF'
            Firebrick            = 'B22222'
            FloralWhite          = 'FFFAF0'
            ForestGreen          = '228B22'
            Fuchsia              = 'FF00FF'
            Gainsboro            = 'DCDCDC'
            GhostWhite           = 'F8F8FF'
            Gold                 = 'FFD700'
            Goldenrod            = 'DAA520'
            Gray                 = '808080'
            Green                = '008000'
            GreenYellow          = 'ADFF2F'
            Honeydew             = 'F0FFF0'
            HotPink              = 'FF69B4'
            IndianRed            = 'CD5C5C'
            Indigo               = '4B0082'
            Ivory                = 'FFFFF0'
            Khaki                = 'F0E68C'
            Lavender             = 'E6E6FA'
            LavenderBlush        = 'FFF0F5'
            LawnGreen            = '7CFC00'
            LemonChiffon         = 'FFFACD'
            LightBlue            = 'ADD8E6'
            LightCoral           = 'F08080'
            LightCyan            = 'E0FFFF'
            LightGoldenrodYellow = 'FAFAD2'
            LightGreen           = '90EE90'
            LightGrey            = 'D3D3D3'
            LightPink            = 'FFB6C1'
            LightSalmon          = 'FFA07A'
            LightSeaGreen        = '20B2AA'
            LightSkyBlue         = '87CEFA'
            LightSlateGray       = '778899'
            LightSteelBlue       = 'B0C4DE'
            LightYellow          = 'FFFFE0'
            Lime                 = '00FF00'
            LimeGreen            = '32CD32'
            Linen                = 'FAF0E6'
            Magenta              = 'FF00FF'
            Maroon               = '800000'
            McMintGreen          = 'BED6C9'
            MediumAuqamarine     = '66CDAA'
            MediumBlue           = '0000CD'
            MediumOrchid         = 'BA55D3'
            MediumPurple         = '9370D8'
            MediumSeaGreen       = '3CB371'
            MediumSlateBlue      = '7B68EE'
            MediumSpringGreen    = '00FA9A'
            MediumTurquoise      = '48D1CC'
            MediumVioletRed      = 'C71585'
            MidnightBlue         = '191970'
            MintCream            = 'F5FFFA'
            MistyRose            = 'FFE4E1'
            Moccasin             = 'FFE4B5'
            NavajoWhite          = 'FFDEAD'
            Navy                 = '000080'
            OldLace              = 'FDF5E6'
            Olive                = '808000'
            OliveDrab            = '688E23'
            Orange               = 'FFA500'
            OrangeRed            = 'FF4500'
            Orchid               = 'DA70D6'
            PaleGoldenRod        = 'EEE8AA'
            PaleGreen            = '98FB98'
            PaleTurquoise        = 'AFEEEE'
            PaleVioletRed        = 'D87093'
            PapayaWhip           = 'FFEFD5'
            PeachPuff            = 'FFDAB9'
            Peru                 = 'CD853F'
            Pink                 = 'FFC0CB'
            Plum                 = 'DDA0DD'
            PowderBlue           = 'B0E0E6'
            Purple               = '800080'
            Red                  = 'FF0000'
            RosyBrown            = 'BC8F8F'
            RoyalBlue            = '4169E1'
            SaddleBrown          = '8B4513'
            Salmon               = 'FA8072'
            SandyBrown           = 'F4A460'
            SeaGreen             = '2E8B57'
            Seashell             = 'FFF5EE'
            Sienna               = 'A0522D'
            Silver               = 'C0C0C0'
            SkyBlue              = '87CEEB'
            SlateBlue            = '6A5ACD'
            SlateGray            = '708090'
            Snow                 = 'FFFAFA'
            SpringGreen          = '00FF7F'
            SteelBlue            = '4682B4'
            Tan                  = 'D2B48C'
            Teal                 = '008080'
            Thistle              = 'D8BFD8'
            Tomato               = 'FF6347'
            Turquoise            = '40E0D0'
            Violet               = 'EE82EE'
            Wheat                = 'F5DEB3'
            White                = 'FFFFFF'
            WhiteSmoke           = 'F5F5F5'
            Yellow               = 'FFFF00'
            YellowGreen          = '9ACD32'
        }
    }
    process
    {
        $pscriboColor = $Color
        if ($wordColorConstants.ContainsKey($pscriboColor))
        {
            return $wordColorConstants[$pscriboColor].ToLower()
        }
        elseif ($pscriboColor.Length -eq 6 -or $pscriboColor.Length -eq 3)
        {
            $pscriboColor = '#{0}' -f $pscriboColor
        }
        elseif ($pscriboColor.Length -eq 7 -or $pscriboColor.Length -eq 4)
        {
            if (-not ($pscriboColor.StartsWith('#')))
            {
                return $null
            }
        }
        if ($pscriboColor -notmatch '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')
        {
            return $null
        }
        return $pscriboColor.TrimStart('#').ToLower()
    }
}

{'repo_name': 'iainbrighton/PScribo', 'stars': '178', 'repo_language': 'PowerShell', 'file_name': 'about_PScriboStyles.help.txt', 'mime_type': 'text/plain', 'hash': 7287115572651776115, 'source_dataset': 'data'}


<%@ Application Codebehind="Global.asax.cs" Inherits="MiddlewareBot.WebApiApplication" Language="C#" %>

{'repo_name': 'microsoft/WhatTheHack', 'stars': '508', 'repo_language': 'HTML', 'file_name': 'stream_2.txt', 'mime_type': 'text/plain', 'hash': -2747248463246682366, 'source_dataset': 'data'}


---
date: 2020-06-02
title: Scaling stories - comment les startups se sont plantées
author: cyppan
slug: scaling-stories-comment-les-startups-se-sont-plantees
---

> - "Ca ne fonctionne pas, mes enfants n'arrivent pas à se connecter à votre service !"
> - "Nous sommes désolé notre équipe technique est mobilisée à 100% sur ce problème c'est une situation exceptionnelle… Nous vous tenons au courant."

C'est le genre de tweet ou de message LinkedIn qu'on a pu voir se multiplier avec le confinement récent dû au Covid-19. En effet les services web, et en particulier les outils de communication ou les programmes du secteur de l'EdTech (education technology), ont dû faire face à un usage particulièrement intense et soutenu ces derniers temps. Il n'y en a que peu à ma connaissance qui ont été capables de maintenir une qualité de service acceptable (Slack et Zoom ont particulièrement brillé sur ce sujet). Si la plupart ont mis en place des solutions minutes comme des queues de connexion,
d'autres encore ont été forcés de désactiver leur service pour une "maintenance" à durée indéterminée…

Même en étant compréhensifs, face à un service planté, on a vite fait de changer. Après tout, avec le choix plus que fourni de services dont on dispose, pourquoi se priver ? Le problème c'est qu'après la crise, il est fort probable que nous ne reviendrons pas au service qu'on avait pourtant trouvé si cool au premier abord… Aïe, pour une startup c'est beaucoup de clients perdus, peut-être assez pour ne jamais retrouver de la traction. Une mort pénible donc pour un business, victime lui aussi du virus.

Mais 🧐

* *Ces entreprises n'auraient-elles pas pu mieux anticiper ?*
* *N'auraient-elles pas pu avoir une meilleure tech à la base, crise ou pas crise ?*
* *Et une fois devant le problème, n'auraient-elles pas pu mieux s'adapter et plus rapidement ?*

## le modèle de "scaling maturity"

![modèle de scaling maturity](/public/images/articles/2020-04-02-scaling-stories-comment-les-startups-se-sont-plantees/scaling-maturity-fr.png)

En premier lieu j'aimerais introduire le concept de *scaling maturity*. "To scale" c'est l'art d'adapter (automatiquement ou non) sa stack technique afin de répondre à la demande en entrée. Et reconnaissons déjà que Zoom et Slack sont beaucoup plus matures que (par exemple) de jeunes startups de l'EdTech.
Analysons les à l'aide du modèle de *scaling maturity*.

1 - **Volume d'usage nominal** : Slack ou Zoom avaient déjà un trafic (très) important, le pic d'activité représente un pourcentage plus petit que pour une startup pour qui c'est peut-être un boost de 100 ou 1000 fois l'activité habituelle.
2 - **Maturité du produit** : Ils ont eu le temps de connaître les spécificités de leur usage, les caractéristiques d'accès aux données, les points de fragilité de leur système, …
3 - **Compétences techniques** : Ils ont probablement une équipe tech plus grande et plus expérimentée.

Pour synthétiser, ils en savent beaucoup sur la façon dont leur produit est utilisé et quelle est leur roadmap, et donc savent bien quel type d'effort concentrer pour s'adapter à la demande supplémentaire. En plus, leur infrastructure actuelle peut déjà encaisser un volume conséquent.

De l'autre côté, les jeunes services web se sont retrouvés submergés, cherchant de l'aide désespérement et des solutions pour [sharder](https://en.wikipedia.org/wiki/Shard_%28database_architecture%29) et répliquer leur base de donnée relationnelle existante (plus à ce sujet un peu plus loin).
Je prends à présent l'exemple hypothétique d'une startup EdTech offrant un service de classe en ligne innovant.

1 - **Volume d'usage nominal** : Quelques clients aiment leur produit, "c'est le futur", ils croient au potentiel de croissance et l'ajout de fonctionnalités avec le temps. Il y a donc un faible volume d'utilisation pour le moment et une croissance mesurée attendue, ils ont opté pour quelques serveurs OVH économiquement intéressants.
2 - **Maturité du produit** : Leur produit est très jeune, ils misent sur l'innovation et des boucles de feedback rapides pour l'étoffer.
3 - **Compétences techniques** : Des stagiaires, peut-être de jeunes employés, parfois des fondateurs qui font eux-mêmes les premiers prototypes. A ce niveau les salaires pèsent beaucoup dans la balance.

Je m'autorise ici une conclusion préliminaire à la première question : les entreprises n'auraient pas pu anticiper, et même j'irai plus loin pour les plus petites d'entre elles, elles ne devaient pas le faire… En effet, si on souhaite créer un produit avec du scaling "infini" dès le début, ça implique d'investir beaucoup **en temps et en argent**. Deux ressources précieuses que l'on préfère rationnellement investir sur d'autres sujets quand on est un business en phase de démarrage (comme trouver sa place sur le marché, ajouter des fonctionnalités, croître, …).

> ![cygne noir](/public/images/articles/2020-04-02-scaling-stories-comment-les-startups-se-sont-plantees/black-swan.jpg)
> Covid-19 est un très bon exemple de ce qu'on appelle un évènement ["cygne noir"](https://fr.wikipedia.org/wiki/Th%C3%A9orie_du_cygne_noir)
> Un évènement qui est très rare, a des répercussions massives, que les entreprises n'avaient donc pas prévu.
> En effet ce point est assez évident, néanmoins je trouve cet "interlude du cygne" bienvenu 😉

J'ai pu parler récemment avec quelques startups EdTech qui recherchaient des solutions urgemment… Elles en étaient au même point : elles ne pouvaient plus doper les ressources de leur base de donnée relationnelle (**scale up**). Après avoir essayé d'ajouter du cache, déployer de nouveau nœuds, de refactorer leurs applications, le point limitant final restait la base de donnée… La seule solution était donc de sharder (**scale out**) afin de répartir les écritures sur plusieurs instances en parallèle. Ils cherchaient donc des solutions intelligentes (dans le sens autonomes) à ajouter en amont de leur base de donnée afin de pouvoir continuer le scale. Pas si évident, et plutôt cher…
Et je ne parlerai même pas de la gestion de la **migration** dans ce contexte !

Pour avoir une idée de la difficulté de sharder une base de donnée existante, je dirais que plus le requêtage des données est global et complexe (par exemple de l'agrégation cross-compte), le plus intelligent et cher devra être le proxy en amont. Ca peut aller d'une simple hash-distribution à un "query planner" distribué complexe, et difficile à scale lui aussi par ailleurs.

A la lumière du modèle de *scaling maturity*, il est assez clair qu'on ne peut les blâmer de ne pas avoir eu ces mécanismes de scale déjà en place auparavant, mais elles auraient pu au moins avoir mieux planifié leur **prochaine étape de scale**.

## Comment on scale efficacement quand on est une startup?

Déconstruisons déjà ce qui doit être "scaled" :

* **la capacité serveur** : La maîtrise des coûts implique un dimensionnement adapté en terme de taille CPU/RAM/storage. Par serveur, j'entends noeuds physiques, virtuels ou containers.
* **les patterns d'accès aux données** : C'est à dire connaître son usage, éviter de gérer des états partagés, des requêtes globales, préférer l'immutabilité, …
* **l'intervention humaine et la maintenance** : Plus on automatise, plus vite on peut itérer, des outils comme Github, CircleCI ou terraform sont précieux.
* **le refactoring de code** : "scale" veut souvent dire pré-calculer des états, utiliser du cache, plus de synchronisation, tout ça doit être codé et maintenu également…

Note : si votre produit n'a pas encore de traction réelle, se préoccuper de ce sujet est probablement prématuré et inutile, un rapide prototype MVC avec la techno que vous connaissez déjà fera tout à fait l'affaire.

Mais si vous avez de l'usage et une première idée de la direction du produit, alors il y a plusieurs possibilités. Si vous avez avec vous un fondateur au profil technique il sait certainement quoi faire. Sinon, et en particulier si vous avez levé des fonds, c'est une bonne idée de se faire accompagner sur le design de l'infrastructure dès à présent.

Explorons différentes stratégies.

### La stratégie de scaling infini

Dissipons immédiatement les nuages de fumée, il est théoriquement possible d'**approcher** une telle architecture mais ce sera très coûteux (en temps et en argent – encore une fois deux choses précieuses pour une startup), et potentiellement assez rigide.
La clé ici serait d'utiliser au maximum des services gérés de haut niveau qui tournent sur de grosses infrastructures clouds. Les services choisis devraient être 100% dynamiques, c'est à dire scale de manière autogérée : on ne devrait pas avoir à gérer de ressources physiques ou même virtuelles. Idéalement ces services intègreraient de base de la réplication (pour scale en lecture) et du sharding (pour scale en écriture) et pourraient être répartis dans différentes régions sur la planète.

Voici quelques exemples de services gérés de cet ordre :

* Base de donnée relationnelle : Google Cloud Spanner
* NoSQL synchronisation temps réel : Google Firestore
* Cluster de cache cross-region : AWS Elasticache
* Stockage de fichier distributé : AWS S3
* Data streaming : Google Pub/Sub
* Data warehouse : Google BigQuery

Hé oui, ça fait beaucoup de services Google, tout simplement parce qu'ils ont un train d'avance !

![courbe de scaling dynamique](/public/images/articles/2020-04-02-scaling-stories-comment-les-startups-se-sont-plantees/dynamic-scaling-curve-fr.png)

*Ici je me dois de nuancer cette courbe*

* Le prix est en fait très bas au démarrage : ces services offrent des niveaux d'utilisation gratuit pour un volume limité et/ou pendant une période limitée.
* Une fois un usage conséquent atteint, un tarif dégressif ou des techniques d'optimisation des coûts liées au provider viendront réduire la facture.

### La stratégie de scaling step-by-step

![courbe de scaling step by step](/public/images/articles/2020-04-02-scaling-stories-comment-les-startups-se-sont-plantees/static-scaling-curve-fr.png)

C'est la stratégie classique et probablement la plus efficace, on fait avec ce qu'on a à disposition au début (compétences, personnes) mais on essaie d'avoir toujours un coup d'avance. On reste conscient des points de fragilité du système, et on sait comment y remédier. On s'attache à planifier les prochaines migrations.
Ca nécessite en particulier :

* De développer une pipeline solide de monitoring et d'alerting. Il y a beaucoup d'outils pour faire ça aujourd'hui.
* De tester chaque migration. Car plus le système est distribué, le moins prévisibles seront les problèmes. Il est plus simple de tester avant de migrer.

Par exemple, les prochaines étapes de scale planifiées pourraient être :

* Sharder la base de donnée ou le stream de données.
* Conserver les données en silos isolés logiquement, afin de pouvoir scaler plus simplement le reste.
* Introduire un scaling automatique des services HTTP basé sur le trafic.

Le principal est de rester économique et intelligent : pour scale efficacement il faut scale dans les bonnes proportions et au bon moment. Trop tôt et ça coûtera trop cher, trop tard et la qualité de service tombera… C'est pourquoi avoir un feedback pertinent (automatisé) sur l'architecture est un réel plus.

Les clouds proposent souvent des metrics de monitoring intégrées, par exemple si on utilise les environnements AWS Beanstalk pour des services web il est fourni automatiquement les métriques suivantes :

* le nombre de requêtes
* la latence moyenne
* l'indice de charge du serveur (load)
* le CPU
* le réseau entrant/sortant
* …

Il est très facile alors de les visualiser en dashboards, de configurer de l'alerting, ou même d'activer de l'auto-scaling basé sur le pourcentage de CPU utilisé… Autant d'outils que l'on peut utiliser directement pour scaler ses web services correctement. Après tout, le plus d'informations (métriques) on a à la base, le mieux on peut prendre les bonnes décisions au final.

Bien entendu, scaler efficacement c'est scaler de manière appropriée, à chaque situation sa réponse adaptée !

Pour conclure, la bonne solution se situe probablement entre les deux stratégies. Ca dépendra du budget, de la complexité technique du produit, et des compétences à disposition, …
Au moins j'espère que vous avez une meilleure idée de comment anticiper le scale !

Scale safe 👋

{'repo_name': 'putaindecode/putaindecode.io', 'stars': '270', 'repo_language': 'Reason', 'file_name': 'generator.html', 'mime_type': 'text/html', 'hash': 5989691368464182417, 'source_dataset': 'data'}


<!DOCTYPE html>

        <title>progressbar组件</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <link type="text/css" rel="stylesheet" href="../style/avalon.doc.css">

模拟进度条，带label

<!DOCTYPE html>
<html>
    <head>
        <title>progressbar组件</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script src="../avalon.js"></script>

        <script>
            require(["progressbar/avalon.progressbar"], function() {
                avalon.define("test", function(vm) {
                    vm.progressbar = {
                        onComplete: function() {
                            avalon.log(this)
                            avalon.log('this bar is complete')
                        },
                        onInit: function(v) {
                            alert(v)
                        }
                    }
                    vm.$skipArray = ["progressbar"]
                    var v = 0
                        , timer
                    setTimeout(function() {
                        // 告知结束
                        avalon.vmodels.$aa.end(100)
                    }, 10000)
                })
                avalon.scan()
            })
        </script>
    </head>
    <body>
<div ms-controller="test">
        <h1>模拟进度条，带label</h1>
        <div ms-widget="progressbar,$aa" data-progressbar-simulate="100" data-progressbar-label="true">

        </div>

    </div>
</body>
</html>

{'repo_name': 'RubyLouvre/avalon.oniui', 'stars': '429', 'repo_language': 'JavaScript', 'file_name': 'avalon.pager.css', 'mime_type': 'text/plain', 'hash': 63807233216412529, 'source_dataset': 'data'}


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: interface.py

from ..input_source import (
    InputSource, FeedInput, QueueInput, StagingInput, DummyConstantInput)
from ..utils import logger

from .config import TrainConfig
from .tower import SingleCostTrainer
from .trainers import SimpleTrainer

__all__ = ['launch_train_with_config', 'apply_default_prefetch']

def apply_default_prefetch(input_source_or_dataflow, trainer):
    """
    Apply a set of default rules to make a fast :class:`InputSource`.

    Args:
        input_source_or_dataflow(InputSource | DataFlow):
        trainer (Trainer):

    Returns:
        InputSource
    """
    if not isinstance(input_source_or_dataflow, InputSource):
        # to mimic same behavior of the old trainer interface
        if type(trainer) == SimpleTrainer:
            input = FeedInput(input_source_or_dataflow)
        else:
            logger.info("Automatically applying QueueInput on the DataFlow.")
            input = QueueInput(input_source_or_dataflow)
    else:
        input = input_source_or_dataflow
    if hasattr(trainer, 'devices'):
        towers = trainer.devices
        if len(towers) > 1:
            # seem to only improve on >1 GPUs
            assert not isinstance(trainer, SimpleTrainer)

            if not isinstance(input, (StagingInput, DummyConstantInput)):
                logger.info("Automatically applying StagingInput on the DataFlow.")
                input = StagingInput(input)
    return input

def launch_train_with_config(config, trainer):
    """
    Train with a :class:`TrainConfig` and a :class:`Trainer`, to
    present a simple training interface. It basically does the following
    3 things (and you can easily do them by yourself if you need more control):

    1. Setup the input with automatic prefetching,
       from `config.data` or `config.dataflow`.
    2. Call `trainer.setup_graph` with the input as well as `config.model`.
    3. Call `trainer.train` with rest of the attributes of config.

    Args:
        config (TrainConfig):
        trainer (Trainer): an instance of :class:`SingleCostTrainer`.

    Examples:

    .. code-block:: python

        launch_train_with_config(
            config, SyncMultiGPUTrainerParameterServer(8, ps_device='gpu'))
    """
    assert isinstance(trainer, SingleCostTrainer), trainer
    assert isinstance(config, TrainConfig), config
    assert config.model is not None
    assert config.dataflow is not None or config.data is not None

    model = config.model
    inputs_desc = model.get_inputs_desc()
    input = config.data or config.dataflow
    input = apply_default_prefetch(input, trainer)

    trainer.setup_graph(
        inputs_desc, input,
        model._build_graph_get_cost, model.get_optimizer)
    trainer.train_with_defaults(
        callbacks=config.callbacks,
        monitors=config.monitors,
        session_creator=config.session_creator,
        session_init=config.session_init,
        steps_per_epoch=config.steps_per_epoch,
        starting_epoch=config.starting_epoch,
        max_epoch=config.max_epoch,
        extra_callbacks=config.extra_callbacks)

{'repo_name': 'wanggrun/Adaptively-Connected-Neural-Networks', 'stars': '145', 'repo_language': 'Python', 'file_name': 'requires.txt', 'mime_type': 'text/plain', 'hash': 8984308269220203802, 'source_dataset': 'data'}


<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="person">
  <p>
   <xsl:value-of select="@given-name"/>
   <xsl:text> </xsl:text>
   <xsl:value-of select="@family-name"/>
  </p>
</xsl:template>
</xsl:stylesheet>

{'repo_name': 'trevorlinton/webkit.js', 'stars': '1804', 'repo_language': 'None', 'file_name': 'ProgramBinary.cpp', 'mime_type': 'text/x-c++', 'hash': 7874234603001531071, 'source_dataset': 'data'}


/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.io.pof.reflect;

import com.tangosol.io.ReadBuffer;

import com.tangosol.io.pof.PofContext;

import java.io.IOException;

/**
* PofArray is a {@link PofValue} implementation for arrays.
*
* @author as  2009.03.06
* @since Coherence 3.5
*/
public class PofArray
        extends ComplexPofValue
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Construct a PofArray instance wrapping the supplied buffer.
    *
    * @param valueParent parent value within the POF stream
    * @param bufValue    buffer containing POF representation of this value
    * @param ctx         POF context to use when reading or writing properties
    * @param of          offset of this value from the beginning of POF stream
    * @param nType       POF type identifier for this value
    * @param ofChildren  offset of the first child element within this value
    * @param cElements   the length of this array
    */
    public PofArray(PofValue valueParent, ReadBuffer bufValue,
                    PofContext ctx, int of, int nType, int ofChildren, int cElements)
        {
        super(valueParent, bufValue, ctx, of, nType, ofChildren);

        m_cElements = cElements;
        }

    // ----- public API -----------------------------------------------------

    /**
    * Return the length of this array.
    *
    * @return the length of this array
    */
    public int getLength()
        {
        return m_cElements;
        }

    // ----- internal -------------------------------------------------------

    /**
    * {@inheritDoc}
    */
    protected PofValue findChildInternal(int nIndex, int ofStart, int iStart)
        {
        ReadBuffer bufValue = getValueBuffer();
        ReadBuffer.BufferInput in = bufValue.getBufferInput();
        in.setOffset(ofStart);

        try
            {
            // check array bounds
            if (nIndex < 0 || nIndex >= getLength())
                {
                throw new IndexOutOfBoundsException(
                        "Element index " + nIndex + " must be in the range [0 .. "
                        + getLength() + ").");
                }

            // skip children until we find the one we are looking for
            int iProp = iStart;
            while (iProp < nIndex)
                {
                skipChild(in);
                iProp++;
                }

            // child found. parse it and return it
            int of = in.getOffset();
            skipChild(in);
            int cb = in.getOffset() - of;

            return extractChild(bufValue, of, cb);
            }
        catch (IOException e)
            {
            throw ensureRuntimeException(e);
            }
        }

    // ----- data members ---------------------------------------------------

    /**
    * The length of this array.
    */
    private int m_cElements;
    }

{'repo_name': 'oracle/coherence', 'stars': '137', 'repo_language': 'Java', 'file_name': 'WrapperMBeanServerBuilder.java', 'mime_type': 'text/x-c', 'hash': -6224957377288694491, 'source_dataset': 'data'}


<?php

namespace Drupal\serialization\Normalizer;

use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper;

/**
 * Converts the Drupal entity object structures to a normalized array.
 *
 * This is the default Normalizer for entities. All formats that have Encoders
 * registered with the Serializer in the DIC will be normalized with this
 * class unless another Normalizer is registered which supersedes it. If a
 * module wants to use format-specific or class-specific normalization, then
 * that module can register a new Normalizer and give it a higher priority than
 * this one.
 */
class ComplexDataNormalizer extends NormalizerBase {

  /**
   * {@inheritdoc}
   */
  protected $supportedInterfaceOrClass = ComplexDataInterface::class;

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = NULL, array $context = []) {
    $attributes = [];
    // $object will not always match $supportedInterfaceOrClass.
    // @see \Drupal\serialization\Normalizer\EntityNormalizer
    // Other normalizers that extend this class may only provide $object that
    // implements \Traversable.
    if ($object instanceof ComplexDataInterface) {
      // If there are no properties to normalize, just normalize the value.
      $object = !empty($object->getProperties(TRUE))
        ? TypedDataInternalPropertiesHelper::getNonInternalProperties($object)
        : $object->getValue();
    }
    /** @var \Drupal\Core\TypedData\TypedDataInterface $property */
    foreach ($object as $name => $property) {
      $attributes[$name] = $this->serializer->normalize($property, $format, $context);
    }
    return $attributes;
  }

}

{'repo_name': 'drupal/drupal', 'stars': '3458', 'repo_language': 'PHP', 'file_name': 'dialog.position.js', 'mime_type': 'text/plain', 'hash': -689150623083808342, 'source_dataset': 'data'}


function mockStk500() {
}

mockStk500.prototype.bootload = function(serialPort, hex, board, callback) {
  callback();
};

module.exports = mockStk500;

{'repo_name': 'noopkat/avrgirl-arduino', 'stars': '344', 'repo_language': 'JavaScript', 'file_name': 'avrgirl-arduino.global.js', 'mime_type': 'text/plain', 'hash': 3222473956257125648, 'source_dataset': 'data'}


// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package exec

import (
	"testing"
)

func BenchmarkExecHostname(b *testing.B) {
	b.ReportAllocs()
	path, err := LookPath("hostname")
	if err != nil {
		b.Fatalf("could not find hostname: %v", err)
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		if err := Command(path).Run(); err != nil {
			b.Fatalf("hostname: %v", err)
		}
	}
}

{'repo_name': 'tailscale/tailscale', 'stars': '2377', 'repo_language': 'Go', 'file_name': 'derper_test.go', 'mime_type': 'text/plain', 'hash': -1210253951353556809, 'source_dataset': 'data'}


# created by tools/tclZIC.tcl - do not edit

set TZData(:Asia/Brunei) {
    {-9223372036854775808 27580 0 LMT}
    {-1383464380 27000 0 BNT}
    {-1167636600 28800 0 BNT}
}

{'repo_name': 'linxid/Machine_Learning_Study_Path', 'stars': '655', 'repo_language': 'Python', 'file_name': 'modules.xml', 'mime_type': 'text/xml', 'hash': 8164129708644829792, 'source_dataset': 'data'}


/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */

#ifndef _NGX_IOCP_MODULE_H_INCLUDED_
#define _NGX_IOCP_MODULE_H_INCLUDED_

typedef struct {
    int  threads;
    int  post_acceptex;
    int  acceptex_read;
} ngx_iocp_conf_t;

extern ngx_module_t  ngx_iocp_module;

#endif /* _NGX_IOCP_MODULE_H_INCLUDED_ */

{'repo_name': 'LomoX-Offical/nginx-openresty-windows', 'stars': '395', 'repo_language': 'C', 'file_name': 'buffer.h', 'mime_type': 'text/x-c', 'hash': 1796747035324755930, 'source_dataset': 'data'}


[remap]

importer="texture"
type="StreamTexture"
path="res://.import/Terrain_icon_base.svg-96d254763c79c9f818ea6155e82e2105.stex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://graphics/images/interface/hud/tod_inspector/Terrain_icon_base.svg"
dest_files=[ "res://.import/Terrain_icon_base.svg-96d254763c79c9f818ea6155e82e2105.stex" ]

[params]

compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=true
flags/anisotropic=true
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

{'repo_name': 'wesnoth/haldric', 'stars': '256', 'repo_language': 'GDScript', 'file_name': 'Magical.tscn', 'mime_type': 'text/plain', 'hash': -3431711541847423655, 'source_dataset': 'data'}